diff options
Diffstat (limited to 'lib/bidding/list')
| -rw-r--r-- | lib/bidding/list/biddings-table.tsx | 12 | ||||
| -rw-r--r-- | lib/bidding/list/edit-bidding-sheet.tsx | 578 |
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 |
