Spaces:
Runtime error
Runtime error
| "use client"; | |
| import { useState, useTransition } from "react"; | |
| import { usePathname, useRouter } from "next/navigation"; | |
| import { Add01Icon, Briefcase01Icon } from "@hugeicons/core-free-icons"; | |
| import type { CaseTypeValue } from "@/lib/constants"; | |
| import { Icon } from "@/components/shared/icon"; | |
| import { Button } from "@/components/ui/button"; | |
| import { | |
| Drawer, | |
| DrawerBody, | |
| DrawerContent, | |
| DrawerDescription, | |
| DrawerFooter, | |
| DrawerHeader, | |
| DrawerTitle, | |
| DrawerTrigger, | |
| } from "@/components/ui/drawer"; | |
| import { Input } from "@/components/ui/input"; | |
| import { Label } from "@/components/ui/label"; | |
| import { | |
| Select, | |
| SelectContent, | |
| SelectItem, | |
| SelectTrigger, | |
| SelectValue, | |
| } from "@/components/ui/select"; | |
| import { Textarea } from "@/components/ui/textarea"; | |
| type CaseCreateFormProps = { | |
| customerId: string; | |
| }; | |
| const initialState = { | |
| caseName: "", | |
| type: "CIVIL" as CaseTypeValue, | |
| subType: "", | |
| opponentFullName: "", | |
| description: "", | |
| }; | |
| export function CaseCreateForm({ customerId }: CaseCreateFormProps) { | |
| const router = useRouter(); | |
| const pathname = usePathname(); | |
| const [open, setOpen] = useState(false); | |
| const [isPending, startTransition] = useTransition(); | |
| const [status, setStatus] = useState<{ | |
| type: "success" | "error"; | |
| message: string; | |
| } | null>(null); | |
| const [formState, setFormState] = useState(initialState); | |
| function updateField<Key extends keyof typeof initialState>( | |
| key: Key, | |
| value: (typeof initialState)[Key], | |
| ) { | |
| setFormState((current) => ({ | |
| ...current, | |
| [key]: value, | |
| })); | |
| } | |
| function handleSubmit(event: React.FormEvent<HTMLFormElement>) { | |
| event.preventDefault(); | |
| setStatus(null); | |
| startTransition(async () => { | |
| const response = await fetch(`/api/customers/${customerId}/cases`, { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/json", | |
| }, | |
| body: JSON.stringify(formState), | |
| }); | |
| const payload = (await response.json().catch(() => null)) as | |
| | { message?: string } | |
| | null; | |
| if (!response.ok) { | |
| setStatus({ | |
| type: "error", | |
| message: payload?.message || "تعذر إنشاء القضية.", | |
| }); | |
| return; | |
| } | |
| setFormState(initialState); | |
| setStatus({ | |
| type: "success", | |
| message: "تم إنشاء القضية بنجاح.", | |
| }); | |
| setOpen(false); | |
| router.replace(`${pathname}?tab=cases`); | |
| router.refresh(); | |
| }); | |
| } | |
| return ( | |
| <Drawer open={open} onOpenChange={setOpen}> | |
| <DrawerTrigger asChild> | |
| <Button> | |
| <span>قضية جديدة</span> | |
| <Icon icon={Briefcase01Icon} size={18} /> | |
| </Button> | |
| </DrawerTrigger> | |
| <DrawerContent> | |
| <DrawerHeader> | |
| <div className="mb-2 flex h-11 w-11 items-center justify-center rounded-2xl bg-[var(--accent-soft)] text-[var(--accent)]"> | |
| <Icon icon={Add01Icon} size={20} /> | |
| </div> | |
| <DrawerTitle>قضية جديدة</DrawerTitle> | |
| <DrawerDescription> | |
| اربط قضية جديدة بالعميل الحالي وسجل بياناتها الأساسية من البداية. | |
| </DrawerDescription> | |
| </DrawerHeader> | |
| <DrawerBody> | |
| <form className="space-y-4" id="create-case-form" onSubmit={handleSubmit}> | |
| <div className="space-y-2"> | |
| <Label htmlFor="case-name">اسم القضية</Label> | |
| <Input | |
| id="case-name" | |
| placeholder="مثال: دعوى نفقة" | |
| value={formState.caseName} | |
| onChange={(event) => updateField("caseName", event.target.value)} | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label>نوع القضية</Label> | |
| <Select | |
| value={formState.type} | |
| onValueChange={(value) => updateField("type", value as CaseTypeValue)} | |
| > | |
| <SelectTrigger> | |
| <SelectValue /> | |
| </SelectTrigger> | |
| <SelectContent> | |
| <SelectItem value="CIVIL">مدنيه</SelectItem> | |
| <SelectItem value="CRIMINAL">جنائيه</SelectItem> | |
| <SelectItem value="PERSONAL_STATUS">أحوال</SelectItem> | |
| </SelectContent> | |
| </Select> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="case-subType">النوع الفرعي</Label> | |
| <Input | |
| id="case-subType" | |
| placeholder="اختياري" | |
| value={formState.subType} | |
| onChange={(event) => updateField("subType", event.target.value)} | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="case-opponent">اسم الخصم بالكامل</Label> | |
| <Input | |
| id="case-opponent" | |
| placeholder="اكتب اسم الخصم" | |
| value={formState.opponentFullName} | |
| onChange={(event) => | |
| updateField("opponentFullName", event.target.value) | |
| } | |
| required | |
| /> | |
| </div> | |
| <div className="space-y-2"> | |
| <Label htmlFor="case-description">وصف مختصر</Label> | |
| <Textarea | |
| id="case-description" | |
| placeholder="اختياري" | |
| value={formState.description} | |
| onChange={(event) => updateField("description", event.target.value)} | |
| /> | |
| </div> | |
| {status ? ( | |
| <p | |
| className={ | |
| status.type === "success" | |
| ? "rounded-2xl bg-[var(--accent-soft)] px-4 py-3 text-sm font-medium text-[var(--accent)]" | |
| : "rounded-2xl bg-[color:rgba(185,28,28,0.08)] px-4 py-3 text-sm font-medium text-[var(--destructive)]" | |
| } | |
| > | |
| {status.message} | |
| </p> | |
| ) : null} | |
| </form> | |
| </DrawerBody> | |
| <DrawerFooter> | |
| <Button type="button" variant="outline" onClick={() => setOpen(false)}> | |
| إلغاء | |
| </Button> | |
| <Button form="create-case-form" disabled={isPending} type="submit"> | |
| <span>{isPending ? "جارٍ الإنشاء..." : "إنشاء القضية"}</span> | |
| <Icon icon={Briefcase01Icon} size={18} /> | |
| </Button> | |
| </DrawerFooter> | |
| </DrawerContent> | |
| </Drawer> | |
| ); | |
| } | |