diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-04-28 02:13:30 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-04-28 02:13:30 +0000 |
| commit | ef4c533ebacc2cdc97e518f30e9a9350004fcdfb (patch) | |
| tree | 345251a3ed0f4429716fa5edaa31024d8f4cb560 /lib/cbe/table/cbe-table.tsx | |
| parent | 9ceed79cf32c896f8a998399bf1b296506b2cd4a (diff) | |
~20250428 작업사항
Diffstat (limited to 'lib/cbe/table/cbe-table.tsx')
| -rw-r--r-- | lib/cbe/table/cbe-table.tsx | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/lib/cbe/table/cbe-table.tsx b/lib/cbe/table/cbe-table.tsx new file mode 100644 index 00000000..38a0a039 --- /dev/null +++ b/lib/cbe/table/cbe-table.tsx @@ -0,0 +1,192 @@ +"use client" + +import * as React from "react" +import { useRouter } from "next/navigation" +import type { + DataTableAdvancedFilterField, + DataTableFilterField, + DataTableRowAction, +} from "@/types/table" + +import { toSentenceCase } from "@/lib/utils" +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 { getColumns } from "./cbe-table-columns" +import { CommentSheet, CbeComment } from "./comments-sheet" +import { VendorWithCbeFields } from "@/config/vendorCbeColumnsConfig" +import { fetchRfqAttachmentsbyCommentId, getAllCBE } from "@/lib/rfqs/service" +import { VendorsTableToolbarActions } from "./cbe-table-toolbar-actions" +import { InviteVendorsDialog } from "./invite-vendors-dialog" +import { VendorContactsDialog } from "@/lib/rfqs/cbe-table/vendor-contact-dialog" +import { useSession } from "next-auth/react" // Next-auth session hook 추가 + + + +import { toast } from "sonner" + +interface VendorsTableProps { + promises: Promise<[ + Awaited<ReturnType<typeof getAllCBE>>, + ]> +} + +export function AllCbeTable({ promises }: VendorsTableProps) { + + // Suspense로 받아온 데이터 + const [{ data, pageCount }] = React.use(promises) + const { data: session } = useSession() // 세션 정보 가져오기 + + const currentUserId = session?.user?.id ? parseInt(session.user.id, 10) : 0 + const currentUser = session?.user + + const [rowAction, setRowAction] = React.useState<DataTableRowAction<VendorWithCbeFields> | null>(null) + // **router** 획득 + const router = useRouter() + // 댓글 시트 관련 state + const [initialComments, setInitialComments] = React.useState<CbeComment[]>([]) + const [isLoadingComments, setIsLoadingComments] = React.useState(false) + + const [commentSheetOpen, setCommentSheetOpen] = React.useState(false) + const [selectedVendorId, setSelectedVendorId] = React.useState<number | null>(null) + const [selectedCbeId, setSelectedCbeId] = React.useState<number | null>(null) + const [isContactDialogOpen, setIsContactDialogOpen] = React.useState(false) + const [selectedVendor, setSelectedVendor] = React.useState<VendorWithCbeFields | null>(null) + const [selectedRfqId, setSelectedRfqId] = React.useState<number | null>(null) + + // ----------------------------------------------------------- + // 특정 action이 설정될 때마다 실행되는 effect + // ----------------------------------------------------------- + React.useEffect(() => { + if (rowAction?.type === "comments") { + // rowAction가 새로 세팅된 뒤 여기서 openCommentSheet 실행 + openCommentSheet(Number(rowAction.row.original.responseId)) + } + }, [rowAction]) + + // ----------------------------------------------------------- + // 댓글 시트 열기 + // ----------------------------------------------------------- + async function openCommentSheet(responseId: number) { + setInitialComments([]) + setIsLoadingComments(true) + const comments = rowAction?.row.original.comments + const rfqId = rowAction?.row.original.rfqId + const vendorId = rowAction?.row.original.vendorId + try { + if (comments && comments.length > 0) { + const commentWithAttachments: CbeComment[] = await Promise.all( + comments.map(async (c) => { + const attachments = await fetchRfqAttachmentsbyCommentId(c.id) + + return { + ...c, + commentedBy: currentUserId, // DB나 API 응답에 있다고 가정 + attachments, + } + }) + ) + // 3) state에 저장 -> CommentSheet에서 initialComments로 사용 + setInitialComments(commentWithAttachments) + } + + if(vendorId){ setSelectedVendorId(vendorId)} + if(rfqId){ setSelectedRfqId(rfqId)} + setSelectedCbeId(responseId) + setCommentSheetOpen(true) + }catch (error) { + console.error("Error loading comments:", error) + toast.error("Failed to load comments") + } finally { + // End loading regardless of success/failure + setIsLoadingComments(false) + } +} + +const openVendorContactsDialog = (vendorId: number, vendor: VendorWithCbeFields) => { + setSelectedVendorId(vendorId) + setSelectedVendor(vendor) + setIsContactDialogOpen(true) +} + + // ----------------------------------------------------------- + // 테이블 컬럼 + // ----------------------------------------------------------- + const columns = React.useMemo( + () => getColumns({ setRowAction, router, openCommentSheet, openVendorContactsDialog }), + [setRowAction, router] + ) + + // ----------------------------------------------------------- + // 필터 필드 + // ----------------------------------------------------------- + const filterFields: DataTableFilterField<VendorWithCbeFields>[] = [ + // 예: 표준 필터 + ] + const advancedFilterFields: DataTableAdvancedFilterField<VendorWithCbeFields>[] = [ + { id: "vendorName", label: "Vendor Name", type: "text" }, + { id: "vendorCode", label: "Vendor Code", type: "text" }, + { id: "respondedAt", label: "Updated at", type: "date" }, + ] + + // ----------------------------------------------------------- + // 테이블 생성 훅 + // ----------------------------------------------------------- + const { table } = useDataTable({ + data, + columns, + pageCount, + filterFields, + enablePinning: true, + enableAdvancedFilter: true, + initialState: { + sorting: [{ id: "respondedAt", desc: true }], + columnPinning: { right: ["comments"] }, + }, + getRowId: (originalRow) => (`${originalRow.vendorId}${originalRow.rfqId}`), + shallow: false, + clearOnDefault: true, + }) + + return ( + <> + <DataTable table={table}> + <DataTableAdvancedToolbar + table={table} + filterFields={advancedFilterFields} + shallow={false} + > + <VendorsTableToolbarActions table={table} rfqId={selectedRfqId ?? 0} /> + </DataTableAdvancedToolbar> + </DataTable> + + {/* 댓글 시트 */} + <CommentSheet + currentUserId={currentUserId} + open={commentSheetOpen} + onOpenChange={setCommentSheetOpen} + vendorId={selectedVendorId ?? 0} + rfqId={selectedRfqId ?? 0} + cbeId={selectedCbeId ?? 0} + isLoading={isLoadingComments} + initialComments={initialComments} + /> + + <InviteVendorsDialog + vendors={rowAction?.row.original ? [rowAction?.row.original] : []} + onOpenChange={() => setRowAction(null)} + rfqId={selectedRfqId ?? 0} + open={rowAction?.type === "invite"} + showTrigger={false} + currentUser={currentUser} + /> + + <VendorContactsDialog + isOpen={isContactDialogOpen} + onOpenChange={setIsContactDialogOpen} + vendorId={selectedVendorId} + vendor={selectedVendor} + /> + </> + ) +}
\ No newline at end of file |
