feat: enhance error handling in forms by introducing FieldError component for consistent error display

This commit is contained in:
Yoga Pangestu 2026-04-22 22:07:58 +07:00
parent beafccf974
commit 703ceefddf
21 changed files with 186 additions and 100 deletions

View File

@ -1,17 +1,64 @@
import type { HTMLAttributes } from 'react'; import type { HTMLAttributes } from 'react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { useMemo } from 'react';
interface InputErrorProps extends HTMLAttributes<HTMLParagraphElement> {
message?: string;
label?: string;
}
export default function InputError({ export default function InputError({
message, message,
label,
className = '', className = '',
...props ...props
}: HTMLAttributes<HTMLParagraphElement> & { message?: string }) { }: InputErrorProps) {
return message ? ( const formattedError = useMemo(() => {
if (!message) return null;
if (!label) return message;
// Preserve all-caps labels (like NIK), otherwise capitalize first letter and lowercase the rest
const isAllOptionsCaps = label === label.toUpperCase() && label.length > 1;
const formattedLabel = isAllOptionsCaps
? label
: label.charAt(0).toUpperCase() + label.slice(1).toLowerCase();
const words = message.split(' ');
// List of common Indonesian and English validation verbs/connectors that follow the attribute
const verbs = [
'wajib', 'harus', 'berupa', 'adalah', 'minimal', 'maksimal', 'tidak', 'kurang', 'lebih', 'antara', 'sudah',
'is', 'must', 'field', 'has', 'was', 'should', 'cannot', 'required', 'invalid'
];
// Find the first occurrence of a verb
let verbIndex = -1;
for (let i = 0; i < words.length; i++) {
if (verbs.includes(words[i].toLowerCase())) {
verbIndex = i;
break;
}
}
if (verbIndex !== -1) {
// Replace everything before the verb with the label
return `${formattedLabel} ${words.slice(verbIndex).join(' ')}`;
}
// Fallback to replacing only the first word if no verb found
if (words.length > 0) {
return `${formattedLabel} ${words.slice(1).join(' ')}`;
}
return message;
}, [message, label]);
return formattedError ? (
<p <p
{...props} {...props}
className={cn('text-sm text-red-600 dark:text-red-400', className)} className={cn('text-sm text-red-600 dark:text-red-400', className)}
> >
{message} {formattedError}
</p> </p>
) : null; ) : null;
} }

View File

