// simplified-documents-table.tsx - Project Code 필터 기능 추가 "use client" import React from "react" import type { DataTableAdvancedFilterField, } 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 { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { FileText, FileInput, FileOutput, 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" import { useQueryStates, parseAsString, parseAsStringEnum, parseAsInteger } from "nuqs" // 🔥 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 documentData = React.useMemo(() => documentResult as Awaited>, [documentResult]) const statsData = React.useMemo(() => statsResult as Awaited>, [statsResult]) const { data, pageCount, drawingKind } = documentData const { primaryDrawingKind, b4Stats: serverB4Stats } = statsData // 🔥 URL searchParams를 통한 필터 상태 관리 const [{ b4FilterType, projectCode, page }, setQueryStates] = useQueryStates( { b4FilterType: parseAsStringEnum<'all' | 'gtt_deliverable' | 'shi_input'>(['all', 'gtt_deliverable', 'shi_input']).withDefault('all'), projectCode: parseAsString.withDefault('all'), page: parseAsInteger.withDefault(1), }, { history: "push", shallow: false, } ) // page 변수는 현재 사용하지 않지만, setQueryStates에서 page를 업데이트하기 위해 필요 // eslint-disable-next-line @typescript-eslint/no-unused-vars const _ensurePageIsInState = page // 🔥 통계 데이터를 위한 전체 데이터 조회 (필터링 없이) const projectCodeStats = React.useMemo(() => { // statsData에서 전체 프로젝트 코드 목록을 가져옴 (향후 개선 가능) const projectMap = new Map() data.forEach(doc => { const code = doc.projectCode || 'Unknown' projectMap.set(code, (projectMap.get(code) || 0) + 1) }) // 정렬된 배열로 변환 (프로젝트 코드 알파벳순) return Array.from(projectMap.entries()) .sort((a, b) => a[0].localeCompare(b[0])) .map(([code, count]) => ({ code, count })) }, [data]) // 🔥 데이터 로드 콜백 (서버에서 이미 필터링되어 옴) React.useEffect(() => { if (data && onDataLoaded) { onDataLoaded(data) } }, [data, onDataLoaded]) // 🔥 컬럼 메모이제이션 최적화 const columns = React.useMemo( () => getSimplifiedDocumentColumns({}), [] ) // 🔥 필터 필드들을 메모이제이션 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: SimplifiedDocumentsView) => doc.drawingKind === 'B4') }, [data]) // 🔥 최종 필터 필드 메모이제이션 const finalFilterFields = React.useMemo(() => { return hasB4Documents ? [...advancedFilterFields, ...b4FilterFields] : advancedFilterFields }, [hasB4Documents, advancedFilterFields, b4FilterFields]) // 🔥 테이블 초기 상태 메모이제이션 const tableInitialState = React.useMemo(() => ({ sorting: [{ id: "createdAt" as const, desc: true }], columnPinning: { right: ["actions"] }, }), []) // 🔥 getRowId 함수 메모이제이션 const getRowId = React.useCallback((originalRow: SimplifiedDocumentsView) => String(originalRow.documentId), []) const { table } = useDataTable({ data, // 서버에서 이미 필터링된 데이터 사용 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 || !serverB4Stats) return null return serverB4Stats }, [hasB4Documents, serverB4Stats]) return (
{/* DrawingKind 정보 간단 표시 */} {kindInfo && (
{/* 주석 처리된 부분은 그대로 유지 */}
{data.length} documents
)} {/* 🔥 필터 섹션 - Project Code 필터와 B4 필터를 함께 배치 */}
{/* Project Code 필터 드롭다운 */}
{projectCode !== 'all' && ( )}
{/* B4 필터 버튼 - URL searchParams 업데이트로 변경 */} {hasB4Documents && b4Stats && (
)}
{/* 테이블 */}
) }