summaryrefslogtreecommitdiff
path: root/lib/bidding/list
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bidding/list')
-rw-r--r--lib/bidding/list/biddings-table.tsx12
-rw-r--r--lib/bidding/list/edit-bidding-sheet.tsx578
2 files changed, 1 insertions, 589 deletions
diff --git a/lib/bidding/list/biddings-table.tsx b/lib/bidding/list/biddings-table.tsx
index 35d57726..f7d57cd7 100644
--- a/lib/bidding/list/biddings-table.tsx
+++ b/lib/bidding/list/biddings-table.tsx
@@ -67,9 +67,6 @@ export function BiddingsTable({ promises }: BiddingsTableProps) {
// 상세 페이지로 이동 (info 페이지로)
router.push(`/evcp/bid/${rowAction.row.original.id}/info`)
break
- case "update":
- // EditBiddingSheet는 아래에서 별도로 처리
- break
case "specification_meeting":
setSpecMeetingDialogOpen(true)
break
@@ -175,14 +172,7 @@ export function BiddingsTable({ promises }: BiddingsTableProps) {
/>
</DataTableAdvancedToolbar>
</DataTable>
-
- <EditBiddingSheet
- open={rowAction?.type === "update"}
- onOpenChange={() => setRowAction(null)}
- bidding={rowAction?.row.original}
- onSuccess={() => router.refresh()}
- />
-
+
{/* 사양설명회 다이얼로그 */}
<SpecificationMeetingDialog
open={specMeetingDialogOpen}
diff --git a/lib/bidding/list/edit-bidding-sheet.tsx b/lib/bidding/list/edit-bidding-sheet.tsx
deleted file mode 100644
index 23f76f4a..00000000
--- a/lib/bidding/list/edit-bidding-sheet.tsx
+++ /dev/null
@@ -1,578 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { useRouter } from "next/navigation"
-import { useForm } from "react-hook-form"
-import { zodResolver } from "@hookform/resolvers/zod"
-import { Loader2 } from "lucide-react"
-import { toast } from "sonner"
-import { useSession } from "next-auth/react"
-
-import { Button } from "@/components/ui/button"
-import {
- Sheet,
- SheetContent,
- SheetDescription,
- SheetHeader,
- SheetTitle,
-} from "@/components/ui/sheet"
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
- FormDescription,
-} from "@/components/ui/form"
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select"
-import { Input } from "@/components/ui/input"
-import { Textarea } from "@/components/ui/textarea"
-import { Switch } from "@/components/ui/switch"
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
-
-import { updateBidding, type UpdateBiddingInput } from "@/lib/bidding/service"
-import {
- updateBiddingSchema,
- type UpdateBiddingSchema
-} from "@/lib/bidding/validation"
-import { BiddingListView } from "@/db/schema"
-import {
- biddingStatusLabels,
- contractTypeLabels,
- biddingTypeLabels,
- awardCountLabels
-} from "@/db/schema"
-import { formatDate } from "@/lib/utils"
-
-interface EditBiddingSheetProps {
- open: boolean
- onOpenChange: (open: boolean) => void
- bidding: BiddingListView | null
- onSuccess?: () => void
-}
-
-export function EditBiddingSheet({
- open,
- onOpenChange,
- bidding,
- onSuccess
-}: EditBiddingSheetProps) {
- const router = useRouter()
- const [isSubmitting, setIsSubmitting] = React.useState(false)
- const { data: session } = useSession()
-
- const form = useForm<UpdateBiddingSchema>({
- resolver: zodResolver(updateBiddingSchema),
- defaultValues: {
- biddingNumber: "",
- revision: 0,
- projectName: "",
- itemName: "",
- title: "",
- description: "",
- content: "",
-
- contractType: "general",
- biddingType: "equipment",
- awardCount: "single",
- contractStartDate: "",
- contractEndDate: "",
-
- preQuoteDate: "",
- biddingRegistrationDate: "",
- submissionStartDate: "",
- submissionEndDate: "",
- evaluationDate: "",
-
- hasSpecificationMeeting: false,
- hasPrDocument: false,
- prNumber: "",
-
- currency: "KRW",
- budget: "",
- targetPrice: "",
- finalBidPrice: "",
-
- isPublic: false,
- isUrgent: false,
-
- status: "bidding_generated",
- managerName: "",
- managerEmail: "",
- managerPhone: "",
-
- remarks: "",
- },
- })
-
- // 시트가 열릴 때 기존 데이터로 폼 초기화
- React.useEffect(() => {
- if (open && bidding) {
- form.reset({
- biddingNumber: bidding.biddingNumber || "",
- revision: bidding.revision || 0,
- projectName: bidding.projectName || "",
- itemName: bidding.itemName || "",
- title: bidding.title || "",
- description: bidding.description || "",
- content: bidding.content || "",
-
- contractType: bidding.contractType || "general",
- biddingType: bidding.biddingType || "equipment",
- awardCount: bidding.awardCount || "single",
- contractStartDate: formatDate(bidding.contractStartDate, "kr"),
- contractEndDate: formatDate(bidding.contractEndDate, "kr"),
-
- preQuoteDate: formatDate(bidding.preQuoteDate, "kr"),
- biddingRegistrationDate: formatDate(bidding.biddingRegistrationDate, "kr"),
- submissionStartDate: formatDate(bidding.submissionStartDate, "kr"),
- submissionEndDate: formatDate(bidding.submissionEndDate, "kr"),
- evaluationDate: formatDate(bidding.evaluationDate, "kr"),
-
- hasSpecificationMeeting: bidding.hasSpecificationMeeting || false,
- hasPrDocument: bidding.hasPrDocument || false,
- prNumber: bidding.prNumber || "",
-
- currency: bidding.currency || "KRW",
- budget: bidding.budget?.toString() || "",
- targetPrice: bidding.targetPrice?.toString() || "",
- finalBidPrice: bidding.finalBidPrice?.toString() || "",
-
- status: bidding.status || "bidding_generated",
- isPublic: bidding.isPublic || false,
- isUrgent: bidding.isUrgent || false,
- managerName: bidding.managerName || "",
- managerEmail: bidding.managerEmail || "",
- managerPhone: bidding.managerPhone || "",
-
- remarks: bidding.remarks || "",
- })
- }
- }, [open, bidding, form])
-
- // 폼 제출
- async function onSubmit(data: UpdateBiddingSchema) {
- if (!bidding) return
-
- setIsSubmitting(true)
- try {
- const userId = session?.user?.id?.toString() || "1"
- const input: UpdateBiddingInput = {
- id: bidding.id,
- ...data,
- }
-
- const result = await updateBidding(input, userId)
-
- if (result.success) {
- toast.success(result.message)
- onOpenChange(false)
- onSuccess?.()
- } else {
- toast.error(result.error || "입찰 수정에 실패했습니다.")
- }
- } catch (error) {
- console.error("Error updating bidding:", error)
- toast.error("입찰 수정 중 오류가 발생했습니다.")
- } finally {
- setIsSubmitting(false)
- }
- }
-
- // 시트 닫기 핸들러
- const handleOpenChange = (open: boolean) => {
- onOpenChange(open)
- if (!open) {
- form.reset()
- }
- }
-
- if (!bidding) {
- return null
- }
-
- return (
- <Sheet open={open} onOpenChange={handleOpenChange}>
- <SheetContent className="flex flex-col h-full sm:max-w-2xl overflow-hidden">
- <SheetHeader className="flex-shrink-0 text-left pb-6">
- <SheetTitle>입찰 수정</SheetTitle>
- <SheetDescription>
- 입찰 정보를 수정합니다. ({bidding.biddingNumber})
- </SheetDescription>
- </SheetHeader>
-
- <Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col flex-1 min-h-0">
- {/* 스크롤 가능한 컨텐츠 영역 */}
- <div className="flex-1 overflow-y-auto pr-2 -mr-2">
- <div className="space-y-6">
- {/* 기본 정보 */}
- <Card>
- <CardHeader>
- <CardTitle className="text-lg">기본 정보</CardTitle>
- </CardHeader>
- <CardContent className="space-y-4">
- <div className="grid grid-cols-2 gap-4">
- <FormField
- control={form.control}
- name="biddingNumber"
- render={({ field }) => (
- <FormItem>
- <FormLabel>입찰번호</FormLabel>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="revision"
- render={({ field }) => (
- <FormItem>
- <FormLabel>리비전</FormLabel>
- <FormControl>
- <Input
- type="number"
- min="0"
- {...field}
- onChange={(e) => field.onChange(parseInt(e.target.value) || 0)}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
-
- <FormField
- control={form.control}
- name="title"
- render={({ field }) => (
- <FormItem>
- <FormLabel>입찰명</FormLabel>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <div className="grid grid-cols-2 gap-4">
- <FormField
- control={form.control}
- name="projectName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>프로젝트명</FormLabel>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="itemName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>품목명</FormLabel>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
- </CardContent>
- </Card>
-
- {/* 계약 정보 */}
- <Card>
- <CardHeader>
- <CardTitle className="text-lg">계약 정보</CardTitle>
- </CardHeader>
- <CardContent className="space-y-4">
- <div className="grid grid-cols-2 gap-4">
- <FormField
- control={form.control}
- name="contractType"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약구분</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {Object.entries(contractTypeLabels).map(([value, label]) => (
- <SelectItem key={value} value={value}>
- {label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="biddingType"
- render={({ field }) => (
- <FormItem>
- <FormLabel>입찰유형</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {Object.entries(biddingTypeLabels).map(([value, label]) => (
- <SelectItem key={value} value={value}>
- {label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
-
- {/* 계약 기간 */}
- <div className="grid grid-cols-2 gap-4">
- <FormField
- control={form.control}
- name="contractStartDate"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약 시작일</FormLabel>
- <FormControl>
- <Input
- type="date"
- {...field}
- min="1900-01-01"
- max="2100-12-31"
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="contractEndDate"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약 종료일</FormLabel>
- <FormControl>
- <Input
- type="date"
- {...field}
- min="1900-01-01"
- max="2100-12-31"
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
-
- {/* <FormField
- control={form.control}
- name="status"
- render={({ field }) => (
- <FormItem>
- <FormLabel>상태</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {Object.entries(biddingStatusLabels).map(([value, label]) => (
- <SelectItem key={value} value={value}>
- {label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- /> */}
-
- <div className="space-y-3">
- <FormField
- control={form.control}
- name="isPublic"
- render={({ field }) => (
- <FormItem className="flex flex-row items-center justify-between rounded-lg border p-3">
- <div className="space-y-0.5">
- <FormLabel className="text-sm">
- 공개 입찰
- </FormLabel>
- <FormDescription className="text-xs">
- 공개 입찰 여부를 설정합니다
- </FormDescription>
- </div>
- <FormControl>
- <Switch
- checked={field.value}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="isUrgent"
- render={({ field }) => (
- <FormItem className="flex flex-row items-center justify-between rounded-lg border p-3">
- <div className="space-y-0.5">
- <FormLabel className="text-sm">
- 긴급 입찰
- </FormLabel>
- <FormDescription className="text-xs">
- 긴급 입찰 여부를 설정합니다
- </FormDescription>
- </div>
- <FormControl>
- <Switch
- checked={field.value}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- </FormItem>
- )}
- />
- </div>
- </CardContent>
- </Card>
-
- {/* 담당자 정보 */}
- <Card>
- <CardHeader>
- <CardTitle className="text-lg">담당자 정보</CardTitle>
- </CardHeader>
- <CardContent className="space-y-4">
- <FormField
- control={form.control}
- name="managerName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>담당자명</FormLabel>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <div className="grid grid-cols-2 gap-4">
- <FormField
- control={form.control}
- name="managerEmail"
- render={({ field }) => (
- <FormItem>
- <FormLabel>이메일</FormLabel>
- <FormControl>
- <Input type="email" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="managerPhone"
- render={({ field }) => (
- <FormItem>
- <FormLabel>전화번호</FormLabel>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
- </CardContent>
- </Card>
-
- {/* 비고 */}
- <Card>
- <CardHeader>
- <CardTitle className="text-lg">비고</CardTitle>
- </CardHeader>
- <CardContent>
- <FormField
- control={form.control}
- name="remarks"
- render={({ field }) => (
- <FormItem>
- <FormControl>
- <Textarea
- placeholder="추가 메모나 특이사항"
- {...field}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </CardContent>
- </Card>
- </div>
- </div>
-
- {/* 고정된 버튼 영역 */}
- <div className="flex-shrink-0 flex justify-end gap-3 pt-6 mt-6 border-t bg-background">
- <Button
- type="button"
- variant="outline"
- onClick={() => handleOpenChange(false)}
- disabled={isSubmitting}
- >
- 취소
- </Button>
- <Button
- type="submit"
- disabled={isSubmitting}
- >
- {isSubmitting && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
- 수정
- </Button>
- </div>
- </form>
- </Form>
- </SheetContent>
- </Sheet>
- )
-} \ No newline at end of file