// simplified-documents-table.tsx - Project Code 필터 기능 추가 "use client" import React from "react" import type { DataTableAdvancedFilterField, DataTableFilterField, DataTableRowAction, } from "@/types/table" import { useDataTable } from "@/hooks/use-data-table" import { getUserVendorDocuments, getUserVendorDocumentStats } from "@/lib/vendor-document-list/enhanced-document-service" import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar" import { toast } from "sonner" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { FileText, FileInput, FileOutput, FolderOpen, Building2 } from "lucide-react" import { Label } from "@/components/ui/label" import { DataTable } from "@/components/data-table/data-table" import { SimplifiedDocumentsView } from "@/db/schema" import { getSimplifiedDocumentColumns } from "./enhanced-doc-table-columns" import { EnhancedDocTableToolbarActions } from "./enhanced-doc-table-toolbar-actions" // 🔥 Project Code 필터를 위한 Select 컴포넌트 import 추가 import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" // DrawingKind별 설명 매핑 const DRAWING_KIND_INFO = { B3: { title: "B3 Vendor", description: "Approval-focused drawings progressing through Approval → Work stages", color: "bg-primary/10 text-primary border-primary/20" }, B4: { title: "B4 GTT", description: "DOLCE-integrated drawings progressing through Pre → Work stages", color: "bg-emerald-50 dark:bg-emerald-950/20 text-emerald-700 dark:text-emerald-400 border-emerald-200 dark:border-emerald-800" }, B5: { title: "B5 FMEA", description: "Sequential drawings progressing through First → Second stages", color: "bg-purple-50 dark:bg-purple-950/20 text-purple-700 dark:text-purple-400 border-purple-200 dark:border-purple-800" } } as const interface SimplifiedDocumentsTableProps { allPromises: Promise<[ Awaited>, Awaited> ]> onDataLoaded?: (data: SimplifiedDocumentsView[]) => void } export function SimplifiedDocumentsTable({ allPromises, onDataLoaded, }: SimplifiedDocumentsTableProps) { // 🔥 React.use() 결과를 안전하게 처리 const promiseResults = React.use(allPromises) const [documentResult, statsResult] = promiseResults // 🔥 데이터 구조분해를 메모이제이션 const { data, pageCount, total, drawingKind, vendorInfo } = React.useMemo(() => documentResult, [documentResult]) const { stats, totalDocuments, primaryDrawingKind } = React.useMemo(() => statsResult, [statsResult]) // 🔥 B4 필터 상태 추가 const [b4FilterType, setB4FilterType] = React.useState<'all' | 'gtt_deliverable' | 'shi_input'>('all') // 🔥 Project Code 필터 상태 추가 const [selectedProjectCode, setSelectedProjectCode] = React.useState('all') // 🔥 고유한 Project Code 목록 추출 및 카운트 메모이제이션 const projectCodeStats = React.useMemo(() => { const projectMap = new Map() data.forEach(doc => { const projectCode = doc.projectCode || 'Unknown' projectMap.set(projectCode, (projectMap.get(projectCode) || 0) + 1) }) // 정렬된 배열로 변환 (프로젝트 코드 알파벳순) return Array.from(projectMap.entries()) .sort((a, b) => a[0].localeCompare(b[0])) .map(([code, count]) => ({ code, count })) }, [data]) // 🔥 데이터 로드 콜백을 useCallback으로 최적화 const handleDataLoaded = React.useCallback((loadedData: SimplifiedDocumentsView[]) => { onDataLoaded?.(loadedData) }, [onDataLoaded]) // 🔥 B4 및 Project Code 필터링된 데이터 메모이제이션 const filteredData = React.useMemo(() => { let result = data // B4 필터 적용 if (b4FilterType !== 'all') { if (b4FilterType === 'gtt_deliverable') { result = result.filter(doc => doc.drawingMoveGbn === '도면입수') } else if (b4FilterType === 'shi_input') { result = result.filter(doc => doc.drawingMoveGbn === '도면제출') } } // Project Code 필터 적용 if (selectedProjectCode !== 'all') { result = result.filter(doc => (doc.projectCode || 'Unknown') === selectedProjectCode ) } return result }, [data, b4FilterType, selectedProjectCode]) // 🔥 데이터가 로드되면 콜백 호출 (필터링된 데이터 사용) React.useEffect(() => { if (filteredData && handleDataLoaded) { handleDataLoaded(filteredData) } }, [filteredData, handleDataLoaded]) // 🔥 상태들을 안정적으로 관리 const [rowAction, setRowAction] = React.useState | null>(null) const [expandedRows] = React.useState>(() => new Set()) // 🔥 컬럼 메모이제이션 최적화 const columns = React.useMemo( () => getSimplifiedDocumentColumns({ setRowAction, }), [] ) // 🔥 필터 필드들을 메모이제이션 const advancedFilterFields: DataTableAdvancedFilterField[] = React.useMemo(() => [ { id: "docNumber", label: "Document No", type: "text", }, { id: "title", label: "Document Title", type: "text", }, { id: "drawingKind", label: "Document Type", type: "select", options: [ { label: "B3", value: "B3" }, { label: "B4", value: "B4" }, { label: "B5", value: "B5" }, ], }, { id: "projectCode", label: "Project Code", type: "text", }, { id: "vendorName", label: "Vendor Name", type: "text", }, { id: "vendorCode", label: "Vendor Code", type: "text", }, { id: "pic", label: "PIC", type: "text", }, { id: "status", label: "Document Status", type: "select", options: [ { label: "Active", value: "ACTIVE" }, { label: "Inactive", value: "INACTIVE" }, { label: "Pending", value: "PENDING" }, { label: "Completed", value: "COMPLETED" }, ], }, { id: "firstStageName", label: "First Stage", type: "text", }, { id: "secondStageName", label: "Second Stage", type: "text", }, { id: "firstStagePlanDate", label: "First Planned Date", type: "date", }, { id: "firstStageActualDate", label: "First Actual Date", type: "date", }, { id: "secondStagePlanDate", label: "Second Planned Date", type: "date", }, { id: "secondStageActualDate", label: "Second Actual Date", type: "date", }, { id: "issuedDate", label: "Issue Date", type: "date", }, { id: "createdAt", label: "Created Date", type: "date", }, { id: "updatedAt", label: "Updated Date", type: "date", }, ], []) // 🔥 B4 전용 필드들 메모이제이션 const b4FilterFields: DataTableAdvancedFilterField[] = React.useMemo(() => [ { id: "cGbn", label: "C Category", type: "text", }, { id: "dGbn", label: "D Category", type: "text", }, { id: "degreeGbn", label: "Degree Category", type: "text", }, { id: "deptGbn", label: "Dept Category", type: "text", }, { id: "jGbn", label: "J Category", type: "text", }, { id: "sGbn", label: "S Category", type: "text", }, ], []) // 🔥 B4 문서 존재 여부 체크 메모이제이션 const hasB4Documents = React.useMemo(() => { return data.some(doc => doc.drawingKind === 'B4') }, [data]) // 🔥 최종 필터 필드 메모이제이션 const finalFilterFields = React.useMemo(() => { return hasB4Documents ? [...advancedFilterFields, ...b4FilterFields] : advancedFilterFields }, [hasB4Documents, advancedFilterFields, b4FilterFields]) // 🔥 테이블 초기 상태 메모이제이션 const tableInitialState = React.useMemo(() => ({ sorting: [{ id: "createdAt", desc: true }], columnPinning: { right: ["actions"] }, }), []) // 🔥 getRowId 함수 메모이제이션 const getRowId = React.useCallback((originalRow: SimplifiedDocumentsView) => String(originalRow.documentId), []) const { table } = useDataTable({ data: filteredData, columns, pageCount, enablePinning: true, enableAdvancedFilter: true, initialState: tableInitialState, getRowId, shallow: false, clearOnDefault: true, columnResizeMode: "onEnd", }) // 🔥 활성 drawingKind 메모이제이션 const activeDrawingKind = React.useMemo(() => { return drawingKind || primaryDrawingKind }, [drawingKind, primaryDrawingKind]) // 🔥 kindInfo 메모이제이션 const kindInfo = React.useMemo(() => { return activeDrawingKind ? DRAWING_KIND_INFO[activeDrawingKind] : null }, [activeDrawingKind]) // 🔥 B4 문서 통계 계산 const b4Stats = React.useMemo(() => { if (!hasB4Documents) return null const gttDeliverableCount = data.filter(doc => doc.drawingKind === 'B4' && doc.drawingMoveGbn === '도면입수' ).length const shiInputCount = data.filter(doc => doc.drawingKind === 'B4' && doc.drawingMoveGbn === '도면제출' ).length return { gttDeliverableCount, shiInputCount } }, [data, hasB4Documents]) return (
{/* DrawingKind 정보 간단 표시 */} {kindInfo && (
{/* 주석 처리된 부분은 그대로 유지 */}
{filteredData.length} documents
)} {/* 🔥 필터 섹션 - Project Code 필터와 B4 필터를 함께 배치 */}
{/* Project Code 필터 드롭다운 */}
{selectedProjectCode !== 'all' && ( )}
{/* B4 필터 버튼 - 기존 코드 유지 */} {hasB4Documents && b4Stats && (
)}
{/* 테이블 */}
) }