diff options
Diffstat (limited to 'lib/bidding/pre-quote/table/bidding-pre-quote-vendor-columns.tsx')
| -rw-r--r-- | lib/bidding/pre-quote/table/bidding-pre-quote-vendor-columns.tsx | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/lib/bidding/pre-quote/table/bidding-pre-quote-vendor-columns.tsx b/lib/bidding/pre-quote/table/bidding-pre-quote-vendor-columns.tsx deleted file mode 100644 index 3266a568..00000000 --- a/lib/bidding/pre-quote/table/bidding-pre-quote-vendor-columns.tsx +++ /dev/null @@ -1,398 +0,0 @@ -"use client" - -import * as React from "react" -import { type ColumnDef } from "@tanstack/react-table" -import { Checkbox } from "@/components/ui/checkbox" -import { Badge } from "@/components/ui/badge" -import { Button } from "@/components/ui/button" -import { - MoreHorizontal, Edit, Trash2, Paperclip -} from "lucide-react" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu" - -// bidding_companies 테이블 타입 정의 (company_condition_responses와 join) -export interface BiddingCompany { - id: number - biddingId: number - companyId: number - invitationStatus: 'pending' | 'sent' | 'accepted' | 'declined' | 'submitted' - invitedAt: Date | null - respondedAt: Date | null - preQuoteAmount: string | null - preQuoteSubmittedAt: Date | null - preQuoteDeadline: Date | null - isPreQuoteSelected: boolean - isPreQuoteParticipated: boolean | null - isAttendingMeeting: boolean | null - notes: string | null - contactPerson: string | null - contactEmail: string | null - contactPhone: string | null - createdAt: Date - updatedAt: Date - - // company_condition_responses 필드들 - paymentTermsResponse: string | null - taxConditionsResponse: string | null - proposedContractDeliveryDate: string | null - priceAdjustmentResponse: boolean | null - isInitialResponse: boolean | null - incotermsResponse: string | null - proposedShippingPort: string | null - proposedDestinationPort: string | null - sparePartResponse: string | null - additionalProposals: string | null - - // 조인된 업체 정보 - companyName?: string - companyCode?: string -} - -interface GetBiddingCompanyColumnsProps { - onEdit: (company: BiddingCompany) => void - onDelete: (company: BiddingCompany) => void - onViewPriceAdjustment?: (company: BiddingCompany) => void - onViewItemDetails?: (company: BiddingCompany) => void - onViewAttachments?: (company: BiddingCompany) => void -} - -export function getBiddingPreQuoteVendorColumns({ - onEdit, - onDelete, - onViewPriceAdjustment, - onViewItemDetails, - onViewAttachments -}: GetBiddingCompanyColumnsProps): ColumnDef<BiddingCompany>[] { - return [ - { - id: 'select', - header: ({ table }) => ( - <Checkbox - checked={table.getIsAllPageRowsSelected()} - onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)} - aria-label="모두 선택" - /> - ), - cell: ({ row }) => ( - <Checkbox - checked={row.getIsSelected()} - onCheckedChange={(value) => row.toggleSelected(!!value)} - aria-label="행 선택" - /> - ), - enableSorting: false, - enableHiding: false, - }, - { - accessorKey: 'companyName', - header: '업체명', - cell: ({ row }) => ( - <div className="font-medium">{row.original.companyName || '-'}</div> - ), - }, - { - accessorKey: 'companyCode', - header: '업체코드', - cell: ({ row }) => ( - <div className="font-mono text-sm">{row.original.companyCode || '-'}</div> - ), - }, - { - accessorKey: 'invitationStatus', - header: '초대 상태', - cell: ({ row }) => { - const status = row.original.invitationStatus - let variant: any - let label: string - - if (status === 'accepted') { - variant = 'default' - label = '수락' - } else if (status === 'declined') { - variant = 'destructive' - label = '거절' - } else if (status === 'pending') { - variant = 'outline' - label = '대기중' - } else if (status === 'sent') { - variant = 'outline' - label = '요청됨' - } else if (status === 'submitted') { - variant = 'outline' - label = '제출됨' - } else { - variant = 'outline' - label = status || '-' - } - - return <Badge variant={variant}>{label}</Badge> - }, - }, - { - accessorKey: 'preQuoteAmount', - header: '사전견적금액', - cell: ({ row }) => { - const hasAmount = row.original.preQuoteAmount && Number(row.original.preQuoteAmount) > 0 - return ( - <div className="text-right font-mono"> - {hasAmount ? ( - <button - onClick={() => onViewItemDetails?.(row.original)} - className="text-primary hover:text-primary/80 hover:underline cursor-pointer" - title="품목별 견적 상세 보기" - > - {Number(row.original.preQuoteAmount).toLocaleString()} KRW - </button> - ) : ( - <span className="text-muted-foreground">-</span> - )} - </div> - ) - }, - }, - { - accessorKey: 'preQuoteSubmittedAt', - header: '사전견적 제출일', - cell: ({ row }) => ( - <div className="text-sm"> - {row.original.preQuoteSubmittedAt ? new Date(row.original.preQuoteSubmittedAt).toLocaleDateString('ko-KR') : '-'} - </div> - ), - }, - { - accessorKey: 'preQuoteDeadline', - header: '사전견적 마감일', - cell: ({ row }) => { - const deadline = row.original.preQuoteDeadline - if (!deadline) { - return <div className="text-muted-foreground text-sm">-</div> - } - - const now = new Date() - const deadlineDate = new Date(deadline) - const isExpired = deadlineDate < now - - return ( - <div className={`text-sm ${isExpired ? 'text-red-600' : ''}`}> - <div>{deadlineDate.toLocaleDateString('ko-KR')}</div> - {isExpired && ( - <Badge variant="destructive" className="text-xs mt-1"> - 마감 - </Badge> - )} - </div> - ) - }, - }, - { - accessorKey: 'attachments', - header: '첨부파일', - cell: ({ row }) => { - const hasAttachments = row.original.preQuoteSubmittedAt // 제출된 경우에만 첨부파일이 있을 수 있음 - return ( - <div className="text-center"> - {hasAttachments ? ( - <Button - variant="ghost" - size="sm" - onClick={() => onViewAttachments?.(row.original)} - className="h-8 w-8 p-0" - title="첨부파일 보기" - > - <Paperclip className="h-4 w-4" /> - </Button> - ) : ( - <span className="text-muted-foreground text-sm">-</span> - )} - </div> - ) - }, - }, - { - accessorKey: 'isPreQuoteParticipated', - header: '사전견적 참여의사', - cell: ({ row }) => { - const participated = row.original.isPreQuoteParticipated - if (participated === null) { - return <Badge variant="outline">미결정</Badge> - } - return ( - <Badge variant={participated ? 'default' : 'destructive'}> - {participated ? '참여' : '미참여'} - </Badge> - ) - }, - }, - { - accessorKey: 'isPreQuoteSelected', - header: '본입찰 선정', - cell: ({ row }) => ( - <Badge variant={row.original.isPreQuoteSelected ? 'default' : 'secondary'}> - {row.original.isPreQuoteSelected ? '선정' : '미선정'} - </Badge> - ), - }, - { - accessorKey: 'isAttendingMeeting', - header: '사양설명회 참석', - cell: ({ row }) => { - const isAttending = row.original.isAttendingMeeting - if (isAttending === null) return <div className="text-sm">-</div> - return ( - <Badge variant={isAttending ? 'default' : 'secondary'}> - {isAttending ? '참석' : '불참석'} - </Badge> - ) - }, - }, - { - accessorKey: 'paymentTermsResponse', - header: '지급조건', - cell: ({ row }) => ( - <div className="text-sm max-w-32 truncate" title={row.original.paymentTermsResponse || ''}> - {row.original.paymentTermsResponse || '-'} - </div> - ), - }, - { - accessorKey: 'taxConditionsResponse', - header: '세금조건', - cell: ({ row }) => ( - <div className="text-sm max-w-32 truncate" title={row.original.taxConditionsResponse || ''}> - {row.original.taxConditionsResponse || '-'} - </div> - ), - }, - { - accessorKey: 'incotermsResponse', - header: '운송조건', - cell: ({ row }) => ( - <div className="text-sm max-w-24 truncate" title={row.original.incotermsResponse || ''}> - {row.original.incotermsResponse || '-'} - </div> - ), - }, - { - accessorKey: 'isInitialResponse', - header: '초도여부', - cell: ({ row }) => { - const isInitial = row.original.isInitialResponse - if (isInitial === null) return <div className="text-sm">-</div> - return ( - <Badge variant={isInitial ? 'default' : 'secondary'}> - {isInitial ? 'Y' : 'N'} - </Badge> - ) - }, - }, - { - accessorKey: 'priceAdjustmentResponse', - header: '연동제', - cell: ({ row }) => { - const hasPriceAdjustment = row.original.priceAdjustmentResponse - if (hasPriceAdjustment === null) return <div className="text-sm">-</div> - return ( - <div className="flex items-center gap-2"> - <Badge variant={hasPriceAdjustment ? 'default' : 'secondary'}> - {hasPriceAdjustment ? '적용' : '미적용'} - </Badge> - {hasPriceAdjustment && onViewPriceAdjustment && ( - <Button - variant="ghost" - size="sm" - onClick={() => onViewPriceAdjustment(row.original)} - className="h-6 px-2 text-xs" - > - 상세 - </Button> - )} - </div> - ) - }, - }, - { - accessorKey: 'proposedContractDeliveryDate', - header: '제안납기일', - cell: ({ row }) => ( - <div className="text-sm"> - {row.original.proposedContractDeliveryDate ? - new Date(row.original.proposedContractDeliveryDate).toLocaleDateString('ko-KR') : '-'} - </div> - ), - }, - { - accessorKey: 'proposedShippingPort', - header: '제안선적지', - cell: ({ row }) => ( - <div className="text-sm max-w-24 truncate" title={row.original.proposedShippingPort || ''}> - {row.original.proposedShippingPort || '-'} - </div> - ), - }, - { - accessorKey: 'proposedDestinationPort', - header: '제안하역지', - cell: ({ row }) => ( - <div className="text-sm max-w-24 truncate" title={row.original.proposedDestinationPort || ''}> - {row.original.proposedDestinationPort || '-'} - </div> - ), - }, - { - accessorKey: 'sparePartResponse', - header: '스페어파트', - cell: ({ row }) => ( - <div className="text-sm max-w-24 truncate" title={row.original.sparePartResponse || ''}> - {row.original.sparePartResponse || '-'} - </div> - ), - }, - { - accessorKey: 'additionalProposals', - header: '추가제안', - cell: ({ row }) => ( - <div className="text-sm max-w-32 truncate" title={row.original.additionalProposals || ''}> - {row.original.additionalProposals || '-'} - </div> - ), - }, - { - id: 'actions', - header: '액션', - cell: ({ row }) => { - const company = row.original - - return ( - <DropdownMenu> - <DropdownMenuTrigger asChild> - <Button variant="ghost" className="h-8 w-8 p-0"> - <span className="sr-only">메뉴 열기</span> - <MoreHorizontal className="h-4 w-4" /> - </Button> - </DropdownMenuTrigger> - <DropdownMenuContent align="end"> - {/* <DropdownMenuItem onClick={() => onEdit(company)}> - <Edit className="mr-2 h-4 w-4" /> - 수정 - </DropdownMenuItem> */} - <DropdownMenuItem - onClick={() => onDelete(company)} - className="text-destructive" - > - <Trash2 className="mr-2 h-4 w-4" /> - 삭제 - </DropdownMenuItem> - </DropdownMenuContent> - </DropdownMenu> - ) - }, - }, - ] -} |
