From 043dfe2f7ac3965de60d3f3caf636237b9d986b0 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Tue, 11 Nov 2025 19:19:25 +0900 Subject: (김준회) 정규업체 등록관리: 주요품목 컬럼 오류 수정, 주요품목 업데이트 dialog 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vendor-regular-registrations-table-columns.tsx | 632 +++++++++++---------- 1 file changed, 325 insertions(+), 307 deletions(-) (limited to 'lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx') diff --git a/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx b/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx index b6f9289f..cd748fd8 100644 --- a/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx +++ b/lib/vendor-regular-registrations/table/vendor-regular-registrations-table-columns.tsx @@ -1,307 +1,325 @@ -"use client" - -import { type ColumnDef } from "@tanstack/react-table" -import { Checkbox } from "@/components/ui/checkbox" -import { Badge } from "@/components/ui/badge" -import { format } from "date-fns" - -import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" -import { VendorRegularRegistration, statusLabels, statusColors } from "@/config/vendorRegularRegistrationsColumnsConfig" -import { DocumentStatusDialog } from "@/components/vendor-regular-registrations/document-status-dialog" -import { Button } from "@/components/ui/button" -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" -import { Eye, FileText, Ellipsis, Shield, Package } from "lucide-react" -import { toast } from "sonner" -import { useState } from "react" -import { SafetyQualificationUpdateDialog } from "./safety-qualification-update-dialog" -import { MajorItemsUpdateDialog } from "./major-items-update-dialog" - -export function getColumns(): ColumnDef[] { - - return [ - { - id: "select", - header: ({ table }) => ( - table.toggleAllPageRowsSelected(!!value)} - aria-label="Select all" - className="translate-y-[2px]" - /> - ), - cell: ({ row }) => ( - row.toggleSelected(!!value)} - aria-label="Select row" - className="translate-y-[2px]" - /> - ), - enableSorting: false, - enableHiding: false, - }, - { - accessorKey: "status", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const status = row.getValue("status") as string - return ( - - {statusLabels[status as keyof typeof statusLabels] || status} - - ) - }, - filterFn: (row, id, value) => { - return Array.isArray(value) && value.includes(row.getValue(id)) - }, - }, - { - accessorKey: "potentialCode", - header: ({ column }) => ( - - ), - cell: ({ row }) => row.getValue("potentialCode") || "-", - }, - { - accessorKey: "businessNumber", - header: ({ column }) => ( - - ), - }, - { - accessorKey: "companyName", - header: ({ column }) => ( - - ), - }, - { - accessorKey: "majorItems", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const majorItems = row.getValue("majorItems") as string - try { - const items = majorItems ? JSON.parse(majorItems) : [] - if (items.length === 0) return "-" - - // 첫 번째 아이템을 itemCode-itemName 형태로 표시 - const firstItem = items[0] - let displayText = "" - - if (typeof firstItem === 'string') { - displayText = firstItem - } else if (typeof firstItem === 'object') { - const code = firstItem.itemCode || firstItem.code || "" - const name = firstItem.itemName || firstItem.name || firstItem.materialGroupName || "" - if (code && name) { - displayText = `${code}-${name}` - } else { - displayText = name || code || String(firstItem) - } - } else { - displayText = String(firstItem) - } - - // 나머지 개수 표시 - if (items.length > 1) { - displayText += ` 외 ${items.length - 1}개` - } - - return displayText - } catch { - return majorItems || "-" - } - }, - }, - { - accessorKey: "establishmentDate", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const date = row.getValue("establishmentDate") as string - return date ? format(new Date(date), "yyyy.MM.dd") : "-" - }, - }, - { - accessorKey: "representative", - header: ({ column }) => ( - - ), - cell: ({ row }) => row.getValue("representative") || "-", - }, - { - id: "documentStatus", - header: "진행현황", - cell: ({ row }) => { - const DocumentStatusCell = () => { - const [documentDialogOpen, setDocumentDialogOpen] = useState(false) - const registration = row.original - - // 문서 현황 계산 (국가별 요구사항 적용) - const isForeign = registration.country !== 'KR' - const requiredDocs = isForeign ? 4 : 3 // 외자: 4개(통장사본 포함), 내자: 3개(통장사본 제외) - const submittedDocs = Object.values(registration.documentSubmissions).filter(Boolean).length - const incompleteDocs = requiredDocs - submittedDocs - - // 기본계약 현황 계산 - const totalContracts = registration.basicContracts?.length || 0 - const completedContracts = registration.basicContracts?.filter(c => c.status === "VENDOR_SIGNED" || c.status === "COMPLETED").length || 0 - const incompleteContracts = totalContracts - completedContracts - - // 안전적격성 평가 현황 - const safetyCompleted = !!registration.safetyQualificationContent - - // 추가정보 현황 - const additionalInfoCompleted = registration.additionalInfo - - // 전체 미완료 항목 계산 - const totalIncomplete = - (incompleteDocs > 0 ? 1 : 0) + - incompleteContracts + - (!safetyCompleted ? 1 : 0) + - (!additionalInfoCompleted ? 1 : 0) - - const isAllComplete = totalIncomplete === 0 - - return ( - <> -
- -
- - - ) - } - - return - }, - }, - { - accessorKey: "registrationRequestDate", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const date = row.getValue("registrationRequestDate") as string - return date ? format(new Date(date), "yyyy.MM.dd") : "-" - }, - }, - { - accessorKey: "assignedDepartment", - header: ({ column }) => ( - - ), - cell: ({ row }) => row.getValue("assignedDepartment") || "-", - }, - { - accessorKey: "assignedUser", - header: ({ column }) => ( - - ), - cell: ({ row }) => row.getValue("assignedUser") || "-", - }, - { - accessorKey: "remarks", - header: ({ column }) => ( - - ), - cell: ({ row }) => row.getValue("remarks") || "-", - }, - { - id: "actions", - cell: ({ row }) => { - const ActionsDropdownCell = () => { - const [safetyQualificationSheetOpen, setSafetyQualificationSheetOpen] = useState(false) - const [majorItemsSheetOpen, setMajorItemsSheetOpen] = useState(false) - const registration = row.original - - return ( - <> - - - - - - setSafetyQualificationSheetOpen(true)} - > - - 안전적격성 평가 - - setMajorItemsSheetOpen(true)} - > - - 주요품목 등록 - - - - - { - // 페이지 새로고침 또는 데이터 리페치 - window.location.reload() - }} - /> - { - // 페이지 새로고침 또는 데이터 리페치 - window.location.reload() - }} - /> - - - ) - } - - return - }, - }, - ] -} +"use client" + +import { type ColumnDef } from "@tanstack/react-table" +import { Checkbox } from "@/components/ui/checkbox" +import { Badge } from "@/components/ui/badge" +import { format } from "date-fns" + +import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header" +import { VendorRegularRegistration, statusLabels, statusColors } from "@/config/vendorRegularRegistrationsColumnsConfig" +import { DocumentStatusDialog } from "@/components/vendor-regular-registrations/document-status-dialog" +import { Button } from "@/components/ui/button" +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu" +import { Ellipsis, Shield, Package } from "lucide-react" +import { useState } from "react" +import { SafetyQualificationUpdateDialog } from "./safety-qualification-update-dialog" +import { MajorItemsUpdateDialog } from "./major-items-update-dialog" + +export function getColumns(): ColumnDef[] { + + return [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + className="translate-y-[2px]" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + className="translate-y-[2px]" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "status", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = row.getValue("status") as string + return ( + + {statusLabels[status as keyof typeof statusLabels] || status} + + ) + }, + filterFn: (row, id, value) => { + return Array.isArray(value) && value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "potentialCode", + header: ({ column }) => ( + + ), + cell: ({ row }) => row.getValue("potentialCode") || "-", + }, + { + accessorKey: "businessNumber", + header: ({ column }) => ( + + ), + }, + { + accessorKey: "companyName", + header: ({ column }) => ( + + ), + }, + { + accessorKey: "majorItems", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const majorItems = row.getValue("majorItems") as string + try { + const items = majorItems ? JSON.parse(majorItems) : [] + if (items.length === 0) return "-" + + // 모든 아이템을 표시 + return ( +
+ {items.map((item: unknown, index: number) => { + let displayText = "" + + if (typeof item === 'string') { + displayText = item + } else if (typeof item === 'object' && item !== null) { + // materialGroup 형태 처리 + const itemObj = item as Record + const materialGroupCode = (itemObj.materialGroupCode as string) || "" + const materialGroupDescription = (itemObj.materialGroupDescription as string) || "" + + if (materialGroupCode && materialGroupDescription) { + displayText = `${materialGroupCode} - ${materialGroupDescription}` + } else if (materialGroupDescription) { + displayText = materialGroupDescription + } else if (materialGroupCode) { + displayText = materialGroupCode + } else { + // 알 수 없는 형태 + console.warn("알 수 없는 품목 형식:", item) + displayText = JSON.stringify(item) + } + } else { + displayText = String(item) + } + + return ( + + {displayText} + + ) + })} +
+ ) + } catch (error) { + // JSON 파싱 실패 시 원본 문자열 표시 + console.error("주요품목 파싱 오류:", error) + return majorItems || "-" + } + }, + }, + { + accessorKey: "establishmentDate", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const date = row.getValue("establishmentDate") as string + return date ? format(new Date(date), "yyyy.MM.dd") : "-" + }, + }, + { + accessorKey: "representative", + header: ({ column }) => ( + + ), + cell: ({ row }) => row.getValue("representative") || "-", + }, + { + id: "documentStatus", + header: "진행현황", + cell: ({ row }) => { + const DocumentStatusCell = () => { + const [documentDialogOpen, setDocumentDialogOpen] = useState(false) + const registration = row.original + + // 문서 현황 계산 (국가별 요구사항 적용) + const isForeign = registration.country !== 'KR' + const requiredDocs = isForeign ? 4 : 3 // 외자: 4개(통장사본 포함), 내자: 3개(통장사본 제외) + const submittedDocs = Object.values(registration.documentSubmissions).filter(Boolean).length + const incompleteDocs = requiredDocs - submittedDocs + + // 기본계약 현황 계산 + const totalContracts = registration.basicContracts?.length || 0 + const completedContracts = registration.basicContracts?.filter(c => c.status === "VENDOR_SIGNED" || c.status === "COMPLETED").length || 0 + const incompleteContracts = totalContracts - completedContracts + + // 안전적격성 평가 현황 + const safetyCompleted = !!registration.safetyQualificationContent + + // 추가정보 현황 + const additionalInfoCompleted = registration.additionalInfo + + // 전체 미완료 항목 계산 + const totalIncomplete = + (incompleteDocs > 0 ? 1 : 0) + + incompleteContracts + + (!safetyCompleted ? 1 : 0) + + (!additionalInfoCompleted ? 1 : 0) + + const isAllComplete = totalIncomplete === 0 + + return ( + <> +
+ +
+ + + ) + } + + return + }, + }, + { + accessorKey: "registrationRequestDate", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const date = row.getValue("registrationRequestDate") as string + return date ? format(new Date(date), "yyyy.MM.dd") : "-" + }, + }, + { + accessorKey: "assignedDepartment", + header: ({ column }) => ( + + ), + cell: ({ row }) => row.getValue("assignedDepartment") || "-", + }, + { + accessorKey: "assignedUser", + header: ({ column }) => ( + + ), + cell: ({ row }) => row.getValue("assignedUser") || "-", + }, + { + accessorKey: "remarks", + header: ({ column }) => ( + + ), + cell: ({ row }) => row.getValue("remarks") || "-", + }, + { + id: "actions", + cell: ({ row }) => { + const ActionsDropdownCell = () => { + const [safetyQualificationSheetOpen, setSafetyQualificationSheetOpen] = useState(false) + const [majorItemsSheetOpen, setMajorItemsSheetOpen] = useState(false) + const registration = row.original + + return ( + <> + + + + + + setSafetyQualificationSheetOpen(true)} + > + + 안전적격성 평가 + + setMajorItemsSheetOpen(true)} + > + + 주요품목 등록 + + + + + { + // 페이지 새로고침 또는 데이터 리페치 + window.location.reload() + }} + /> + { + // 페이지 새로고침 또는 데이터 리페치 + window.location.reload() + }} + /> + + + ) + } + + return + }, + }, + ] +} -- cgit v1.2.3