"use client" import { AlertTriangle, Plus, Save } from "lucide-react" import { Button } from "@/shared/components/ui/button" import { Alert, AlertTitle } from "@/shared/components/ui/alert" import { FieldGroup } from "@/shared/components/ui/field" import { Rhform, RhfTextField, RhfTextareaField, RhfSelectField, RhfAsyncSelectField, RhfDateField, } from "@/shared/components/form" import { toast } from "sonner" import { useAuthApi } from "@/shared/useApi" import { useResourceForm } from "@/shared/hooks/use-resource-form" import { useFormMutation } from "@/shared/hooks/use-form-mutation" import { toRelation, toId } from "@/shared/lib/utils" import { taskFormSchema, type TaskFormValues } from "./task.schema" import { TASK_ROUTES, TASK_TYPE_ROUTES, TASK_SECTION_ROUTES, EMPLOYEE_ROUTES, DEPARTMENT_ROUTES, JOB_CARD_ROUTES } from "@garage/api" import { TaskStatus, TaskPriority } from "@garage/api" import { TaskTypeCrudDialog } from "./task-type-crud-dialog" import { TaskSectionCrudDialog } from "./task-section-crud-dialog" // ── Constants ── const STATUS_OPTIONS = TaskStatus.map((s) => ({ value: s, label: s.charAt(0).toUpperCase() + s.slice(1), })) const PRIORITY_OPTIONS = TaskPriority.map((p,i) => ({ value: i, label: p.charAt(0).toUpperCase() + p.slice(1), })) const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) => o.label } // ── Props ── export type TaskFormProps = { resourceId?: string | null initialData?: unknown onSuccess?: () => void } // ── Default values ── const DEFAULT_VALUES: TaskFormValues = { subject: "", description: "", task_type: null, task_section: null, owner: null, department: null, priority: "medium", due_date: "", status: "pending", job_card: null, } // ── Mapping helpers ── function mapToFormValues(data: unknown): TaskFormValues { const d = (data as any)?.data ?? data ?? {} return { subject: d.subject || "", description: d.description || "", task_type: toRelation(d.task_type_id, d.task_type?.title), task_section: toRelation(d.task_section_id, d.task_section?.title), owner: toRelation( d.owner_id, d.owner ? `${d.owner.first_name ?? ""} ${d.owner.last_name ?? ""}`.trim() : undefined, ), department: toRelation(d.department_id, d.department?.name), priority: d.priority || "medium", due_date: d.due_date ? d.due_date.split("T")[0] : "", status: d.status || "pending", job_card: toRelation(d.job_card_id, d.job_card?.title), } } function mapFormToPayload(values: TaskFormValues) { return { subject: values.subject, description: values.description || undefined, task_type_id: toId(values.task_type), task_section_id: toId(values.task_section), owner_id: toId(values.owner), department_id: toId(values.department), priority: values.priority || undefined, due_date: values.due_date || undefined, status: values.status || undefined, job_card_id: toId(values.job_card), } } // ── Component ── export function TaskForm({ resourceId, initialData, onSuccess }: TaskFormProps) { const api = useAuthApi() const { form, isEditing } = useResourceForm({ schema: taskFormSchema, defaultValues: DEFAULT_VALUES, resourceId, initialData, mapToFormValues, queryKey: [TASK_ROUTES.BY_ID, resourceId], }) const { mutate, error, isPending } = useFormMutation(form, { mutationFn: (values: TaskFormValues) => { const payload = mapFormToPayload(values) const promise = isEditing && resourceId ? api.tasks.update(resourceId, payload as any) : api.tasks.create(payload as any) toast.promise(promise, { loading: isEditing ? "Updating task..." : "Creating task...", success: isEditing ? "Task updated successfully" : "Task created successfully", error: isEditing ? "Failed to update task" : "Failed to create task", }) return promise }, onSuccess: () => { form.reset() onSuccess?.() }, }) return ( mutate(values)} className="space-y-6"> {error && ( {isEditing ? "Failed to update task" : "Failed to create task"} )}
{/* Task Type with inline CRUD */}
Task Type
api.taskTypes.list()} mapOption={(item: any) => ({ value: String(item.id), label: item.title })} {...STORE_OBJECT} />
{/* Task Section with inline CRUD */}
Task Section
api.taskSections.list()} mapOption={(item: any) => ({ value: String(item.id), label: item.title })} {...STORE_OBJECT} />
api.employees.list()} mapOption={(item: any) => ({ value: String(item.id), label: `${item.first_name ?? ""} ${item.last_name ?? ""}`.trim(), })} {...STORE_OBJECT} /> api.departments.list()} mapOption={(item: any) => ({ value: String(item.id), label: item.name })} {...STORE_OBJECT} />
api.jobCards.list()} mapOption={(item: any) => ({ value: String(item.id), label: item.title || `#${item.id}`, })} {...STORE_OBJECT} />
) }