From dfdfae3018f8499240f48d28ce634f4a5c56e006 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Wed, 2 Apr 2025 09:54:08 +0000
Subject: 벤더 코멘트 처리
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../table/update-investigation-sheet.tsx           | 324 +++++++++++++++++++++
 1 file changed, 324 insertions(+)
 create mode 100644 lib/vendor-investigation/table/update-investigation-sheet.tsx

(limited to 'lib/vendor-investigation/table/update-investigation-sheet.tsx')

diff --git a/lib/vendor-investigation/table/update-investigation-sheet.tsx b/lib/vendor-investigation/table/update-investigation-sheet.tsx
new file mode 100644
index 00000000..fe30c892
--- /dev/null
+++ b/lib/vendor-investigation/table/update-investigation-sheet.tsx
@@ -0,0 +1,324 @@
+"use client"
+
+import * as React from "react"
+import { zodResolver } from "@hookform/resolvers/zod"
+import { useForm } from "react-hook-form"
+import { Loader } from "lucide-react"
+import { toast } from "sonner"
+
+import { Button } from "@/components/ui/button"
+import {
+  Form,
+  FormControl,
+  FormField,
+  FormItem,
+  FormLabel,
+  FormMessage,
+} from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+import {
+  Sheet,
+  SheetClose,
+  SheetContent,
+  SheetDescription,
+  SheetFooter,
+  SheetHeader,
+  SheetTitle,
+} from "@/components/ui/sheet"
+import {
+  Select,
+  SelectContent,
+  SelectGroup,
+  SelectItem,
+  SelectTrigger,
+  SelectValue,
+} from "@/components/ui/select"
+
+import {
+  updateVendorInvestigationSchema,
+  type UpdateVendorInvestigationSchema,
+} from "../validations"
+import { updateVendorInvestigationAction } from "../service"
+import { VendorInvestigationsViewWithContacts } from "@/config/vendorInvestigationsColumnsConfig"
+
+/** 
+ * The shape of `vendorInvestigation` 
+ * might come from your `vendorInvestigationsView` row 
+ * or your existing type for a single investigation.
+ */
+
+interface UpdateVendorInvestigationSheetProps
+  extends React.ComponentPropsWithoutRef<typeof Sheet> {
+  investigation: VendorInvestigationsViewWithContacts | null
+}
+
+/**
+ * A sheet for updating a vendor investigation (plus optional attachments).
+ */
+export function UpdateVendorInvestigationSheet({
+  investigation,
+  ...props
+}: UpdateVendorInvestigationSheetProps) {
+  const [isPending, startTransition] = React.useTransition()
+
+  // RHF + Zod
+  const form = useForm<UpdateVendorInvestigationSchema>({
+    resolver: zodResolver(updateVendorInvestigationSchema),
+    defaultValues: {
+      investigationId: investigation?.investigationId ?? 0,
+      investigationStatus: investigation?.investigationStatus ?? "PLANNED",
+      scheduledStartAt: investigation?.scheduledStartAt ?? undefined,
+      scheduledEndAt: investigation?.scheduledEndAt ?? undefined,
+      completedAt: investigation?.completedAt ?? undefined,
+      investigationNotes: investigation?.investigationNotes ?? "",
+    },
+  })
+
+  React.useEffect(() => {
+    if (investigation) {
+      form.reset({
+        investigationId: investigation.investigationId,
+        investigationStatus: investigation.investigationStatus || "PLANNED",
+        scheduledStartAt: investigation.scheduledStartAt ?? undefined,
+        scheduledEndAt: investigation.scheduledEndAt ?? undefined,
+        completedAt: investigation.completedAt ?? undefined,
+        investigationNotes: investigation.investigationNotes ?? "",
+      })
+    }
+  }, [investigation, form])
+
+  // Format date for form data
+  const formatDateForFormData = (date: Date | undefined): string | null => {
+    if (!date) return null;
+    return date.toISOString();
+  }
+
+  // Submit handler
+  async function onSubmit(values: UpdateVendorInvestigationSchema) {
+    if (!values.investigationId) return
+
+    startTransition(async () => {
+      // 1) Build a FormData object for the server action
+      const formData = new FormData()
+
+      // Add text fields
+      formData.append("investigationId", String(values.investigationId))
+      formData.append("investigationStatus", values.investigationStatus)
+      
+      // Format dates properly before appending to FormData
+      if (values.scheduledStartAt) {
+        const formattedDate = formatDateForFormData(values.scheduledStartAt)
+        if (formattedDate) formData.append("scheduledStartAt", formattedDate)
+      }
+      
+      if (values.scheduledEndAt) {
+        const formattedDate = formatDateForFormData(values.scheduledEndAt)
+        if (formattedDate) formData.append("scheduledEndAt", formattedDate)
+      }
+      
+      if (values.completedAt) {
+        const formattedDate = formatDateForFormData(values.completedAt)
+        if (formattedDate) formData.append("completedAt", formattedDate)
+      }
+      
+      if (values.investigationNotes) {
+        formData.append("investigationNotes", values.investigationNotes)
+      }
+
+      // Add attachments (if any)
+      // Note: If you have multiple files in "attachments", we store them in the form under the same key.
+      const attachmentValue = form.getValues("attachments");
+      if (attachmentValue instanceof FileList) {
+        for (let i = 0; i < attachmentValue.length; i++) {
+          formData.append("attachments", attachmentValue[i]);
+        }
+      }
+
+      const { error } = await updateVendorInvestigationAction(formData)
+      if (error) {
+        toast.error(error)
+        return
+      }
+
+      toast.success("Investigation updated!")
+      form.reset()
+      props.onOpenChange?.(false)
+    })
+  }
+
+  // Format date value for input field
+  const formatDateForInput = (date: Date | undefined): string => {
+    if (!date) return "";
+    return date instanceof Date ? date.toISOString().slice(0, 10) : "";
+  }
+
+  // Handle date input change
+  const handleDateChange = (e: React.ChangeEvent<HTMLInputElement>, onChange: (...event: any[]) => void) => {
+    const val = e.target.value;
+    if (val) {
+      // Ensure proper date handling by setting to noon to avoid timezone issues
+      const newDate = new Date(`${val}T12:00:00`);
+      onChange(newDate);
+    } else {
+      onChange(undefined);
+    }
+  }
+
+  return (
+    <Sheet {...props}>
+      <SheetContent className="flex flex-col gap-6 sm:max-w-md">
+        <SheetHeader className="text-left">
+          <SheetTitle>Update Investigation</SheetTitle>
+          <SheetDescription>
+            Change the investigation details &amp; attachments
+          </SheetDescription>
+        </SheetHeader>
+
+        <Form {...form}>
+          <form
+            onSubmit={form.handleSubmit(onSubmit)}
+            className="flex flex-col gap-4"
+            // Must use multipart to support file uploads
+            encType="multipart/form-data"
+          >
+            {/* investigationStatus */}
+            <FormField
+              control={form.control}
+              name="investigationStatus"
+              render={({ field }) => (
+                <FormItem>
+                  <FormLabel>Status</FormLabel>
+                  <FormControl>
+                    <Select value={field.value} onValueChange={field.onChange}>
+                      <SelectTrigger className="capitalize">
+                        <SelectValue placeholder="Select a status" />
+                      </SelectTrigger>
+                      <SelectContent>
+                        <SelectGroup>
+                          <SelectItem value="PLANNED">PLANNED</SelectItem>
+                          <SelectItem value="IN_PROGRESS">IN_PROGRESS</SelectItem>
+                          <SelectItem value="COMPLETED">COMPLETED</SelectItem>
+                          <SelectItem value="CANCELED">CANCELED</SelectItem>
+                        </SelectGroup>
+                      </SelectContent>
+                    </Select>
+                  </FormControl>
+                  <FormMessage />
+                </FormItem>
+              )}
+            />
+
+            {/* scheduledStartAt */}
+            <FormField
+              control={form.control}
+              name="scheduledStartAt"
+              render={({ field }) => (
+                <FormItem>
+                  <FormLabel>Scheduled Start</FormLabel>
+                  <FormControl>
+                    <Input
+                      type="date"
+                      value={formatDateForInput(field.value)}
+                      onChange={(e) => handleDateChange(e, field.onChange)}
+                    />
+                  </FormControl>
+                  <FormMessage />
+                </FormItem>
+              )}
+            />
+
+            {/* scheduledEndAt */}
+            <FormField
+              control={form.control}
+              name="scheduledEndAt"
+              render={({ field }) => (
+                <FormItem>
+                  <FormLabel>Scheduled End</FormLabel>
+                  <FormControl>
+                    <Input
+                      type="date"
+                      value={formatDateForInput(field.value)}
+                      onChange={(e) => handleDateChange(e, field.onChange)}
+                    />
+                  </FormControl>
+                  <FormMessage />
+                </FormItem>
+              )}
+            />
+
+            {/* completedAt */}
+            <FormField
+              control={form.control}
+              name="completedAt"
+              render={({ field }) => (
+                <FormItem>
+                  <FormLabel>Completed At</FormLabel>
+                  <FormControl>
+                    <Input
+                      type="date"
+                      value={formatDateForInput(field.value)}
+                      onChange={(e) => handleDateChange(e, field.onChange)}
+                    />
+                  </FormControl>
+                  <FormMessage />
+                </FormItem>
+              )}
+            />
+
+            {/* investigationNotes */}
+            <FormField
+              control={form.control}
+              name="investigationNotes"
+              render={({ field }) => (
+                <FormItem>
+                  <FormLabel>Notes</FormLabel>
+                  <FormControl>
+                    <Input placeholder="Notes about the investigation..." {...field} />
+                  </FormControl>
+                  <FormMessage />
+                </FormItem>
+              )}
+            />
+
+            {/* attachments: multiple file upload */}
+            <FormField
+              control={form.control}
+              name="attachments"
+              render={({ field: { value, onChange, ...fieldProps } }) => (
+                <FormItem>
+                  <FormLabel>Attachments</FormLabel>
+                  <FormControl>
+                    <Input
+                      type="file"
+                      multiple
+                      onChange={(e) => {
+                        onChange(e.target.files); // Store the FileList directly
+                      }}
+                      {...fieldProps}
+                    />
+                  </FormControl>
+                  <FormMessage />
+                </FormItem>
+              )}
+            />
+
+            {/* Footer Buttons */}
+            <SheetFooter className="gap-2 pt-2 sm:space-x-0">
+              <SheetClose asChild>
+                <Button type="button" variant="outline">
+                  Cancel
+                </Button>
+              </SheetClose>
+              <Button disabled={isPending}>
+                {isPending && (
+                  <Loader className="mr-2 h-4 w-4 animate-spin" aria-hidden="true" />
+                )}
+                Save
+              </Button>
+            </SheetFooter>
+          </form>
+        </Form>
+      </SheetContent>
+    </Sheet>
+  )
+}
\ No newline at end of file
-- 
cgit v1.2.3

