From 33e8452331c301430191b3506825ebaf3edac93a Mon Sep 17 00:00:00 2001 From: dujinkim Date: Wed, 1 Oct 2025 09:48:03 +0000 Subject: (최겸) 구매 PQ 리스트 기능 수정, 견적 첨부파일 리비전 액션 추가, 기타 등 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pq/table/add-pq-list-dialog.tsx | 34 +++------- lib/pq/table/copy-pq-list-dialog.tsx | 80 ++++++++++++---------- lib/pq/table/pq-lists-columns.tsx | 127 ++++++++++++++++++++++++++++++++--- lib/pq/table/pq-lists-table.tsx | 45 +++++++++++-- lib/pq/table/pq-lists-toolbar.tsx | 4 +- 5 files changed, 212 insertions(+), 78 deletions(-) (limited to 'lib/pq/table') diff --git a/lib/pq/table/add-pq-list-dialog.tsx b/lib/pq/table/add-pq-list-dialog.tsx index c1899a29..472a1b3d 100644 --- a/lib/pq/table/add-pq-list-dialog.tsx +++ b/lib/pq/table/add-pq-list-dialog.tsx @@ -10,13 +10,8 @@ import { DatePicker } from "@/components/ui/date-picker" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form" import { Loader2, Plus } from "lucide-react" +import { ProjectSelector } from "@/components/ProjectSelector" -// 프로젝트 목록을 위한 임시 타입 (실제로는 projects에서 가져와야 함) -interface Project { - id: number - name: string - code: string -} const pqListFormSchema = z.object({ name: z.string().min(1, "PQ 목록 명을 입력해주세요"), @@ -42,7 +37,6 @@ interface PqListFormProps { open: boolean onOpenChange: (open: boolean) => void initialData?: Partial & { id?: number } - projects?: Project[] onSubmit: (data: PqListFormData & { id?: number }) => Promise isLoading?: boolean } @@ -57,7 +51,6 @@ export function AddPqDialog({ open, onOpenChange, initialData, - projects = [], onSubmit, isLoading = false }: PqListFormProps) { @@ -162,23 +155,13 @@ export function AddPqDialog({ 프로젝트 * - + + field.onChange(project.id)} + placeholder="프로젝트를 선택하세요" + /> + )} @@ -200,6 +183,7 @@ export function AddPqDialog({ date={field.value ?? undefined} onSelect={(date) => field.onChange(date ?? null)} placeholder="유효일 선택" + minDate={new Date()} /> diff --git a/lib/pq/table/copy-pq-list-dialog.tsx b/lib/pq/table/copy-pq-list-dialog.tsx index 647ab1a3..51b7eed1 100644 --- a/lib/pq/table/copy-pq-list-dialog.tsx +++ b/lib/pq/table/copy-pq-list-dialog.tsx @@ -33,11 +33,17 @@ const copyPqSchema = z.object({ sourcePqListId: z.number({ required_error: "복사할 PQ 목록을 선택해주세요" }), - targetProjectId: z.number({ - required_error: "대상 프로젝트를 선택해주세요" - }), + targetProjectId: z.number().optional(), validTo: z.date(), newName: z.string(), +}).refine((data) => { + // 미실사 PQ가 아닌 경우에만 targetProjectId 필수 + if (data.targetProjectId !== undefined) return true + // 미실사 PQ인 경우 targetProjectId는 선택사항 + return true +}, { + message: "프로젝트 PQ인 경우 대상 프로젝트를 선택해야 합니다", + path: ["targetProjectId"] }) type CopyPqFormData = z.infer @@ -106,36 +112,6 @@ export function CopyPqDialog({
- {/* 대상 프로젝트 선택 */} - ( - - - 대상 프로젝트 * - - - - - )} - /> {/* 복사할 PQ 목록 선택 */} - {pqLists.map((pqList) => ( + {pqLists + .filter(pqList => pqList.type !== "GENERAL") // 일반 PQ 제외 + .map((pqList) => (
@@ -184,6 +162,39 @@ export function CopyPqDialog({ )} /> + {/* 대상 프로젝트 선택 (미실사 PQ가 아닌 경우에만) */} + {selectedPqList?.type !== "NON_INSPECTION" && ( + ( + + + 대상 프로젝트 * + + + + + )} + /> + )} + {/* 새 PQ 목록 명 */} field.onChange(date ?? null)} placeholder="유효기간 선택" + minDate={new Date()} /> diff --git a/lib/pq/table/pq-lists-columns.tsx b/lib/pq/table/pq-lists-columns.tsx index 1c401fac..a9262a12 100644 --- a/lib/pq/table/pq-lists-columns.tsx +++ b/lib/pq/table/pq-lists-columns.tsx @@ -13,9 +13,19 @@ import { DropdownMenuTrigger } from "@/components/ui/dropdown-menu" import { Button } from "@/components/ui/button" -import React from "react" +import React, { useMemo, useState } from "react" import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" import { Checkbox } from "@/components/ui/checkbox" +import { + Sheet, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, +} from "@/components/ui/sheet" +import { DatePicker } from "@/components/ui/date-picker" +import { toast } from "sonner" export interface PQList { id: number @@ -48,6 +58,84 @@ const typeColors = { interface GetColumnsProps { setRowAction: React.Dispatch | null>> } + +// 유효일 수정 시트 컴포넌트 +interface EditValidToSheetProps { + pqList: PQList | null + open: boolean + onOpenChange: (open: boolean) => void + onUpdate: (pqListId: number, newValidTo: Date | null) => Promise +} + +export function EditValidToSheet({ pqList, open, onOpenChange, onUpdate }: EditValidToSheetProps) { + const [newValidTo, setNewValidTo] = useState(pqList?.validTo || null) + const [isLoading, setIsLoading] = useState(false) + + const handleSave = async () => { + if (!pqList) return + + setIsLoading(true) + try { + await onUpdate(pqList.id, newValidTo) + onOpenChange(false) + } catch (error) { + console.error("유효일 수정 실패:", error) + } finally { + setIsLoading(false) + } + } + + return ( + + + + 유효일 수정 + + {pqList && ( + <> + {pqList.name}의 유효일을 수정합니다. + + )} + + + +
+
+
+ +
+ {pqList?.validTo ? formatDate(pqList.validTo, "ko-KR") : "설정되지 않음"} +
+
+ +
+ +
+ setNewValidTo(date ?? null)} + placeholder="새 유효일을 선택하세요" + minDate={new Date()} + /> +
+
+
+
+ + + + + +
+
+ ) +} + export function createPQListsColumns({ setRowAction }: GetColumnsProps): ColumnDef[] { @@ -122,17 +210,23 @@ export function createPQListsColumns({ ), cell: ({ row }) => { const validTo = row.getValue("validTo") as Date | null - const now = new Date() - const isExpired = validTo && validTo < now - - const formattedDate = validTo ? formatDate(validTo, "ko-KR") : "-" - + + const dateInfo = useMemo(() => { + if (!validTo) return { formattedDate: "-", isExpired: false } + + const now = new Date() + const isExpired = validTo < now + const formattedDate = formatDate(validTo, "ko-KR") + + return { formattedDate, isExpired } + }, [validTo]) + return (
- - {formattedDate} + + {dateInfo.formattedDate} - {isExpired && ( + {dateInfo.isExpired && ( 만료 @@ -168,14 +262,20 @@ export function createPQListsColumns({ header: ({ column }) => ( ), - cell: ({ row }) => formatDate(row.getValue("createdAt"), "ko-KR"), + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as Date + return useMemo(() => formatDate(createdAt, "ko-KR"), [createdAt]) + }, }, { accessorKey: "updatedAt", header: ({ column }) => ( ), - cell: ({ row }) => formatDate(row.getValue("updatedAt"), "ko-KR"), + cell: ({ row }) => { + const updatedAt = row.getValue("updatedAt") as Date + return useMemo(() => formatDate(updatedAt, "ko-KR"), [updatedAt]) + }, }, { id: "actions", @@ -196,6 +296,11 @@ export function createPQListsColumns({ > 상세보기 + setRowAction({ row, type: "editValidTo" })} + > + 유효일 수정 + {/* setRowAction({ row, type: "delete" })} diff --git a/lib/pq/table/pq-lists-table.tsx b/lib/pq/table/pq-lists-table.tsx index c5fd82a5..1be0a1c7 100644 --- a/lib/pq/table/pq-lists-table.tsx +++ b/lib/pq/table/pq-lists-table.tsx @@ -13,10 +13,12 @@ import { deletePQListsAction, copyPQListAction, togglePQListsAction, + updatePqValidToAction, } from "@/lib/pq/service" import { CopyPqDialog } from "./copy-pq-list-dialog" import { AddPqDialog } from "./add-pq-list-dialog" import { PQListsToolbarActions } from "./pq-lists-toolbar" +import { EditValidToSheet } from "./pq-lists-columns" import type { DataTableRowAction } from "@/types/table" interface Project { @@ -34,10 +36,12 @@ export function PqListsTable({ promises }: PqListsTableProps) { const [rowAction, setRowAction] = React.useState | null>(null) const [createDialogOpen, setCreateDialogOpen] = React.useState(false) const [copyDialogOpen, setCopyDialogOpen] = React.useState(false) + const [editValidToSheetOpen, setEditValidToSheetOpen] = React.useState(false) + const [selectedPqList, setSelectedPqList] = React.useState(null) const [isPending, startTransition] = React.useTransition() const [{ data, pageCount }, projects] = React.use(promises) - const activePqLists = data.filter((item) => !item.isDeleted) + // const activePqLists = data.filter((item) => !item.isDeleted) const columns = React.useMemo(() => createPQListsColumns({ setRowAction }), [setRowAction]) @@ -116,15 +120,38 @@ export function PqListsTable({ promises }: PqListsTableProps) { }) } + const handleUpdateValidTo = React.useCallback(async (pqListId: number, newValidTo: Date | null) => { + startTransition(async () => { + try { + const result = await updatePqValidToAction({ pqListId, validTo: newValidTo }) + if (result.success) { + toast.success(result.message || "유효일이 성공적으로 수정되었습니다") + setEditValidToSheetOpen(false) + setSelectedPqList(null) + router.refresh() + } else { + toast.error(`유효일 수정 실패: ${result.error}`) + } + } catch (error) { + console.error("유효일 수정 실패:", error) + toast.error("유효일 수정 실패") + } + }) + }, []) + React.useEffect(() => { if (!rowAction) return - const id = rowAction.row.original.id + const pqList = rowAction.row.original switch (rowAction.type) { case "view": - router.push(`/evcp/pq-criteria/${id}`) + router.push(`/evcp/pq-criteria/${pqList.id}`) break case "delete": - handleDelete([id]) + handleDelete([pqList.id]) + break + case "editValidTo": + setSelectedPqList(pqList) + setEditValidToSheetOpen(true) break } setRowAction(null) @@ -153,18 +180,24 @@ export function PqListsTable({ promises }: PqListsTableProps) { open={createDialogOpen} onOpenChange={setCreateDialogOpen} onSubmit={handleCreate} - projects={projects} isLoading={isPending} /> + + ) } diff --git a/lib/pq/table/pq-lists-toolbar.tsx b/lib/pq/table/pq-lists-toolbar.tsx index 3a85327d..1feb9a1a 100644 --- a/lib/pq/table/pq-lists-toolbar.tsx +++ b/lib/pq/table/pq-lists-toolbar.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { Button } from "@/components/ui/button" -import { Trash, CopyPlus, Plus } from "lucide-react" +import { Trash, CopyPlus, Plus, RefreshCw } from "lucide-react" import { type Table } from "@tanstack/react-table" import type { PQList } from "./pq-lists-columns" // import { PqListForm } from "./add-pq-list-dialog" @@ -44,7 +44,7 @@ export function PQListsToolbarActions({ size="sm" onClick={() => onToggleActive(selected, newState!)} > - + {toggleLabel} )} -- cgit v1.2.3