'use client' import * as React from 'react' import { useRouter } from 'next/navigation' import type { DataTableAdvancedFilterField, DataTableFilterField, } from '@/types/table' import { useDataTable } from '@/hooks/use-data-table' import { useToast } from '@/hooks/use-toast' import { DataTable } from '@/components/data-table/data-table' import { DataTableAdvancedToolbar } from '@/components/data-table/data-table-advanced-toolbar' import { getPartnersBiddingListColumns } from './partners-bidding-list-columns' import { PartnersBiddingListItem } from '../detail/service' import { PartnersBiddingToolbarActions } from './partners-bidding-toolbar-actions' import { PartnersSpecificationMeetingDialog } from './partners-bidding-attendance-dialog' import { PartnersBiddingAttachmentsDialog } from './partners-bidding-attachments-dialog' interface PartnersBiddingListProps { companyId: number promises: Promise<[PartnersBiddingListItem[]]> } export function PartnersBiddingList({ promises }: PartnersBiddingListProps) { const [biddingData] = React.use(promises) const [rowAction, setRowAction] = React.useState<{ type: string; row: { original: PartnersBiddingListItem } } | null>(null) // const [selectedBiddingForSpecificationMeetingParticipation] = React.useState(null) const [isAttachmentsDialogOpen, setIsAttachmentsDialogOpen] = React.useState(false) const [selectedBiddingForAttachments, setSelectedBiddingForAttachments] = React.useState(null) const router = useRouter() const { toast } = useToast() React.useEffect(() => { if (rowAction) { const bidding = rowAction.row.original switch (rowAction.type) { case 'view': // 사전견적 요청 상태에서는 상세보기 제한 if (bidding.status === 'request_for_quotation' || bidding.status === 'received_quotation' || bidding.status === 'set_target_price') { toast({ title: '접근 제한', description: '사전견적 상태에서는 본입찰을 이용할 수 없습니다.', variant: 'destructive', }) return } if (bidding.status === 'bidding_opened' && !bidding.isBiddingInvited) { // 본입찰이 오픈되었지만 초대받지 않은 경우 toast({ title: '접근 제한', description: '본입찰에 초대받지 않은 업체입니다.', variant: 'destructive', }) return } // 상세 페이지로 이동 (biddingId 사용) router.push(`/partners/bid/${bidding.biddingId}`) break case 'pre-quote': // 사전견적 페이지로 이동 // 사전견적에 초대받지 않은 벤더는 bidding status가 bidding_opened 이고 isPreQuoteParticipated이 null일 경우, 초대받지 않은 것으로 판단 if (bidding.status === 'bidding_opened' && bidding.isPreQuoteParticipated === null) { toast({ title: '접근 제한', description: '사전견적에 초대받지 않은 업체입니다.', variant: 'destructive', }) return } router.push(`/partners/bid/${bidding.biddingId}/pre-quote`) break case 'view-documents': // 첨부파일 다이얼로그 열기 setSelectedBiddingForAttachments(rowAction.row.original) setIsAttachmentsDialogOpen(true) setRowAction(null) // rowAction 초기화 break default: break } } }, [rowAction, router, toast]) const columns = React.useMemo( () => getPartnersBiddingListColumns({ setRowAction }), [setRowAction] ) const filterFields: DataTableFilterField[] = [ { id: 'title', label: '입찰명', placeholder: '입찰명으로 검색...', }, { id: 'biddingNumber', label: '입찰번호', placeholder: '입찰번호로 검색...', }, { id: 'itemName', label: '품목명', placeholder: '품목명으로 검색...', }, { id: 'projectName', label: '프로젝트명', placeholder: '프로젝트명으로 검색...', }, { id: 'managerName', label: '담당자', placeholder: '담당자로 검색...', }, { id: 'invitationStatus', label: '참여의사', placeholder: '참여의사로 필터링...', }, { id: 'status', label: '입찰상태', placeholder: '입찰상태로 필터링...', }, ] const advancedFilterFields: DataTableAdvancedFilterField[] = [ { id: 'title', label: '입찰명', type: 'text' }, { id: 'biddingNumber', label: '입찰번호', type: 'text' }, { id: 'itemName', label: '품목명', type: 'text' }, { id: 'projectName', label: '프로젝트명', type: 'text' }, { id: 'managerName', label: '담당자', type: 'text' }, { id: 'contractType', label: '계약구분', type: 'text' }, { id: 'invitationStatus', label: '참여의사', type: 'text' }, { id: 'status', label: '입찰상태', type: 'text' }, { id: 'submissionStartDate', label: '입찰시작일', type: 'date' }, { id: 'submissionEndDate', label: '입찰마감일', type: 'date' }, { id: 'responseDeadline', label: '참여회신마감일', type: 'date' }, { id: 'createdAt', label: '등록일', type: 'date' }, { id: 'updatedAt', label: '수정일', type: 'date' }, ] const { table } = useDataTable({ data: biddingData, columns, pageCount: 1, filterFields, enableAdvancedFilter: true, initialState: { sorting: [{ id: 'createdAt', desc: true }], columnPinning: { right: ['actions'] }, }, getRowId: (originalRow) => String(originalRow.id), shallow: false, clearOnDefault: true, }) return ( <> setRowAction(null)} biddingDetail={rowAction?.row.original ? { id: rowAction.row.original.biddingId, biddingNumber: rowAction.row.original.biddingNumber, title: rowAction.row.original.title, preQuoteDate: null, biddingRegistrationDate: rowAction.row.original.submissionStartDate?.toISOString() || null, evaluationDate: null, hasSpecificationMeeting: rowAction.row.original.hasSpecificationMeeting || false, } : null} biddingCompanyId={rowAction?.row.original?.biddingCompanyId || 0} isAttending={rowAction?.row.original?.isAttendingMeeting || null} /> ) }