summaryrefslogtreecommitdiff
path: root/lib/bidding/detail
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-09 10:34:05 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-09 10:34:05 +0000
commit86b1fd1cc801f45642f84d24c0b5c84368454ff0 (patch)
tree63176d1feb6d3fbbb71d942343056ba6d793b586 /lib/bidding/detail
parentc62ec046327fd388ebce04571b55910747e69a3b (diff)
(최겸) 구매 입찰 사전견적, 입찰, 낙찰, 유찰, 재입찰 기능 개발
Diffstat (limited to 'lib/bidding/detail')
-rw-r--r--lib/bidding/detail/service.ts62
-rw-r--r--lib/bidding/detail/table/bidding-detail-content.tsx42
-rw-r--r--lib/bidding/detail/table/bidding-detail-header.tsx49
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-columns.tsx43
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx27
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-table.tsx20
-rw-r--r--lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx29
7 files changed, 172 insertions, 100 deletions
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts
index 956c1798..d9bcb255 100644
--- a/lib/bidding/detail/service.ts
+++ b/lib/bidding/detail/service.ts
@@ -71,7 +71,7 @@ export interface QuotationVendor {
quotationAmount: number // 견적금액
currency: string
submissionDate: string // 제출일
- isWinner: boolean // 낙찰여부
+ isWinner: boolean | null // 낙찰여부 (null: 미정, true: 낙찰, false: 탈락)
awardRatio: number | null // 발주비율
isBiddingParticipated: boolean | null // 본입찰 참여여부
status: 'pending' | 'submitted' | 'selected' | 'rejected'
@@ -262,7 +262,7 @@ export async function getQuotationVendors(biddingId: number): Promise<QuotationV
quotationAmount: Number(vendor.quotationAmount) || 0,
currency: vendor.currency,
submissionDate: vendor.submissionDate ? (vendor.submissionDate instanceof Date ? vendor.submissionDate.toISOString().split('T')[0] : String(vendor.submissionDate).split('T')[0]) : '',
- isWinner: vendor.isWinner || false,
+ isWinner: vendor.isWinner,
awardRatio: vendor.awardRatio ? Number(vendor.awardRatio) : null,
isBiddingParticipated: vendor.isBiddingParticipated,
status: vendor.status as 'pending' | 'submitted' | 'selected' | 'rejected',
@@ -1208,7 +1208,7 @@ export async function uploadAwardDocument(biddingId: number, file: File, userId:
originalFileName: file.name,
filePath: saveResult.filePath,
fileSize: file.size,
- documentType: 'award',
+ documentType: 'other',
title: '낙찰 관련 문서',
description: '낙찰 관련 첨부파일',
uploadedBy: userId,
@@ -1347,7 +1347,7 @@ export async function awardBidding(biddingId: number, selectionReason: string, u
eq(biddingCompanies.biddingId, biddingId),
eq(biddingCompanies.isWinner, true)
))
-
+
if (awardedCompanies.length === 0) {
return { success: false, error: '낙찰된 업체가 없습니다. 먼저 발주비율을 산정해주세요.' }
}
@@ -1373,27 +1373,40 @@ export async function awardBidding(biddingId: number, selectionReason: string, u
// 2. 선정 사유 저장 (첫 번째 낙찰 업체 기준으로 저장)
const firstAwardedCompany = awardedCompanies[0]
- await tx
- .insert(vendorSelectionResults)
- .values({
- biddingId,
- selectedCompanyId: firstAwardedCompany.companyId,
- selectionReason,
- selectedBy: userId,
- selectedAt: new Date(),
- createdAt: new Date(),
- updatedAt: new Date()
- })
- .onConflictDoUpdate({
- target: [vendorSelectionResults.biddingId],
- set: {
+
+ // 기존 선정 결과 확인
+ const existingResult = await tx
+ .select()
+ .from(vendorSelectionResults)
+ .where(eq(vendorSelectionResults.biddingId, biddingId))
+ .limit(1)
+
+ if (existingResult.length > 0) {
+ // 업데이트
+ await tx
+ .update(vendorSelectionResults)
+ .set({
selectedCompanyId: firstAwardedCompany.companyId,
selectionReason,
selectedBy: userId,
selectedAt: new Date(),
updatedAt: new Date()
- }
- })
+ })
+ .where(eq(vendorSelectionResults.biddingId, biddingId))
+ } else {
+ // 삽입
+ await tx
+ .insert(vendorSelectionResults)
+ .values({
+ biddingId,
+ selectedCompanyId: firstAwardedCompany.companyId,
+ selectionReason,
+ selectedBy: userId,
+ selectedAt: new Date(),
+ createdAt: new Date(),
+ updatedAt: new Date()
+ })
+ }
})
@@ -1644,12 +1657,14 @@ export interface PartnersBiddingListItem {
isWinner: boolean | null
isAttendingMeeting: boolean | null
isPreQuoteSelected: boolean | null
+ isPreQuoteParticipated: boolean | null
+ preQuoteDeadline: Date | null
isBiddingInvited: boolean | null
notes: string | null
createdAt: Date
updatedAt: Date
// updatedBy: string | null
-
+ hasSpecificationMeeting: boolean | null
// biddings 정보
biddingId: number
biddingNumber: string
@@ -1688,6 +1703,8 @@ export async function getBiddingListForPartners(companyId: number): Promise<Part
isWinner: biddingCompanies.isWinner,
isAttendingMeeting: biddingCompanies.isAttendingMeeting,
isPreQuoteSelected: biddingCompanies.isPreQuoteSelected,
+ isPreQuoteParticipated: biddingCompanies.isPreQuoteParticipated,
+ preQuoteDeadline: biddingCompanies.preQuoteDeadline,
isBiddingInvited: biddingCompanies.isBiddingInvited,
notes: biddingCompanies.notes,
createdAt: biddingCompanies.createdAt,
@@ -1712,6 +1729,7 @@ export async function getBiddingListForPartners(companyId: number): Promise<Part
managerPhone: biddings.managerPhone,
currency: biddings.currency,
budget: biddings.budget,
+ hasSpecificationMeeting: biddings.hasSpecificationMeeting,
})
.from(biddingCompanies)
.innerJoin(biddings, eq(biddingCompanies.biddingId, biddings.id))
@@ -1791,6 +1809,8 @@ export async function getBiddingDetailsForPartners(biddingId: number, companyId:
isAttendingMeeting: biddingCompanies.isAttendingMeeting,
isPreQuoteSelected: biddingCompanies.isPreQuoteSelected,
isBiddingParticipated: biddingCompanies.isBiddingParticipated,
+ isPreQuoteParticipated: biddingCompanies.isPreQuoteParticipated,
+ hasSpecificationMeeting: biddings.hasSpecificationMeeting,
// 응답한 조건들 (company_condition_responses) - 제시된 조건과 응답 모두 여기서 관리
paymentTermsResponse: companyConditionResponses.paymentTermsResponse,
taxConditionsResponse: companyConditionResponses.taxConditionsResponse,
diff --git a/lib/bidding/detail/table/bidding-detail-content.tsx b/lib/bidding/detail/table/bidding-detail-content.tsx
index 91bea2f4..a96509a9 100644
--- a/lib/bidding/detail/table/bidding-detail-content.tsx
+++ b/lib/bidding/detail/table/bidding-detail-content.tsx
@@ -7,6 +7,10 @@ import { QuotationDetails, QuotationVendor } from '@/lib/bidding/detail/service'
import { BiddingDetailVendorTableContent } from './bidding-detail-vendor-table'
import { BiddingDetailItemsDialog } from './bidding-detail-items-dialog'
import { BiddingDetailTargetPriceDialog } from './bidding-detail-target-price-dialog'
+import { BiddingPreQuoteItemDetailsDialog } from '../../../bidding/pre-quote/table/bidding-pre-quote-item-details-dialog'
+import { getPrItemsForBidding } from '../../../bidding/pre-quote/service'
+import { useToast } from '@/hooks/use-toast'
+import { useTransition } from 'react'
interface BiddingDetailContentProps {
bidding: Bidding
@@ -21,6 +25,9 @@ export function BiddingDetailContent({
quotationVendors,
prItems
}: BiddingDetailContentProps) {
+ const { toast } = useToast()
+ const [isPending, startTransition] = useTransition()
+
const [dialogStates, setDialogStates] = React.useState({
items: false,
targetPrice: false,
@@ -29,6 +36,11 @@ export function BiddingDetailContent({
})
const [refreshTrigger, setRefreshTrigger] = React.useState(0)
+
+ // PR 아이템 다이얼로그 관련 state
+ const [isItemDetailsDialogOpen, setIsItemDetailsDialogOpen] = React.useState(false)
+ const [selectedVendorForDetails, setSelectedVendorForDetails] = React.useState<QuotationVendor | null>(null)
+ const [prItemsForDialog, setPrItemsForDialog] = React.useState<any[]>([])
const handleRefresh = React.useCallback(() => {
setRefreshTrigger(prev => prev + 1)
@@ -42,6 +54,25 @@ export function BiddingDetailContent({
setDialogStates(prev => ({ ...prev, [type]: false }))
}, [])
+ const handleViewItemDetails = React.useCallback((vendor: QuotationVendor) => {
+ startTransition(async () => {
+ try {
+ // PR 아이템 정보 로드
+ const prItemsData = await getPrItemsForBidding(bidding.id)
+ setPrItemsForDialog(prItemsData)
+ setSelectedVendorForDetails(vendor)
+ setIsItemDetailsDialogOpen(true)
+ } catch (error) {
+ console.error('Failed to load PR items:', error)
+ toast({
+ title: '오류',
+ description: '품목 정보를 불러오는데 실패했습니다.',
+ variant: 'destructive',
+ })
+ }
+ })
+ }, [bidding.id, toast])
+
return (
<div className="space-y-6">
<BiddingDetailVendorTableContent
@@ -53,6 +84,7 @@ export function BiddingDetailContent({
onOpenTargetPriceDialog={() => openDialog('targetPrice')}
onOpenSelectionReasonDialog={() => openDialog('selectionReason')}
onOpenAwardDialog={() => openDialog('award')}
+ onViewItemDetails={handleViewItemDetails}
onEdit={undefined}
onDelete={undefined}
onSelectWinner={undefined}
@@ -72,6 +104,16 @@ export function BiddingDetailContent({
bidding={bidding}
onSuccess={handleRefresh}
/>
+
+ <BiddingPreQuoteItemDetailsDialog
+ open={isItemDetailsDialogOpen}
+ onOpenChange={setIsItemDetailsDialogOpen}
+ biddingId={bidding.id}
+ biddingCompanyId={selectedVendorForDetails?.id || 0}
+ companyName={selectedVendorForDetails?.vendorName || ''}
+ prItems={prItemsForDialog}
+ currency={bidding.currency || 'KRW'}
+ />
</div>
)
}
diff --git a/lib/bidding/detail/table/bidding-detail-header.tsx b/lib/bidding/detail/table/bidding-detail-header.tsx
index fcbbeb9a..2798478c 100644
--- a/lib/bidding/detail/table/bidding-detail-header.tsx
+++ b/lib/bidding/detail/table/bidding-detail-header.tsx
@@ -141,50 +141,6 @@ export function BiddingDetailHeader({ bidding }: BiddingDetailHeaderProps) {
})
}
- const getActionButtons = () => {
- const buttons = []
-
- // 기본 액션 버튼들 (항상 표시)
-
-
- // 모든 액션 버튼을 항상 표시 (상태 검증은 각 핸들러에서)
- buttons.push(
- <Button
- key="register"
- onClick={handleRegister}
- disabled={isPending}
- >
- <Send className="w-4 h-4 mr-2" />
- 입찰등록
- </Button>
- )
-
- buttons.push(
- <Button
- key="disposal"
- variant="destructive"
- onClick={handleMarkAsDisposal}
- disabled={isPending}
- >
- <XCircle className="w-4 h-4 mr-2" />
- 유찰
- </Button>
- )
-
- buttons.push(
- <Button
- key="rebidding"
- onClick={handleCreateRebidding}
- disabled={isPending}
- >
- <RotateCcw className="w-4 h-4 mr-2" />
- 재입찰
- </Button>
- )
-
- return buttons
- }
-
return (
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="px-6 py-4">
@@ -209,11 +165,6 @@ export function BiddingDetailHeader({ bidding }: BiddingDetailHeaderProps) {
</Badge>
</div>
</div>
-
- {/* 액션 버튼들 */}
- <div className="flex items-center gap-2 flex-shrink-0">
- {getActionButtons()}
- </div>
</div>
</div>
diff --git a/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx b/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx
index bb1d2c62..cbdf79c2 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-columns.tsx
@@ -23,6 +23,7 @@ interface GetVendorColumnsProps {
onDelete: (vendor: QuotationVendor) => void
onSelectWinner: (vendor: QuotationVendor) => void
onViewPriceAdjustment?: (vendor: QuotationVendor) => void
+ onViewItemDetails?: (vendor: QuotationVendor) => void
onSendBidding?: (vendor: QuotationVendor) => void
onUpdateParticipation?: (vendor: QuotationVendor, participated: boolean) => void
}
@@ -32,6 +33,7 @@ export function getBiddingDetailVendorColumns({
onDelete,
onSelectWinner,
onViewPriceAdjustment,
+ onViewItemDetails,
onSendBidding,
onUpdateParticipation
}: GetVendorColumnsProps): ColumnDef<QuotationVendor>[] {
@@ -72,11 +74,24 @@ export function getBiddingDetailVendorColumns({
{
accessorKey: 'quotationAmount',
header: '견적금액',
- cell: ({ row }) => (
- <div className="text-right font-mono">
- {row.original.quotationAmount ? Number(row.original.quotationAmount).toLocaleString() : '-'} {row.original.currency}
- </div>
- ),
+ cell: ({ row }) => {
+ const hasAmount = row.original.quotationAmount && Number(row.original.quotationAmount) > 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.quotationAmount).toLocaleString()} {row.original.currency}
+ </button>
+ ) : (
+ <span className="text-muted-foreground">- {row.original.currency}</span>
+ )}
+ </div>
+ )
+ },
},
{
accessorKey: 'biddingResult',
@@ -84,7 +99,7 @@ export function getBiddingDetailVendorColumns({
cell: ({ row }) => {
const isWinner = row.original.isWinner
if (isWinner === null || isWinner === undefined) {
- return <div>-</div>
+ return <div>미정</div>
}
return (
<Badge variant={isWinner ? 'default' : 'secondary'} className={isWinner ? 'bg-green-600' : ''}>
@@ -158,12 +173,24 @@ export function getBiddingDetailVendorColumns({
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>작업</DropdownMenuLabel>
- <DropdownMenuItem onClick={() => onEdit(vendor)}>
+ <DropdownMenuItem
+ onClick={() => onEdit(vendor)}
+ disabled={vendor.isBiddingParticipated !== true}
+ >
발주비율 산정
+ {vendor.isBiddingParticipated !== true && (
+ <span className="text-xs text-muted-foreground ml-2">(입찰참여 필요)</span>
+ )}
</DropdownMenuItem>
{vendor.status !== 'selected' && (
- <DropdownMenuItem onClick={() => onSelectWinner(vendor)}>
+ <DropdownMenuItem
+ onClick={() => onSelectWinner(vendor)}
+ disabled={vendor.isBiddingParticipated !== true}
+ >
낙찰 선정
+ {vendor.isBiddingParticipated !== true && (
+ <span className="text-xs text-muted-foreground ml-2">(입찰참여 필요)</span>
+ )}
</DropdownMenuItem>
)}
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 b10212ab..9a5408c2 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-edit-dialog.tsx
@@ -112,6 +112,22 @@ export function BiddingDetailVendorEditDialog({
)}
{/* 수정 가능한 필드들 */}
+ {vendor && vendor.isBiddingParticipated !== true && (
+ <div className="bg-orange-50 border border-orange-200 rounded-lg p-3 mb-4">
+ <div className="flex items-center gap-2 text-orange-800">
+ <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
+ <path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
+ </svg>
+ <span className="font-medium">입찰 참여 안내</span>
+ </div>
+ <p className="text-sm text-orange-700 mt-1">
+ {vendor.isBiddingParticipated === null
+ ? '이 업체는 아직 입찰참여 여부가 결정되지 않았습니다. 입찰에 참여한 업체만 발주비율을 설정할 수 있습니다.'
+ : '이 업체는 입찰에 참여하지 않습니다. 발주비율을 설정할 수 없습니다.'
+ }
+ </p>
+ </div>
+ )}
<div className="space-y-2">
<Label htmlFor="edit-awardRatio">발주비율 (%)</Label>
@@ -123,14 +139,23 @@ export function BiddingDetailVendorEditDialog({
value={formData.awardRatio}
onChange={(e) => setFormData({ ...formData, awardRatio: Number(e.target.value) })}
placeholder="발주비율을 입력하세요"
+ disabled={vendor?.isBiddingParticipated !== true}
/>
+ {vendor?.isBiddingParticipated !== true && (
+ <p className="text-sm text-muted-foreground">
+ 입찰에 참여한 업체만 발주비율을 설정할 수 있습니다.
+ </p>
+ )}
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}>
취소
</Button>
- <Button onClick={handleEdit} disabled={isPending}>
+ <Button
+ onClick={handleEdit}
+ disabled={isPending || vendor?.isBiddingParticipated !== true}
+ >
산정
</Button>
</DialogFooter>
diff --git a/lib/bidding/detail/table/bidding-detail-vendor-table.tsx b/lib/bidding/detail/table/bidding-detail-vendor-table.tsx
index dd1ae94b..95f63ce9 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-table.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-table.tsx
@@ -1,6 +1,7 @@
'use client'
import * as React from 'react'
+import { useSession } from 'next-auth/react'
import { type DataTableAdvancedFilterField, type DataTableFilterField } from '@/types/table'
import { useDataTable } from '@/hooks/use-data-table'
import { DataTable } from '@/components/data-table/data-table'
@@ -33,6 +34,7 @@ interface BiddingDetailVendorTableContentProps {
onEdit?: (vendor: QuotationVendor) => void
onDelete?: (vendor: QuotationVendor) => void
onSelectWinner?: (vendor: QuotationVendor) => void
+ onViewItemDetails?: (vendor: QuotationVendor) => void
}
const filterFields: DataTableFilterField<QuotationVendor>[] = [
@@ -97,10 +99,15 @@ export function BiddingDetailVendorTableContent({
onOpenAwardDialog,
onEdit,
onDelete,
- onSelectWinner
+ onSelectWinner,
+ onViewItemDetails
}: BiddingDetailVendorTableContentProps) {
+ const { data: session } = useSession()
const { toast } = useToast()
const [isPending, startTransition] = useTransition()
+
+ // 세션에서 사용자 ID 가져오기
+ const userId = session?.user?.id || ''
const [selectedVendor, setSelectedVendor] = React.useState<QuotationVendor | null>(null)
const [isEditDialogOpen, setIsEditDialogOpen] = React.useState(false)
const [isAwardDialogOpen, setIsAwardDialogOpen] = React.useState(false)
@@ -145,7 +152,7 @@ export function BiddingDetailVendorTableContent({
const result = selectWinnerSchema.safeParse({
biddingId,
vendorId: vendor.id,
- awardRatio: vendor.awardRatio,
+ awardRatio: vendor.awardRatio || 0,
})
if (!result.success) {
@@ -157,7 +164,7 @@ export function BiddingDetailVendorTableContent({
return
}
- const response = await selectWinner(biddingId, vendor.id, vendor.awardRatio, 'current-user')
+ const response = await selectWinner(biddingId, vendor.id, vendor.awardRatio || 0, userId)
if (response.success) {
toast({
@@ -209,9 +216,10 @@ export function BiddingDetailVendorTableContent({
onEdit: onEdit || handleEdit,
onDelete: onDelete || handleDelete,
onSelectWinner: onSelectWinner || handleSelectWinner,
- onViewPriceAdjustment: handleViewPriceAdjustment
+ onViewPriceAdjustment: handleViewPriceAdjustment,
+ onViewItemDetails: onViewItemDetails
}),
- [onEdit, onDelete, onSelectWinner, handleEdit, handleDelete, handleSelectWinner, handleViewPriceAdjustment]
+ [onEdit, onDelete, onSelectWinner, handleEdit, handleDelete, handleSelectWinner, handleViewPriceAdjustment, onViewItemDetails]
)
const { table } = useDataTable({
@@ -241,9 +249,9 @@ export function BiddingDetailVendorTableContent({
table={table}
biddingId={biddingId}
bidding={bidding}
+ userId={userId}
onOpenItemsDialog={onOpenItemsDialog}
onOpenTargetPriceDialog={onOpenTargetPriceDialog}
- onOpenSelectionReasonDialog={onOpenSelectionReasonDialog}
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 8cdec191..64c31633 100644
--- a/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
+++ b/lib/bidding/detail/table/bidding-detail-vendor-toolbar-actions.tsx
@@ -15,6 +15,7 @@ interface BiddingDetailVendorToolbarActionsProps {
table: Table<QuotationVendor>
biddingId: number
bidding: Bidding
+ userId: string
onOpenItemsDialog: () => void
onOpenTargetPriceDialog: () => void
onOpenAwardDialog: () => void
@@ -25,6 +26,7 @@ export function BiddingDetailVendorToolbarActions({
table,
biddingId,
bidding,
+ userId,
onOpenItemsDialog,
onOpenTargetPriceDialog,
onOpenAwardDialog,
@@ -41,17 +43,17 @@ export function BiddingDetailVendorToolbarActions({
const handleRegister = () => {
startTransition(async () => {
- const result = await registerBidding(bidding.id, 'current-user') // TODO: 실제 사용자 ID
+ const result = await registerBidding(bidding.id, userId)
if (result.success) {
toast({
- title: '성공',
+ title: result.message,
description: result.message,
})
router.refresh()
} else {
toast({
- title: '오류',
+ title: result.error,
description: result.error,
variant: 'destructive',
})
@@ -61,17 +63,17 @@ export function BiddingDetailVendorToolbarActions({
const handleMarkAsDisposal = () => {
startTransition(async () => {
- const result = await markAsDisposal(bidding.id, 'current-user') // TODO: 실제 사용자 ID
+ const result = await markAsDisposal(bidding.id, userId)
if (result.success) {
toast({
- title: '성공',
+ title: result.message,
description: result.message,
})
router.refresh()
} else {
toast({
- title: '오류',
+ title: result.error,
description: result.error,
variant: 'destructive',
})
@@ -81,18 +83,18 @@ export function BiddingDetailVendorToolbarActions({
const handleCreateRebidding = () => {
startTransition(async () => {
- const result = await createRebidding(bidding.id, 'current-user') // TODO: 실제 사용자 ID
+ const result = await createRebidding(bidding.id, userId)
if (result.success) {
toast({
- title: '성공',
+ title: result.message,
description: result.message,
})
router.refresh()
onSuccess()
} else {
toast({
- title: '오류',
+ title: result.error,
description: result.error,
variant: 'destructive',
})
@@ -104,7 +106,7 @@ export function BiddingDetailVendorToolbarActions({
<>
<div className="flex items-center gap-2">
{/* 상태별 액션 버튼 */}
- {bidding.status === 'bidding_generated' && (
+ {bidding.status === 'set_target_price' && (
<Button
variant="default"
size="sm"
@@ -115,8 +117,6 @@ export function BiddingDetailVendorToolbarActions({
입찰 등록
</Button>
)}
-
- {bidding.status === 'bidding_closed' && (
<>
<Button
variant="destructive"
@@ -137,7 +137,6 @@ export function BiddingDetailVendorToolbarActions({
낙찰
</Button>
</>
- )}
{bidding.status === 'bidding_disposal' && (
<Button
@@ -159,13 +158,13 @@ export function BiddingDetailVendorToolbarActions({
)}
{/* 공통 관리 버튼들 */}
- <Button
+ {/* <Button
variant="outline"
size="sm"
onClick={onOpenItemsDialog}
>
품목 정보
- </Button>
+ </Button> */}
<Button
variant="outline"
size="sm"