"use client" import * as React from "react" import type { DataTableAdvancedFilterField, DataTableFilterField, DataTableRowAction, } from "@/types/table" import { useRouter } from "next/navigation" import { useDataTable } from "@/hooks/use-data-table" import { DataTable } from "@/components/data-table/data-table" import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar" import { useFeatureFlags } from "./feature-flags-provider" import { getColumns } from "./rfqs-table-columns" import { RfqWithAll } from "../types" import { fetchRfqAttachments, fetchRfqAttachmentsbyCommentId, } from "../../rfqs/service" import { RfqsVendorTableToolbarActions } from "./rfqs-table-toolbar-actions" import { RfqsItemsDialog } from "./ItemsDialog" import { RfqAttachmentsSheet } from "./attachment-rfq-sheet" import { CommentSheet } from "./comments-sheet" import { getRfqResponsesForVendor } from "../service" import { useSession } from "next-auth/react" // Next-auth session hook 추가 interface RfqsTableProps { promises: Promise<[Awaited>]> } // 코멘트+첨부파일 구조 예시 export interface RfqCommentWithAttachments { id: number commentText: string commentedBy?: number commentedByEmail?: string createdAt?: Date attachments?: { id: number fileName: string filePath: string }[] } export interface ExistingAttachment { id: number fileName: string filePath: string createdAt?: Date vendorId?: number | null size?: number } export interface ExistingItem { id?: number itemCode: string description: string | null quantity: number | null uom: string | null } export function RfqsVendorTable({ promises }: RfqsTableProps) { const { featureFlags } = useFeatureFlags() const { data: session } = useSession() // 세션 정보 가져오기 // 1) 테이블 데이터( RFQs ) const [{ data: responseData, pageCount }] = React.use(promises) // 데이터를 RfqWithAll 타입으로 변환 (id 필드 추가) const data: RfqWithAll[] = React.useMemo(() => { return responseData.map(item => ({ ...item, id: item.rfqId, // id 필드를 rfqId와 동일하게 설정 })); }, [responseData]); const router = useRouter() // 2) 첨부파일 시트 + 관련 상태 const [attachmentsOpen, setAttachmentsOpen] = React.useState(false) const [selectedRfqIdForAttachments, setSelectedRfqIdForAttachments] = React.useState(null) const [attachDefault, setAttachDefault] = React.useState([]) // 3) 코멘트 시트 + 관련 상태 const [initialComments, setInitialComments] = React.useState([]) const [commentSheetOpen, setCommentSheetOpen] = React.useState(false) const [selectedRfqIdForComments, setSelectedRfqIdForComments] = React.useState(null) // 4) rowAction으로 다양한 모달/시트 열기 const [rowAction, setRowAction] = React.useState | null>(null) // 열리고 닫힐 때마다, rowAction 등을 확인해서 시트 열기/닫기 처리 React.useEffect(() => { if (rowAction?.type === "comments" && rowAction?.row.original) { openCommentSheet(rowAction.row.original.id) } }, [rowAction]) /** * (A) 코멘트 시트를 열기 전에, * DB에서 (rfqId에 해당하는) 코멘트들 + 각 코멘트별 첨부파일을 조회. */ const openCommentSheet = React.useCallback(async (rfqId: number) => { setInitialComments([]) // 여기서 rowAction을 직접 참조하지 않고, 필요한 데이터만 파라미터로 받기 const comments = data.find(rfq => rfq.rfqId === rfqId)?.comments || [] if (comments && comments.length > 0) { const commentWithAttachments = await Promise.all( comments.map(async (c) => { const attachments = await fetchRfqAttachmentsbyCommentId(c.id) return { ...c, commentedBy: c.commentedBy || 1, attachments, } }) ) setInitialComments(commentWithAttachments) } setSelectedRfqIdForComments(rfqId) setCommentSheetOpen(true) }, [data]) // data만 의존성으로 추가 /** * (B) 첨부파일 시트 열기 */ const openAttachmentsSheet = React.useCallback(async (rfqId: number) => { const list = await fetchRfqAttachments(rfqId) setAttachDefault(list) setSelectedRfqIdForAttachments(rfqId) setAttachmentsOpen(true) }, []) // 5) DataTable 컬럼 세팅 const columns = React.useMemo( () => getColumns({ setRowAction, router, openAttachmentsSheet, openCommentSheet }), [setRowAction, router, openAttachmentsSheet, openCommentSheet] ) /** * 간단한 filterFields 예시 */ const filterFields: DataTableFilterField[] = [ { id: "rfqCode", label: "RFQ Code", placeholder: "Filter RFQ Code...", }, { id: "projectName", label: "Project", placeholder: "Filter Project...", }, { id: "rfqDescription", label: "Description", placeholder: "Filter Description...", }, ] /** * Advanced filter fields 예시 */ const advancedFilterFields: DataTableAdvancedFilterField[] = [ { id: "rfqCode", label: "RFQ Code", type: "text", }, { id: "rfqDescription", label: "Description", type: "text", }, { id: "projectCode", label: "Project Code", type: "text", }, { id: "projectName", label: "Project Name", type: "text", }, { id: "rfqDueDate", label: "Due Date", type: "date", }, { id: "responseStatus", label: "Response Status", type: "select", options: [ { label: "Reviewing", value: "REVIEWING" }, { label: "Accepted", value: "ACCEPTED" }, { label: "Declined", value: "DECLINED" }, ], } ] // useDataTable() 훅 -> pagination, sorting 등 관리 const { table } = useDataTable({ data, columns, pageCount, filterFields, enablePinning: true, enableAdvancedFilter: true, initialState: { sorting: [{ id: "respondedAt", desc: true }], columnPinning: { right: ["actions"] }, }, getRowId: (originalRow) => String(originalRow.id), shallow: false, clearOnDefault: true, }) const currentUserId = session?.user?.id ? parseInt(session.user.id, 10) : 0 const currentVendorId = session?.user?.id ? session.user.companyId : 0 return ( <> {/* 1) 아이템 목록 Dialog */} {rowAction?.type === "items" && rowAction?.row.original && ( setRowAction(null)} rfq={rowAction.row.original} /> )} {/* 2) 코멘트 시트 */} {selectedRfqIdForComments && ( )} {/* 3) 첨부파일 시트 */} ) }