@ -184,37 +184,59 @@ function FieldSeparator({
function FieldError({ function FieldError({
className, className,
children, children,
errors, error,
label,
...props ...props
}: React.ComponentProps<"div"> & { }: React.ComponentProps<"div"> & {
errors?: Array<{ message?: string } | undefined> error?: string | string[]
label?: string
}) { }) {
const content = useMemo(() => { const content = useMemo(() => {
if (children) { if (children) {
return children return children
} }
if (!errors?.length) { const rawError = Array.isArray(error) ? error[0] : error
if (!rawError) {
return null return null
} }
const uniqueErrors = [ if (label) {
...new Map(errors.map((error) => [error?.message, error])).values(), const isAllUppercase = label === label.toUpperCase() && label.length > 1
] const formattedLabel = isAllUppercase
? label
: label.charAt(0).toUpperCase() + label.slice(1).toLowerCase()
if (uniqueErrors?.length == 1) { const words = rawError.split(" ")
return uniqueErrors[0]?.message
// List of common Indonesian and English validation verbs/connectors that follow the attribute
const verbs = [
"wajib", "harus", "berupa", "adalah", "minimal", "maksimal", "tidak", "kurang", "lebih", "antara", "sudah",
"is", "must", "field", "has", "was", "should", "cannot", "required", "invalid"
]
// Find the first occurrence of a verb
let verbIndex = -1
for (let i = 0; i < words.length; i++) {
if (verbs.includes(words[i].toLowerCase())) {
verbIndex = i
break
}
}
if (verbIndex !== -1) {
// Replace everything before the verb with the label
// If the first word was "The" or "Isian", we replace them too
return `${formattedLabel} ${words.slice(verbIndex).join(" ")}`
}
// Fallback to replacing only the first word if no verb found
return `${formattedLabel} ${words.slice(1).join(" ")}`
} }
return ( return rawError
<ul className="ml-4 flex list-disc flex-col gap-1"> }, [children, error, label])
{uniqueErrors.map(
(error, index) =>
error?.message && <li key={index}>{error.message}</li>
)}
</ul>
)
}, [children, errors])
if (!content) { if (!content) {
return null return null

View File

@ -6,7 +6,7 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog" } from "@/components/ui/dialog"
import { Field, FieldGroup } from "@/components/ui/field" import { Field, FieldError, FieldGroup } from "@/components/ui/field"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { Expense } from '@/types'; import { Expense } from '@/types';
@ -122,7 +122,7 @@ export function ExpenseFormModal({ isOpen, onClose, expense }: ExpenseFormModalP
placeholder='Contoh: Bayar Listrik' placeholder='Contoh: Bayar Listrik'
maxLength={100} maxLength={100}
/> />
{errors.name && <p className="text-xs text-red-500">{errors.name}</p>} <FieldError error={errors.name} label="Nama" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -140,7 +140,7 @@ export function ExpenseFormModal({ isOpen, onClose, expense }: ExpenseFormModalP
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors.amount && <p className="text-xs text-red-500">{errors.amount}</p>} <FieldError error={errors.amount} label="Nominal" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -179,7 +179,7 @@ export function ExpenseFormModal({ isOpen, onClose, expense }: ExpenseFormModalP
onChange={onImageChange} onChange={onImageChange}
/> />
</div> </div>
{errors.image && <p className="text-xs text-red-500 mt-1">{errors.image}</p>} <FieldError error={errors.image} label="Bukti" className="text-xs mt-1" />
</Field> </Field>
</FieldGroup> </FieldGroup>
<DialogFooter className="mt-6"> <DialogFooter className="mt-6">

View File

@ -1,7 +1,7 @@
import { Head, Link, useForm, router } from '@inertiajs/react'; import { Head, Link, useForm, router } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field"; import { Field, FieldError } from "@/components/ui/field";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import * as orderRoutes from '@/routes/order'; import * as orderRoutes from '@/routes/order';
@ -268,7 +268,7 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
<Field> <Field>
<Label htmlFor='customer_name' className="text-xs text-muted-foreground" required>Pelanggan</Label> <Label htmlFor='customer_name' className="text-xs text-muted-foreground" required>Pelanggan</Label>
<Input id="customer_name" className="h-8 text-xs" value={data.customer_name} onChange={e => setData('customer_name', e.target.value)} placeholder="Nama Pelanggan" /> <Input id="customer_name" className="h-8 text-xs" value={data.customer_name} onChange={e => setData('customer_name', e.target.value)} placeholder="Nama Pelanggan" />
{errors.customer_name && <p className="text-xs text-red-500">{errors.customer_name}</p>} <FieldError error={errors.customer_name} label="Pelanggan" className="text-xs" />
</Field> </Field>
<Field> <Field>
<Label className="text-xs text-muted-foreground" required>Channel</Label> <Label className="text-xs text-muted-foreground" required>Channel</Label>
@ -282,7 +282,7 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{errors.order_channel && <p className="text-xs text-red-500">{errors.order_channel}</p>} <FieldError error={errors.order_channel} label="Channel" className="text-xs" />
</Field> </Field>
</div> </div>
@ -299,7 +299,7 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{errors.payment_method && <p className="text-xs text-red-500">{errors.payment_method}</p>} <FieldError error={errors.payment_method} label="Metode Bayar" className="text-xs" />
</Field> </Field>
<Field> <Field>
<Label className="text-xs text-muted-foreground" required>Status</Label> <Label className="text-xs text-muted-foreground" required>Status</Label>
@ -313,7 +313,7 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{errors.order_status && <p className="text-xs text-red-500">{errors.order_status}</p>} <FieldError error={errors.order_status} label="Status" className="text-xs" />
</Field> </Field>
</div> </div>
@ -338,7 +338,7 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors.discount && <p className="text-xs text-red-500">{errors.discount}</p>} <FieldError error={errors.discount} label="Potongan / Diskon" className="text-xs" />
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import { Head, Link, useForm, router } from '@inertiajs/react'; import { Head, Link, useForm, router } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field"; import { Field, FieldError } from "@/components/ui/field";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import * as orderRoutes from '@/routes/order'; import * as orderRoutes from '@/routes/order';
@ -270,7 +270,7 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
<Field> <Field>
<Label htmlFor='customer_name' className="text-xs text-muted-foreground" required>Pelanggan</Label> <Label htmlFor='customer_name' className="text-xs text-muted-foreground" required>Pelanggan</Label>
<Input id='customer_name' className="h-8 text-xs" value={data.customer_name} onChange={e => setData('customer_name', e.target.value)} /> <Input id='customer_name' className="h-8 text-xs" value={data.customer_name} onChange={e => setData('customer_name', e.target.value)} />
{errors.customer_name && <p className="text-xs text-red-500">{errors.customer_name}</p>} <FieldError error={errors.customer_name} label="Pelanggan" className="text-xs" />
</Field> </Field>
<Field> <Field>
<Label className="text-xs text-muted-foreground" required>Channel</Label> <Label className="text-xs text-muted-foreground" required>Channel</Label>
@ -282,7 +282,7 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{errors.order_channel && <p className="text-xs text-red-500">{errors.order_channel}</p>} <FieldError error={errors.order_channel} label="Channel" className="text-xs" />
</Field> </Field>
</div> </div>
@ -297,7 +297,7 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{errors.payment_method && <p className="text-xs text-red-500">{errors.payment_method}</p>} <FieldError error={errors.payment_method} label="Metode Bayar" className="text-xs" />
</Field> </Field>
<Field> <Field>
<Label className="text-xs text-muted-foreground" required>Status</Label> <Label className="text-xs text-muted-foreground" required>Status</Label>
@ -309,7 +309,7 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{errors.order_status && <p className="text-xs text-red-500">{errors.order_status}</p>} <FieldError error={errors.order_status} label="Status" className="text-xs" />
</Field> </Field>
</div> </div>
@ -335,7 +335,7 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
autoComplete='off' autoComplete='off'
/> />
</div> </div>
{errors.discount && <p className="text-xs text-red-500">{errors.discount}</p>} <FieldError error={errors.discount} label="Potongan / Diskon" className="text-xs" />
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import { Head, Link, useForm, router } from '@inertiajs/react'; import { Head, Link, useForm, router } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field"; import { Field, FieldError } from "@/components/ui/field";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import purchaseRoutes from '@/routes/purchase'; import purchaseRoutes from '@/routes/purchase';
@ -272,11 +272,13 @@ export default function PurchaseCreate({ products, cartItems }: { products: Prod
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
<FieldError error={errors.purchase_date} label="Tanggal" className="text-xs" />
</Field> </Field>
<Field> <Field>
<Label htmlFor='note' className="text-xs text-muted-foreground">Catatan</Label> <Label htmlFor='note' className="text-xs text-muted-foreground">Catatan</Label>
<Input id='note' className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." /> <Input id='note' className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." />
<FieldError error={errors.note} label="Catatan" className="text-xs" />
</Field> </Field>
<div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between"> <div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between">
@ -577,6 +579,7 @@ export default function PurchaseCreate({ products, cartItems }: { products: Prod
<Field> <Field>
<Label htmlFor="note" className="text-xs text-muted-foreground">Catatan</Label> <Label htmlFor="note" className="text-xs text-muted-foreground">Catatan</Label>
<Input id="note" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." /> <Input id="note" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." />
<FieldError error={errors.note} label="Catatan" className="text-xs" />
</Field> </Field>
<div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between"> <div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between">
@ -752,6 +755,7 @@ export default function PurchaseCreate({ products, cartItems }: { products: Prod
<Field> <Field>
<Label htmlFor="note_mobile" className="text-xs text-muted-foreground">Catatan</Label> <Label htmlFor="note_mobile" className="text-xs text-muted-foreground">Catatan</Label>
<Input id="note_mobile" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." /> <Input id="note_mobile" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." />
<FieldError error={errors.note} label="Catatan" className="text-xs" />
</Field> </Field>
<div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between"> <div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between">

View File

@ -1,7 +1,7 @@
import { Head, Link, useForm, router } from '@inertiajs/react'; import { Head, Link, useForm, router } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field"; import { Field, FieldError } from "@/components/ui/field";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import purchaseRoutes from '@/routes/purchase'; import purchaseRoutes from '@/routes/purchase';
@ -276,11 +276,13 @@ export default function PurchaseEdit({ purchase, products }: { purchase: Purchas
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
<FieldError error={errors.purchase_date} label="Tanggal" className="text-xs" />
</Field> </Field>
<Field> <Field>
<Label htmlFor='note' className="text-xs text-muted-foreground">Catatan</Label> <Label htmlFor='note' className="text-xs text-muted-foreground">Catatan</Label>
<Input id='note' className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." /> <Input id='note' className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." />
<FieldError error={errors.note} label="Catatan" className="text-xs" />
</Field> </Field>
<div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between"> <div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between">
@ -576,11 +578,13 @@ export default function PurchaseEdit({ purchase, products }: { purchase: Purchas
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
<FieldError error={errors.purchase_date} label="Tanggal" className="text-xs" />
</Field> </Field>
<Field> <Field>
<Label htmlFor="note" className="text-xs text-muted-foreground">Catatan</Label> <Label htmlFor="note" className="text-xs text-muted-foreground">Catatan</Label>
<Input id="note" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." /> <Input id="note" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." />
<FieldError error={errors.note} label="Catatan" className="text-xs" />
</Field> </Field>
<div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between"> <div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between">
@ -756,6 +760,7 @@ export default function PurchaseEdit({ purchase, products }: { purchase: Purchas
<Field> <Field>
<Label htmlFor="note_mobile" className="text-xs text-muted-foreground">Catatan</Label> <Label htmlFor="note_mobile" className="text-xs text-muted-foreground">Catatan</Label>
<Input id="note_mobile" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." /> <Input id="note_mobile" className="h-8 text-xs" value={data.note} onChange={e => setData('note', e.target.value)} placeholder="...." />
<FieldError error={errors.note} label="Catatan" className="text-xs" />
</Field> </Field>
<div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between"> <div className="rounded-xl bg-primary/10 border border-primary/20 p-3 flex items-center justify-between">

View File

@ -6,7 +6,7 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog" } from "@/components/ui/dialog"
import { Field, FieldGroup } from "@/components/ui/field" import { Field, FieldError, FieldGroup } from "@/components/ui/field"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { Category } from '@/types'; import { Category } from '@/types';
@ -85,7 +85,7 @@ export function CategoryFormModal({ isOpen, onClose, category }: CategoryFormMod
placeholder='Contoh: Gamis' placeholder='Contoh: Gamis'
maxLength={50} maxLength={50}
/> />
{errors.name && <p className="text-xs text-red-500">{errors.name}</p>} <FieldError error={errors.name} label="Nama" className="text-xs" />
</Field> </Field>
</FieldGroup> </FieldGroup>
<DialogFooter className="mt-6"> <DialogFooter className="mt-6">

View File

@ -2,7 +2,7 @@ import { Head, Link } from '@inertiajs/react';
import { useForm } from '@inertiajs/react'; import { useForm } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field" import { Field, FieldError } from "@/components/ui/field"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import productRoutes from '@/routes/product'; import productRoutes from '@/routes/product';
@ -143,7 +143,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
placeholder='Contoh: Gamis Wanita' placeholder='Contoh: Gamis Wanita'
maxLength={100} maxLength={100}
/> />
{errors.name && <p className="text-xs text-red-500">{errors.name}</p>} <FieldError error={errors.name} label="Nama" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -185,7 +185,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
</ComboboxList> </ComboboxList>
</ComboboxContent> </ComboboxContent>
</Combobox> </Combobox>
{errors.category_ids && <p className="text-xs text-red-500 mt-1">{errors.category_ids}</p>} <FieldError error={errors.category_ids} label="Kategori" className="text-xs mt-1" />
</Field> </Field>
<Field> <Field>
@ -194,7 +194,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
value={data.description} value={data.description}
onChange={(val) => setData('description', val)} onChange={(val) => setData('description', val)}
/> />
{errors.description && <p className="text-xs text-red-500 mt-1">{errors.description}</p>} <FieldError error={errors.description} label="Deskripsi" className="text-xs mt-1" />
</Field> </Field>
</CardContent> </CardContent>
</Card> </Card>
@ -223,7 +223,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.purchase'] && <p className="text-xs text-red-500">{errors['prices.purchase']}</p>} <FieldError error={errors['prices.purchase']} label="Harga Beli" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -244,7 +244,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.distributor'] && <p className="text-xs text-red-500">{errors['prices.distributor']}</p>} <FieldError error={errors['prices.distributor']} label="Harga Distributor" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -265,7 +265,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.agent'] && <p className="text-xs text-red-500">{errors['prices.agent']}</p>} <FieldError error={errors['prices.agent']} label="Harga Agen" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -286,7 +286,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.reseller'] && <p className="text-xs text-red-500">{errors['prices.reseller']}</p>} <FieldError error={errors['prices.reseller']} label="Harga Reseller" className="text-xs" />
</Field> </Field>
<Field className="md:col-span-2"> <Field className="md:col-span-2">
@ -307,7 +307,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.retail'] && <p className="text-xs text-red-500">{errors['prices.retail']}</p>} <FieldError error={errors['prices.retail']} label="Harga Retail" className="text-xs" />
</Field> </Field>
</div> </div>
</CardContent> </CardContent>
@ -353,7 +353,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
className="hidden" className="hidden"
onChange={handleThumbnailChange} onChange={handleThumbnailChange}
/> />
{errors.thumbnail && <p className="text-xs text-red-500 mt-2">{errors.thumbnail}</p>} <FieldError error={errors.thumbnail} label="Thumbnail" className="text-xs mt-2" />
</CardContent> </CardContent>
</Card> </Card>
@ -397,7 +397,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
className="hidden" className="hidden"
onChange={handleImagesChange} onChange={handleImagesChange}
/> />
{errors['images'] && <p className="text-xs text-red-500">{errors['images']}</p>} <FieldError error={errors['images']} label="Galeri Gambar" className="text-xs" />
</CardContent> </CardContent>
</Card> </Card>

View File

@ -3,7 +3,7 @@ import type { Product, ProductPrice } from '@/types';
import { Category } from '@/types/category'; import { Category } from '@/types/category';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field" import { Field, FieldError } from "@/components/ui/field"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { toast } from 'sonner'; import { toast } from 'sonner';
@ -194,7 +194,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
placeholder='Contoh: Gamis Wanita' placeholder='Contoh: Gamis Wanita'
maxLength={100} maxLength={100}
/> />
{errors.name && <p className="text-xs text-red-500">{errors.name}</p>} <FieldError error={errors.name} label="Nama" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -209,7 +209,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
placeholder="0" placeholder="0"
autoComplete='off' autoComplete='off'
/> />
{errors.stock && <p className="text-xs text-red-500">{errors.stock}</p>} <FieldError error={errors.stock} label="Stok" className="text-xs" />
</Field> </Field>
</div> </div>
@ -252,7 +252,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
</ComboboxList> </ComboboxList>
</ComboboxContent> </ComboboxContent>
</Combobox> </Combobox>
{errors.category_ids && <p className="text-xs text-red-500 mt-1">{errors.category_ids}</p>} <FieldError error={errors.category_ids} label="Kategori" className="text-xs mt-1" />
</Field> </Field>
<Field> <Field>
@ -261,7 +261,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
value={data.description} value={data.description}
onChange={(val) => setData('description', val)} onChange={(val) => setData('description', val)}
/> />
{errors.description && <p className="text-xs text-red-500 mt-1">{errors.description}</p>} <FieldError error={errors.description} label="Deskripsi" className="text-xs mt-1" />
</Field> </Field>
</CardContent> </CardContent>
</Card> </Card>
@ -290,7 +290,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.purchase'] && <p className="text-xs text-red-500">{errors['prices.purchase']}</p>} <FieldError error={errors['prices.purchase']} label="Harga Beli" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -311,7 +311,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.distributor'] && <p className="text-xs text-red-500">{errors['prices.distributor']}</p>} <FieldError error={errors['prices.distributor']} label="Harga Distributor" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -332,7 +332,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.agent'] && <p className="text-xs text-red-500">{errors['prices.agent']}</p>} <FieldError error={errors['prices.agent']} label="Harga Agen" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -353,7 +353,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.reseller'] && <p className="text-xs text-red-500">{errors['prices.reseller']}</p>} <FieldError error={errors['prices.reseller']} label="Harga Reseller" className="text-xs" />
</Field> </Field>
<Field className="md:col-span-2"> <Field className="md:col-span-2">
@ -374,7 +374,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors['prices.retail'] && <p className="text-xs text-red-500">{errors['prices.retail']}</p>} <FieldError error={errors['prices.retail']} label="Harga Retail" className="text-xs" />
</Field> </Field>
</div> </div>
</CardContent> </CardContent>
@ -420,7 +420,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
className="hidden" className="hidden"
onChange={handleThumbnailChange} onChange={handleThumbnailChange}
/> />
{errors.thumbnail && <p className="text-xs text-red-500 mt-2">{errors.thumbnail}</p>} <FieldError error={errors.thumbnail} label="Thumbnail" className="text-xs mt-2" />
</CardContent> </CardContent>
</Card> </Card>
@ -464,7 +464,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
className="hidden" className="hidden"
onChange={handleImagesChange} onChange={handleImagesChange}
/> />
{errors['images'] && <p className="text-xs text-red-500">{errors['images']}</p>} <FieldError error={errors['images']} label="Galeri Gambar" className="text-xs" />
</CardContent> </CardContent>
</Card> </Card>

View File

@ -2,7 +2,7 @@ import { Head, Link } from '@inertiajs/react';
import { useForm } from '@inertiajs/react'; import { useForm } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field" import { Field, FieldError } from "@/components/ui/field"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import userRoutes from '@/routes/user'; import userRoutes from '@/routes/user';
@ -77,7 +77,7 @@ export default function UserCreate() {
autoComplete='off' autoComplete='off'
placeholder='Contoh: John Doe' placeholder='Contoh: John Doe'
/> />
{errors.full_name && <p className="text-xs text-red-500">{errors.full_name}</p>} <FieldError error={errors.full_name} label="Nama Lengkap" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -91,7 +91,7 @@ export default function UserCreate() {
placeholder='Contoh: 3213051307900001' placeholder='Contoh: 3213051307900001'
maxLength={16} maxLength={16}
/> />
{errors.nik && <p className="text-xs text-red-500">{errors.nik}</p>} <FieldError error={errors.nik} label="NIK" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -104,7 +104,7 @@ export default function UserCreate() {
autoComplete='off' autoComplete='off'
placeholder='Contoh: 08123456789' placeholder='Contoh: 08123456789'
/> />
{errors.phone_number && <p className="text-xs text-red-500">{errors.phone_number}</p>} <FieldError error={errors.phone_number} label="Nomor Telepon" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -122,7 +122,7 @@ export default function UserCreate() {
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors.base_salary && <p className="text-xs text-red-500">{errors.base_salary}</p>} <FieldError error={errors.base_salary} label="Gaji Pokok" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -135,7 +135,7 @@ export default function UserCreate() {
autoComplete='off' autoComplete='off'
placeholder='Contoh: Jakarta' placeholder='Contoh: Jakarta'
/> />
{errors.birth_place && <p className="text-xs text-red-500">{errors.birth_place}</p>} <FieldError error={errors.birth_place} label="Tempat Lahir" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -175,14 +175,14 @@ export default function UserCreate() {
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
{errors.birth_date && <p className="text-xs text-red-500">{errors.birth_date}</p>} <FieldError error={errors.birth_date} label="Tanggal Lahir" className="text-xs" />
</Field> </Field>
</div> </div>
<Field> <Field>
<Label htmlFor="address" required>Alamat</Label> <Label htmlFor="address" required>Alamat</Label>
<Textarea id='address' name='address' value={data.address} onChange={e => setData('address', e.target.value)} placeholder='Contoh: Kp. Bakan Sampeu' /> <Textarea id='address' name='address' value={data.address} onChange={e => setData('address', e.target.value)} placeholder='Contoh: Kp. Bakan Sampeu' />
{errors.address && <p className="text-xs text-red-500">{errors.address}</p>} <FieldError error={errors.address} label="Alamat" className="text-xs" />
</Field> </Field>
</CardContent> </CardContent>
</Card> </Card>
@ -205,7 +205,7 @@ export default function UserCreate() {
autoComplete='off' autoComplete='off'
placeholder='Contoh: john@example.com' placeholder='Contoh: john@example.com'
/> />
{errors.email && <p className="text-xs text-red-500">{errors.email}</p>} <FieldError error={errors.email} label="Alamat Surel" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -218,7 +218,7 @@ export default function UserCreate() {
autoComplete='off' autoComplete='off'
placeholder='Contoh: johndoe' placeholder='Contoh: johndoe'
/> />
{errors.username && <p className="text-xs text-red-500">{errors.username}</p>} <FieldError error={errors.username} label="Nama Pengguna" className="text-xs" />
</Field> </Field>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -2,7 +2,7 @@ import { Head, Link } from '@inertiajs/react';
import { useForm } from '@inertiajs/react'; import { useForm } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field" import { Field, FieldError } from "@/components/ui/field"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import userRoutes from '@/routes/user'; import userRoutes from '@/routes/user';
@ -79,7 +79,7 @@ export default function UserEdit({ user }: { user: any }) {
placeholder='Contoh: 3213051307900001' placeholder='Contoh: 3213051307900001'
maxLength={16} maxLength={16}
/> />
{errors.nik && <p className="text-xs text-red-500">{errors.nik}</p>} <FieldError error={errors.nik} label="NIK" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -92,7 +92,7 @@ export default function UserEdit({ user }: { user: any }) {
autoComplete='off' autoComplete='off'
placeholder='Contoh: John Doe' placeholder='Contoh: John Doe'
/> />
{errors.full_name && <p className="text-xs text-red-500">{errors.full_name}</p>} <FieldError error={errors.full_name} label="Nama Lengkap" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -105,7 +105,7 @@ export default function UserEdit({ user }: { user: any }) {
autoComplete='off' autoComplete='off'
placeholder='Contoh: 08123456789' placeholder='Contoh: 08123456789'
/> />
{errors.phone_number && <p className="text-xs text-red-500">{errors.phone_number}</p>} <FieldError error={errors.phone_number} label="Nomor Telepon" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -123,7 +123,7 @@ export default function UserEdit({ user }: { user: any }) {
placeholder="Rp 0" placeholder="Rp 0"
autoComplete='off' autoComplete='off'
/> />
{errors.base_salary && <p className="text-xs text-red-500">{errors.base_salary}</p>} <FieldError error={errors.base_salary} label="Gaji Pokok" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -136,7 +136,7 @@ export default function UserEdit({ user }: { user: any }) {
autoComplete='off' autoComplete='off'
placeholder='Contoh: Jakarta' placeholder='Contoh: Jakarta'
/> />
{errors.birth_place && <p className="text-xs text-red-500">{errors.birth_place}</p>} <FieldError error={errors.birth_place} label="Tempat Lahir" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -176,14 +176,14 @@ export default function UserEdit({ user }: { user: any }) {
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>
{errors.birth_date && <p className="text-xs text-red-500">{errors.birth_date}</p>} <FieldError error={errors.birth_date} label="Tanggal Lahir" className="text-xs" />
</Field> </Field>
</div> </div>
<Field> <Field>
<Label htmlFor="address" required>Alamat</Label> <Label htmlFor="address" required>Alamat</Label>
<Textarea id='address' name='address' value={data.address} onChange={e => setData('address', e.target.value)} placeholder='Contoh: Kp. Bakan Sampeu' /> <Textarea id='address' name='address' value={data.address} onChange={e => setData('address', e.target.value)} placeholder='Contoh: Kp. Bakan Sampeu' />
{errors.address && <p className="text-xs text-red-500">{errors.address}</p>} <FieldError error={errors.address} label="Alamat" className="text-xs" />
</Field> </Field>
</CardContent> </CardContent>
</Card> </Card>
@ -206,7 +206,7 @@ export default function UserEdit({ user }: { user: any }) {
autoComplete='off' autoComplete='off'
placeholder='Contoh: john@example.com' placeholder='Contoh: john@example.com'
/> />
{errors.email && <p className="text-xs text-red-500">{errors.email}</p>} <FieldError error={errors.email} label="Alamat Surel" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -219,7 +219,7 @@ export default function UserEdit({ user }: { user: any }) {
autoComplete='off' autoComplete='off'
placeholder='Contoh: johndoe' placeholder='Contoh: johndoe'
/> />
{errors.username && <p className="text-xs text-red-500">{errors.username}</p>} <FieldError error={errors.username} label="Nama Pengguna" className="text-xs" />
</Field> </Field>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -1,7 +1,7 @@
import { Head, useForm } from '@inertiajs/react'; import { Head, useForm } from '@inertiajs/react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Field } from "@/components/ui/field" import { Field, FieldError } from "@/components/ui/field"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
@ -96,7 +96,7 @@ export default function SettingIndex({ setting }: { setting: GeneralSetting | nu
placeholder='Contoh: VN Grup Dress' placeholder='Contoh: VN Grup Dress'
maxLength={100} maxLength={100}
/> />
{errors.name && <p className="text-xs text-red-500">{errors.name}</p>} <FieldError error={errors.name} label="Nama Aplikasi" className="text-xs" />
</Field> </Field>
<Field> <Field>
@ -108,7 +108,7 @@ export default function SettingIndex({ setting }: { setting: GeneralSetting | nu
placeholder="Deskripsi singkat aplikasi" placeholder="Deskripsi singkat aplikasi"
rows={4} rows={4}
/> />
{errors.description && <p className="text-xs text-red-500 mt-1">{errors.description}</p>} <FieldError error={errors.description} label="Deskripsi" className="text-xs mt-1" />
</Field> </Field>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
@ -120,7 +120,7 @@ export default function SettingIndex({ setting }: { setting: GeneralSetting | nu
onChange={(e) => setData('phone', e.target.value)} onChange={(e) => setData('phone', e.target.value)}
placeholder="0812xxxx" placeholder="0812xxxx"
/> />
{errors.phone && <p className="text-xs text-red-500">{errors.phone}</p>} <FieldError error={errors.phone} label="No. Telepon" className="text-xs" />
</Field> </Field>
</div> </div>
@ -133,7 +133,7 @@ export default function SettingIndex({ setting }: { setting: GeneralSetting | nu
placeholder="Alamat lengkap toko" placeholder="Alamat lengkap toko"
rows={3} rows={3}
/> />
{errors.address && <p className="text-xs text-red-500 mt-1">{errors.address}</p>} <FieldError error={errors.address} label="Alamat" className="text-xs mt-1" />
</Field> </Field>
</CardContent> </CardContent>
</Card> </Card>
@ -178,7 +178,7 @@ export default function SettingIndex({ setting }: { setting: GeneralSetting | nu
className="hidden" className="hidden"
onChange={handleLogoChange} onChange={handleLogoChange}
/> />
{errors.logo && <p className="text-xs text-red-500 mt-2">{errors.logo}</p>} <FieldError error={errors.logo} label="Logo Aplikasi" className="text-xs mt-2" />
</CardContent> </CardContent>
</Card> </Card>
@ -222,7 +222,7 @@ export default function SettingIndex({ setting }: { setting: GeneralSetting | nu
className="hidden" className="hidden"
onChange={handleIconChange} onChange={handleIconChange}
/> />
{errors.icon && <p className="text-xs text-red-500 mt-2">{errors.icon}</p>} <FieldError error={errors.icon} label="Favicon / Icon" className="text-xs mt-2" />
</CardContent> </CardContent>
</Card> </Card>

View File

@ -24,7 +24,7 @@ export default function ConfirmPassword() {
autoFocus autoFocus
/> />
<InputError message={errors.password} /> <InputError message={errors.password} label="Password" />
</div> </div>
<div className="flex items-center"> <div className="flex items-center">

View File

@ -35,7 +35,7 @@ export default function ForgotPassword({ status }: { status?: string }) {
placeholder="email@example.com" placeholder="email@example.com"
/> />
<InputError message={errors.email} /> <InputError message={errors.email} label="Email address" />
</div> </div>
<div className="my-6 flex items-center justify-start"> <div className="my-6 flex items-center justify-start">

View File

@ -39,7 +39,7 @@ export default function Login({
autoComplete="off" autoComplete="off"
placeholder="johndoe@example.com atau johndoe" placeholder="johndoe@example.com atau johndoe"
/> />
<InputError message={errors.login} /> <InputError message={errors.login} label="Alamat surel atau nama pengguna" />
</div> </div>
<div className="grid gap-2"> <div className="grid gap-2">
@ -54,7 +54,7 @@ export default function Login({
autoComplete="off" autoComplete="off"
placeholder="********" placeholder="********"
/> />
<InputError message={errors.password} /> <InputError message={errors.password} label="Kata sandi" />
</div> </div>
<div className="flex items-center space-x-3"> <div className="flex items-center space-x-3">

View File

@ -36,6 +36,7 @@ export default function Register() {
/> />
<InputError <InputError
message={errors.name} message={errors.name}
label="Name"
className="mt-2" className="mt-2"
/> />
</div> </div>
@ -51,7 +52,7 @@ export default function Register() {
name="email" name="email"
placeholder="email@example.com" placeholder="email@example.com"
/> />
<InputError message={errors.email} /> <InputError message={errors.email} label="Email address" />
</div> </div>
<div className="grid gap-2"> <div className="grid gap-2">
@ -64,7 +65,7 @@ export default function Register() {
name="password" name="password"
placeholder="Password" placeholder="Password"
/> />
<InputError message={errors.password} /> <InputError message={errors.password} label="Password" />
</div> </div>
<div className="grid gap-2"> <div className="grid gap-2">
@ -81,6 +82,7 @@ export default function Register() {
/> />
<InputError <InputError
message={errors.password_confirmation} message={errors.password_confirmation}
label="Confirm password"
/> />
</div> </div>

View File

@ -37,6 +37,7 @@ export default function ResetPassword({ token, email }: Props) {
/> />
<InputError <InputError
message={errors.email} message={errors.email}
label="Email"
className="mt-2" className="mt-2"
/> />
</div> </div>
@ -51,7 +52,7 @@ export default function ResetPassword({ token, email }: Props) {
autoFocus autoFocus
placeholder="Password" placeholder="Password"
/> />
<InputError message={errors.password} /> <InputError message={errors.password} label="Password" />
</div> </div>
<div className="grid gap-2"> <div className="grid gap-2">
@ -67,6 +68,7 @@ export default function ResetPassword({ token, email }: Props) {
/> />
<InputError <InputError
message={errors.password_confirmation} message={errors.password_confirmation}
label="Confirm password"
className="mt-2" className="mt-2"
/> />
</div> </div>

View File

@ -73,6 +73,7 @@ export default function TwoFactorChallenge() {
/> />
<InputError <InputError
message={errors.recovery_code} message={errors.recovery_code}
label="Recovery code"
/> />
</> </>
) : ( ) : (
@ -99,7 +100,7 @@ export default function TwoFactorChallenge() {
</InputOTPGroup> </InputOTPGroup>
</InputOTP> </InputOTP>
</div> </div>
<InputError message={errors.code} /> <InputError message={errors.code} label="Code" />
</div> </div>
)} )}

View File

@ -56,6 +56,7 @@ export default function Profile({
<InputError <InputError
className="mt-2" className="mt-2"
message={errors.name} message={errors.name}
label="Name"
/> />
</div> </div>
@ -76,6 +77,7 @@ export default function Profile({
<InputError <InputError
className="mt-2" className="mt-2"
message={errors.email} message={errors.email}
label="Email address"
/> />
</div> </div>

View File

@ -100,7 +100,7 @@ export default function Security({
placeholder="Current password" placeholder="Current password"
/> />
<InputError message={errors.current_password} /> <InputError message={errors.current_password} label="Current password" />
</div> </div>
<div className="grid gap-2"> <div className="grid gap-2">
@ -115,7 +115,7 @@ export default function Security({
placeholder="New password" placeholder="New password"
/> />
<InputError message={errors.password} /> <InputError message={errors.password} label="New password" />
</div> </div>
<div className="grid gap-2"> <div className="grid gap-2">
@ -133,6 +133,7 @@ export default function Security({
<InputError <InputError
message={errors.password_confirmation} message={errors.password_confirmation}
label="Confirm password"
/> />
</div> </div>