summaryrefslogtreecommitdiff
path: root/lib/bidding/detail/table
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bidding/detail/table')
-rw-r--r--lib/bidding/detail/table/bidding-detail-content.tsx6
-rw-r--r--lib/bidding/detail/table/bidding-detail-header.tsx103
-rw-r--r--lib/bidding/detail/table/bidding-detail-items-dialog.tsx1
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-columns.tsx25
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx9
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-table.tsx69
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx11
-rw-r--r--lib/bidding/detail/table/bidding-vendor-prices-dialog.tsx2
8 files changed, 6 insertions, 220 deletions
diff --git a/lib/bidding/detail/table/bidding-detail-content.tsx b/lib/bidding/detail/table/bidding-detail-content.tsx
index a96509a9..895016a2 100644
--- a/lib/bidding/detail/table/bidding-detail-content.tsx
+++ b/lib/bidding/detail/table/bidding-detail-content.tsx
@@ -35,7 +35,7 @@ export function BiddingDetailContent({
award: false
})
- const [refreshTrigger, setRefreshTrigger] = React.useState(0)
+ const [, setRefreshTrigger] = React.useState(0)
// PR 아이템 다이얼로그 관련 state
const [isItemDetailsDialogOpen, setIsItemDetailsDialogOpen] = React.useState(false)
@@ -80,14 +80,10 @@ export function BiddingDetailContent({
bidding={bidding}
vendors={quotationVendors}
onRefresh={handleRefresh}
- onOpenItemsDialog={() => openDialog('items')}
onOpenTargetPriceDialog={() => openDialog('targetPrice')}
onOpenSelectionReasonDialog={() => openDialog('selectionReason')}
- onOpenAwardDialog={() => openDialog('award')}
onViewItemDetails={handleViewItemDetails}
onEdit={undefined}
- onDelete={undefined}
- onSelectWinner={undefined}
/>
<BiddingDetailItemsDialog
diff --git a/lib/bidding/detail/table/bidding-detail-header.tsx b/lib/bidding/detail/table/bidding-detail-header.tsx
deleted file mode 100644
index 8d18472f..00000000
--- a/lib/bidding/detail/table/bidding-detail-header.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-'use client'
-
-import * as React from 'react'
-import { useRouter } from 'next/navigation'
-import { Bidding, biddingStatusLabels, contractTypeLabels, biddingTypeLabels } from '@/db/schema'
-import { Badge } from '@/components/ui/badge'
-import { Button } from '@/components/ui/button'
-import {
- ArrowLeft,
- Send,
- RotateCcw,
- XCircle,
- Calendar,
- Building2,
- User,
- Package,
- DollarSign,
- Hash
-} from 'lucide-react'
-
-import { formatDate } from '@/lib/utils'
-import {
- registerBidding,
- markAsDisposal,
- createRebidding
-} from '@/lib/bidding/detail/service'
-import { useToast } from '@/hooks/use-toast'
-import { useTransition } from 'react'
-
-interface BiddingDetailHeaderProps {
- bidding: Bidding
-}
-
-export function BiddingDetailHeader({ bidding }: BiddingDetailHeaderProps) {
- const router = useRouter()
- const { toast } = useToast()
- const [isPending, startTransition] = useTransition()
-
- const handleGoBack = () => {
- router.push('/evcp/bid')
- }
-
- return (
- <div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
- <div className="px-6 py-4">
- {/* 헤더 메인 영역 */}
- <div className="flex items-center justify-between mb-4">
- <div className="flex items-center gap-4 flex-1 min-w-0">
- {/* 제목과 배지 */}
- <div className="flex items-center gap-3 flex-1 min-w-0">
- <h1 className="text-xl font-semibold truncate">{bidding.title}</h1>
- <div className="flex items-center gap-2 flex-shrink-0">
- <Badge variant="outline" className="font-mono text-xs">
- <Hash className="w-3 h-3 mr-1" />
- {bidding.biddingNumber}
- {bidding.revision && bidding.revision > 0 && ` Rev.${bidding.revision}`}
- </Badge>
- <Badge variant={
- bidding.status === 'bidding_disposal' ? 'destructive' :
- bidding.status === 'vendor_selected' ? 'default' :
- 'secondary'
- } className="text-xs">
- {biddingStatusLabels[bidding.status]}
- </Badge>
- </div>
- </div>
- </div>
- </div>
-
- {/* 세부 정보 영역 */}
-
- {/* 일정 정보 */}
- {/* {(bidding.submissionStartDate || bidding.evaluationDate || bidding.preQuoteDate || bidding.biddingRegistrationDate) && (
- <div className="flex flex-wrap items-center gap-4 mt-3 pt-3 border-t border-border/50">
- <Calendar className="w-4 h-4 text-muted-foreground flex-shrink-0" />
- <div className="flex flex-wrap items-center gap-4 text-sm text-muted-foreground">
- {bidding.submissionStartDate && bidding.submissionEndDate && (
- <div>
- <span className="font-medium">제출기간:</span> {formatDate(bidding.submissionStartDate, 'KR')} ~ {formatDate(bidding.submissionEndDate, 'KR')}
- </div>
- )}
- {bidding.evaluationDate && (
- <div>
- <span className="font-medium">평가일:</span> {formatDate(bidding.evaluationDate, 'KR')}
- </div>
- )}
- {bidding.preQuoteDate && (
- <div>
- <span className="font-medium">사전견적일:</span> {formatDate(bidding.preQuoteDate, 'KR')}
- </div>
- )}
- {bidding.biddingRegistrationDate && (
- <div>
- <span className="font-medium">입찰등록일:</span> {formatDate(bidding.biddingRegistrationDate, 'KR')}
- </div>
- )}
- </div>
- </div>
- )} */}
- </div>
- </div>
- )
-} \ No newline at end of file
diff --git a/lib/bidding/detail/table/bidding-detail-items-dialog.tsx b/lib/bidding/detail/table/bidding-detail-items-dialog.tsx
index 2bab3ef0..8c2ae44a 100644
--- a/lib/bidding/detail/table/bidding-detail-items-dialog.tsx
+++ b/lib/bidding/detail/table/bidding-detail-items-dialog.tsx
@@ -17,7 +17,6 @@ import {
TableHeader,
TableRow,
} from '@/components/ui/table'
-import { Badge } from '@/components/ui/badge'
import { formatDate } from '@/lib/utils'
interface PrItem {
diff --git a/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx b/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx
index 3b42cc88..782c5f7a 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx
@@ -6,7 +6,7 @@ import { Checkbox } from "@/components/ui/checkbox"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
- MoreHorizontal, Edit, Trash2, Trophy
+ MoreHorizontal
} from "lucide-react"
import {
DropdownMenu,
@@ -20,8 +20,6 @@ import { QuotationVendor } from "@/lib/bidding/detail/service"
interface GetVendorColumnsProps {
onEdit: (vendor: QuotationVendor) => void
- onDelete: (vendor: QuotationVendor) => void
- onSelectWinner: (vendor: QuotationVendor) => void
onViewPriceAdjustment?: (vendor: QuotationVendor) => void
onViewItemDetails?: (vendor: QuotationVendor) => void
onSendBidding?: (vendor: QuotationVendor) => void
@@ -30,9 +28,6 @@ interface GetVendorColumnsProps {
export function getBiddingDetailVendorColumns({
onEdit,
- onDelete,
- onSelectWinner,
- onViewPriceAdjustment,
onViewItemDetails,
onSendBidding,
onUpdateParticipation
@@ -182,17 +177,6 @@ export function getBiddingDetailVendorColumns({
<span className="text-xs text-muted-foreground ml-2">(입찰참여 필요)</span>
)}
</DropdownMenuItem>
- {vendor.status !== 'selected' && (
- <DropdownMenuItem
- onClick={() => onSelectWinner(vendor)}
- disabled={vendor.isBiddingParticipated !== true}
- >
- 낙찰 선정
- {vendor.isBiddingParticipated !== true && (
- <span className="text-xs text-muted-foreground ml-2">(입찰참여 필요)</span>
- )}
- </DropdownMenuItem>
- )}
{/* 입찰 참여여부 관리 */}
{vendor.isBiddingParticipated === null && onUpdateParticipation && (
@@ -217,13 +201,6 @@ export function getBiddingDetailVendorColumns({
</>
)}
- <DropdownMenuSeparator />
- <DropdownMenuItem
- onClick={() => onDelete(vendor)}
- className="text-destructive"
- >
- 삭제
- </DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
diff --git a/lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx b/lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx
index e029d536..f43e850a 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx
@@ -4,8 +4,6 @@ import * as React from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
-import { Textarea } from '@/components/ui/textarea'
-import { Checkbox } from '@/components/ui/checkbox'
import {
Dialog,
DialogContent,
@@ -14,13 +12,6 @@ import {
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog'
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from '@/components/ui/select'
import { updateBiddingDetailVendor } from '@/lib/bidding/detail/service'
import { QuotationVendor } from '@/lib/bidding/detail/service'
import { useToast } from '@/hooks/use-toast'
diff --git a/lib/bidding/detail/table/bidding-detail-vendor-table.tsx b/lib/bidding/detail/table/bidding-detail-vendor-table.tsx
index a9778636..3e8adda9 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-table.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-table.tsx
@@ -7,33 +7,22 @@ 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 { BiddingDetailVendorToolbarActions } from './bidding-detail-vendor-toolbar-actions'
-import { BiddingDetailVendorCreateDialog } from './bidding-detail-vendor-create-dialog'
import { BiddingDetailVendorEditDialog } from './bidding-detail-vendor-edit-dialog'
import { BiddingAwardDialog } from './bidding-award-dialog'
import { getBiddingDetailVendorColumns } from './bidding-detail-vendor-columns'
import { QuotationVendor, getPriceAdjustmentFormByBiddingCompanyId } from '@/lib/bidding/detail/service'
import { Bidding } from '@/db/schema'
import { PriceAdjustmentDialog } from '@/components/bidding/price-adjustment-dialog'
-import {
- deleteQuotationVendor,
- selectWinner
-} from '@/lib/bidding/detail/service'
-import { selectWinnerSchema } from '@/lib/bidding/validation'
import { useToast } from '@/hooks/use-toast'
-import { useTransition, useCallback } from 'react'
interface BiddingDetailVendorTableContentProps {
biddingId: number
bidding: Bidding
vendors: QuotationVendor[]
onRefresh: () => void
- onOpenItemsDialog: () => void
onOpenTargetPriceDialog: () => void
onOpenSelectionReasonDialog: () => void
- onOpenAwardDialog: () => void
onEdit?: (vendor: QuotationVendor) => void
- onDelete?: (vendor: QuotationVendor) => void
- onSelectWinner?: (vendor: QuotationVendor) => void
onViewItemDetails?: (vendor: QuotationVendor) => void
}
@@ -93,18 +82,12 @@ export function BiddingDetailVendorTableContent({
bidding,
vendors,
onRefresh,
- onOpenItemsDialog,
onOpenTargetPriceDialog,
- onOpenSelectionReasonDialog,
- onOpenAwardDialog,
onEdit,
- onDelete,
- onSelectWinner,
onViewItemDetails
}: BiddingDetailVendorTableContentProps) {
const { data: session } = useSession()
const { toast } = useToast()
- const [isPending, startTransition] = useTransition()
// 세션에서 사용자 ID 가져오기
const userId = session?.user?.id || ''
@@ -114,52 +97,6 @@ export function BiddingDetailVendorTableContent({
const [priceAdjustmentData, setPriceAdjustmentData] = React.useState<any>(null)
const [isPriceAdjustmentDialogOpen, setIsPriceAdjustmentDialogOpen] = React.useState(false)
- const handleSelectWinner = useCallback((vendor: QuotationVendor) => {
- if (!vendor.awardRatio || vendor.awardRatio <= 0) {
- toast({
- title: '오류',
- description: '발주비율을 먼저 설정해주세요.',
- variant: 'destructive',
- })
- return
- }
-
- if (!confirm(`${vendor.vendorName} 업체를 낙찰자로 선정하시겠습니까?`)) return
-
- startTransition(async () => {
- const result = selectWinnerSchema.safeParse({
- biddingId,
- vendorId: vendor.id,
- awardRatio: vendor.awardRatio || 0,
- })
-
- if (!result.success) {
- toast({
- title: '유효성 오류',
- description: result.error.issues[0]?.message || '입력값을 확인해주세요.',
- variant: 'destructive',
- })
- return
- }
-
- const response = await selectWinner(biddingId, vendor.id, vendor.awardRatio || 0, userId)
-
- if (response.success) {
- toast({
- title: '성공',
- description: response.message,
- })
- onRefresh()
- } else {
- toast({
- title: '오류',
- description: response.error,
- variant: 'destructive',
- })
- }
- })
- }, [toast, startTransition, biddingId, userId, selectWinnerSchema, selectWinner, onRefresh])
-
const handleEdit = (vendor: QuotationVendor) => {
setSelectedVendor(vendor)
setIsEditDialogOpen(true)
@@ -192,12 +129,10 @@ export function BiddingDetailVendorTableContent({
const columns = React.useMemo(
() => getBiddingDetailVendorColumns({
onEdit: onEdit || handleEdit,
- onDelete: onDelete,
- onSelectWinner: onSelectWinner || handleSelectWinner,
onViewPriceAdjustment: handleViewPriceAdjustment,
onViewItemDetails: onViewItemDetails
}),
- [onEdit, onDelete, onSelectWinner, handleEdit, handleSelectWinner, handleViewPriceAdjustment, onViewItemDetails]
+ [onEdit, handleEdit, handleViewPriceAdjustment, onViewItemDetails]
)
const { table } = useDataTable({
@@ -224,11 +159,9 @@ export function BiddingDetailVendorTableContent({
shallow={false}
>
<BiddingDetailVendorToolbarActions
- table={table}
biddingId={biddingId}
bidding={bidding}
userId={userId}
- onOpenItemsDialog={onOpenItemsDialog}
onOpenTargetPriceDialog={onOpenTargetPriceDialog}
onOpenAwardDialog={() => setIsAwardDialogOpen(true)}
onSuccess={onRefresh}
diff --git a/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx b/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
index eec44bb1..5d1bfde7 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
@@ -1,12 +1,11 @@
"use client"
import * as React from "react"
-import { type Table } from "@tanstack/react-table"
import { useRouter } from "next/navigation"
import { useTransition } from "react"
import { Button } from "@/components/ui/button"
import { Plus, Send, RotateCcw, XCircle, Trophy, FileText, DollarSign } from "lucide-react"
-import { QuotationVendor, registerBidding, markAsDisposal, createRebidding, awardBidding } from "@/lib/bidding/detail/service"
+import { registerBidding, markAsDisposal, createRebidding } from "@/lib/bidding/detail/service"
import { sendBiddingBasicContracts, getSelectedVendorsForBidding } from "@/lib/bidding/pre-quote/service"
import { BiddingDetailVendorCreateDialog } from "./bidding-detail-vendor-create-dialog"
@@ -17,22 +16,18 @@ import { useToast } from "@/hooks/use-toast"
import { BiddingInvitationDialog } from "./bidding-invitation-dialog"
interface BiddingDetailVendorToolbarActionsProps {
- table: Table<QuotationVendor>
biddingId: number
bidding: Bidding
userId: string
- onOpenItemsDialog: () => void
onOpenTargetPriceDialog: () => void
onOpenAwardDialog: () => void
onSuccess: () => void
}
export function BiddingDetailVendorToolbarActions({
- table,
biddingId,
bidding,
userId,
- onOpenItemsDialog,
onOpenTargetPriceDialog,
onOpenAwardDialog,
onSuccess
@@ -306,7 +301,7 @@ export function BiddingDetailVendorToolbarActions({
biddingTitle={bidding.title}
budget={bidding.budget ? parseFloat(bidding.budget.toString()) : null}
targetPrice={bidding.targetPrice ? parseFloat(bidding.targetPrice.toString()) : null}
- currency={bidding.currency}
+ currency={bidding.currency || ''}
/>
<BiddingInvitationDialog
@@ -315,7 +310,7 @@ export function BiddingDetailVendorToolbarActions({
vendors={selectedVendors}
biddingId={biddingId}
biddingTitle={bidding.title || ''}
- projectName={bidding.projectName}
+ projectName={bidding.projectName || ''}
onSend={handleBiddingInvitationSend}
/>
</>
diff --git a/lib/bidding/detail/table/bidding-vendor-prices-dialog.tsx b/lib/bidding/detail/table/bidding-vendor-prices-dialog.tsx
index fb54eaba..c12ac1df 100644
--- a/lib/bidding/detail/table/bidding-vendor-prices-dialog.tsx
+++ b/lib/bidding/detail/table/bidding-vendor-prices-dialog.tsx
@@ -28,7 +28,6 @@ import {
TrendingUp
} from 'lucide-react'
import { useToast } from '@/hooks/use-toast'
-import { useTransition } from 'react'
import { getVendorPricesForBidding } from '../service'
interface VendorPrice {
@@ -70,7 +69,6 @@ export function BiddingVendorPricesDialog({
currency = 'KRW'
}: BiddingVendorPricesDialogProps) {
const { toast } = useToast()
- const [isPending, startTransition] = useTransition()
const [vendorPrices, setVendorPrices] = React.useState<VendorPrice[]>([])
const [isLoading, setIsLoading] = React.useState(false)
const [viewMode, setViewMode] = React.useState<'quantity' | 'weight'>('quantity')