'use client' import * as React from 'react' import { createColumnHelper } from '@tanstack/react-table' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { CheckCircle, XCircle, FileText, MoreHorizontal, Calendar, User, Paperclip, AlertTriangle } from 'lucide-react' import { formatDate } from '@/lib/utils' import { biddingStatusLabels, contractTypeLabels } from '@/db/schema' import { PartnersBiddingListItem } from '../detail/service' import { Checkbox } from '@/components/ui/checkbox' import { toast } from 'sonner' const columnHelper = createColumnHelper() interface PartnersBiddingListColumnsProps { setRowAction?: (action: { type: string; row: { original: PartnersBiddingListItem } }) => void } export function getPartnersBiddingListColumns({ setRowAction }: PartnersBiddingListColumnsProps = {}) { return [ // select 버튼 { id: "select", header: ({ table }) => ( table.toggleAllPageRowsSelected(!!v)} aria-label="select all" className="translate-y-0.5" /> ), cell: ({ row }) => ( row.toggleSelected(!!v)} aria-label="select row" className="translate-y-0.5" /> ), size: 40, enableSorting: false, enableHiding: false, }, // 입찰 No. columnHelper.accessor('biddingNumber', { header: '입찰 No.', cell: ({ row }) => { const biddingNumber = row.original.biddingNumber const originalBiddingNumber = row.original.originalBiddingNumber const revision = row.original.revision return (
{biddingNumber}
Rev. {revision ?? 0}
{originalBiddingNumber && (
원: {originalBiddingNumber}
)}
) }, }), // 입찰상태 columnHelper.accessor('status', { header: '입찰상태', cell: ({ row }) => { const status = row.original.status return ( {biddingStatusLabels[status] || status} ) }, }), // 긴급여부 columnHelper.accessor('isUrgent', { header: '긴급여부', cell: ({ row }) => { const isUrgent = row.original.isUrgent return isUrgent ? (
긴급
) : (
일반
) }, }), // 첨부파일 columnHelper.display({ id: 'attachments', header: 'SHI 첨부파일', cell: ({ row }) => { const handleViewDocumentsClick = (e: React.MouseEvent) => { e.stopPropagation() if (setRowAction) { setRowAction({ type: 'view-documents', row: { original: row.original } }) } } return ( ) }, size: 80, enableSorting: false, }), // 액션 (드롭다운 메뉴) columnHelper.display({ id: 'actions', header: '액션', cell: ({ row }) => { // 사양설명회 참석여부 체크 함수 const checkSpecificationMeeting = () => { const hasSpecMeeting = row.original.hasSpecificationMeeting const isAttending = row.original.isAttendingMeeting // 사양설명회가 있고, 참석여부가 아직 설정되지 않은 경우 if (hasSpecMeeting && isAttending === null) { toast.warning('사양설명회 참석여부 필요', { description: '사전견적 또는 입찰을 진행하기 전에 사양설명회 참석여부를 먼저 설정해주세요.', duration: 5000, }) return false } return true } const handleView = () => { // 사양설명회 체크 if (!checkSpecificationMeeting()) { return } if (setRowAction) { setRowAction({ type: 'view', row: { original: row.original } }) } } return ( 입찰 상세보기 ) }, }), // 품목명 columnHelper.accessor('itemName', { header: '품목명', cell: ({ row }) => (
{row.original.itemName}
), }), // 입찰명 columnHelper.accessor('title', { header: '입찰명', cell: ({ row }) => (
{row.original.title}
), }), // 사양설명회 columnHelper.accessor('isAttendingMeeting', { header: '사양설명회', cell: ({ row }) => { const isAttending = row.original.isAttendingMeeting if (isAttending === null) { return
-
} return isAttending ? ( ) : ( ) }, }), // 사전견적 참여의사 columnHelper.accessor('isPreQuoteParticipated', { header: '사전견적 참여의사', cell: ({ row }) => { const participated = row.original.isPreQuoteParticipated if (participated === null) { return 미결정 } return ( {participated ? '참여' : '미참여'} ) }, }), // 입찰 참여의사 columnHelper.accessor('isBiddingParticipated', { header: '입찰 참여의사', cell: ({ row }) => { const participated = row.original.isBiddingParticipated if (participated === null) { return 미결정 } return ( {participated ? '참여' : '불참'} ) }, }), // 계약구분 columnHelper.accessor('contractType', { header: '계약구분', cell: ({ row }) => (
{contractTypeLabels[row.original.contractType] || row.original.contractType}
), }), // 입찰기간 columnHelper.accessor('submissionStartDate', { header: '입찰기간', cell: ({ row }) => { const startDate = row.original.submissionStartDate const endDate = row.original.submissionEndDate if (!startDate || !endDate) { return
-
} return (
{formatDate(startDate, 'KR')}
~
{formatDate(endDate, 'KR')}
) }, }), // 사전견적 마감일 columnHelper.accessor('preQuoteDeadline', { header: '사전견적 마감일', cell: ({ row }) => { const deadline = row.original.preQuoteDeadline if (!deadline) { return
-
} const now = new Date() const deadlineDate = new Date(deadline) const isExpired = deadlineDate < now return (
{formatDate(deadline, 'KR')} {isExpired && ( 마감 )}
) }, }), // 계약기간 columnHelper.accessor('contractStartDate', { header: '계약기간', cell: ({ row }) => { const startDate = row.original.contractStartDate const endDate = row.original.contractEndDate if (!startDate || !endDate) { return
-
} return (
{formatDate(startDate, 'KR')}
~
{formatDate(endDate, 'KR')}
) }, }), // 입찰담당자 columnHelper.display({ id: 'bidPicName', header: '입찰담당자', cell: ({ row }) => { const name = row.original.bidPicName if (!name) { return
-
} return (
{name}
) }, }), // 조달담당자 columnHelper.display({ id: 'supplyPicName', header: '조달담당자', cell: ({ row }) => { const name = row.original.supplyPicName if (!name) { return
-
} return (
{name}
) }, }), // 최종수정일 columnHelper.accessor('updatedAt', { header: '최종수정일', cell: ({ row }) => (
{formatDate(row.original.updatedAt, 'KR')}
), }), ] }