diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 00:32:31 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-28 00:32:31 +0000 |
| commit | 20800b214145ee6056f94ca18fa1054f145eb977 (patch) | |
| tree | b5c8b27febe5b126e6d9ece115ea05eace33a020 /lib/vendor-document-list/table/simplified-document-edit-dialog.tsx | |
| parent | e1344a5da1aeef8fbf0f33e1dfd553078c064ccc (diff) | |
(대표님) lib 파트 커밋
Diffstat (limited to 'lib/vendor-document-list/table/simplified-document-edit-dialog.tsx')
| -rw-r--r-- | lib/vendor-document-list/table/simplified-document-edit-dialog.tsx | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/lib/vendor-document-list/table/simplified-document-edit-dialog.tsx b/lib/vendor-document-list/table/simplified-document-edit-dialog.tsx new file mode 100644 index 00000000..933df263 --- /dev/null +++ b/lib/vendor-document-list/table/simplified-document-edit-dialog.tsx @@ -0,0 +1,287 @@ +"use client" + +import * as React from "react" +import { useForm } from "react-hook-form" +import { zodResolver } from "@hookform/resolvers/zod" +import { z } from "zod" +import { toast } from "sonner" + +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Textarea } from "@/components/ui/textarea" +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { Calendar as CalendarComponent } from "@/components/ui/calendar" +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" +import { Calendar, Edit, Loader2 } from "lucide-react" +import { format } from "date-fns" +import { ko } from "date-fns/locale" +import { cn } from "@/lib/utils" +import { EnhancedDocumentsView } from "@/db/schema/vendorDocu" + +// 단순화된 문서 편집 스키마 +const documentEditSchema = z.object({ + docNumber: z.string().min(1, "문서번호는 필수입니다"), + title: z.string().min(1, "제목은 필수입니다"), + pic: z.string().optional(), + status: z.string().min(1, "상태는 필수입니다"), + issuedDate: z.date().optional(), + description: z.string().optional(), +}) + +type DocumentEditSchema = z.infer<typeof documentEditSchema> + +const statusOptions = [ + { value: "ACTIVE", label: "활성" }, + { value: "INACTIVE", label: "비활성" }, + { value: "COMPLETED", label: "완료" }, + { value: "CANCELLED", label: "취소" }, +] + +interface SimplifiedDocumentEditDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + document: EnhancedDocumentsView | null + projectType: "ship" | "plant" +} + +export function SimplifiedDocumentEditDialog({ + open, + onOpenChange, + document, + projectType, +}: SimplifiedDocumentEditDialogProps) { + const [isUpdating, setIsUpdating] = React.useState(false) + + const form = useForm<DocumentEditSchema>({ + resolver: zodResolver(documentEditSchema), + defaultValues: { + docNumber: "", + title: "", + pic: "", + status: "ACTIVE", + issuedDate: undefined, + description: "", + }, + }) + + // 폼 초기화 + React.useEffect(() => { + if (document) { + form.reset({ + docNumber: document.docNumber, + title: document.title, + pic: document.pic || "", + status: document.status, + issuedDate: document.issuedDate ? new Date(document.issuedDate) : undefined, + description: "", + }) + } + }, [document, form]) + + async function onSubmit(data: DocumentEditSchema) { + if (!document) return + + setIsUpdating(true) + try { + // 실제 업데이트 API 호출 (구현 필요) + // await updateDocumentInfo({ documentId: document.documentId, ...data }) + + toast.success("문서 정보가 업데이트되었습니다") + onOpenChange(false) + } catch (error) { + toast.error("업데이트 중 오류가 발생했습니다") + console.error(error) + } finally { + setIsUpdating(false) + } + } + + return ( + <Dialog open={open} onOpenChange={onOpenChange}> + <DialogContent className="sm:max-w-md"> + <DialogHeader> + <DialogTitle className="flex items-center gap-2"> + <Edit className="w-5 h-5" /> + 문서 정보 수정 + </DialogTitle> + <DialogDescription> + {document ? `${document.docNumber}의 기본 정보를 수정합니다.` : "문서 기본 정보를 수정합니다."} + </DialogDescription> + </DialogHeader> + + <Form {...form}> + <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4"> + <FormField + control={form.control} + name="docNumber" + render={({ field }) => ( + <FormItem> + <FormLabel>문서번호</FormLabel> + <FormControl> + <Input {...field} disabled={projectType === "ship"} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="title" + render={({ field }) => ( + <FormItem> + <FormLabel>제목</FormLabel> + <FormControl> + <Input {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <div className="grid grid-cols-2 gap-4"> + <FormField + control={form.control} + name="pic" + render={({ field }) => ( + <FormItem> + <FormLabel>담당자 (PIC)</FormLabel> + <FormControl> + <Input {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="status" + render={({ field }) => ( + <FormItem> + <FormLabel>상태</FormLabel> + <Select onValueChange={field.onChange} value={field.value}> + <FormControl> + <SelectTrigger> + <SelectValue /> + </SelectTrigger> + </FormControl> + <SelectContent> + {statusOptions.map((option) => ( + <SelectItem key={option.value} value={option.value}> + {option.label} + </SelectItem> + ))} + </SelectContent> + </Select> + <FormMessage /> + </FormItem> + )} + /> + </div> + + <FormField + control={form.control} + name="issuedDate" + render={({ field }) => ( + <FormItem> + <FormLabel>발행일</FormLabel> + <Popover> + <PopoverTrigger asChild> + <FormControl> + <Button + variant="outline" + className={cn( + "w-full pl-3 text-left font-normal", + !field.value && "text-muted-foreground" + )} + > + {field.value ? ( + format(field.value, "yyyy년 MM월 dd일", { locale: ko }) + ) : ( + <span>날짜를 선택하세요</span> + )} + <Calendar className="ml-auto h-4 w-4 opacity-50" /> + </Button> + </FormControl> + </PopoverTrigger> + <PopoverContent className="w-auto p-0" align="start"> + <CalendarComponent + mode="single" + selected={field.value} + onSelect={field.onChange} + disabled={(date) => date > new Date()} + initialFocus + /> + </PopoverContent> + </Popover> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="description" + render={({ field }) => ( + <FormItem> + <FormLabel>설명 (선택)</FormLabel> + <FormControl> + <Textarea {...field} placeholder="문서에 대한 설명을 입력하세요" rows={3} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <DialogFooter> + <Button + type="button" + variant="outline" + onClick={() => onOpenChange(false)} + disabled={isUpdating} + > + 취소 + </Button> + <Button type="submit" disabled={isUpdating}> + {isUpdating ? ( + <> + <Loader2 className="mr-2 h-4 w-4 animate-spin" /> + 저장 중... + </> + ) : ( + <> + <Edit className="mr-2 h-4 w-4" /> + 저장 + </> + )} + </Button> + </DialogFooter> + </form> + </Form> + </DialogContent> + </Dialog> + ) +}
\ No newline at end of file |
