diff options
Diffstat (limited to 'lib/b-rfq/vendor-response/waive-response-dialog.tsx')
| -rw-r--r-- | lib/b-rfq/vendor-response/waive-response-dialog.tsx | 210 |
1 files changed, 0 insertions, 210 deletions
diff --git a/lib/b-rfq/vendor-response/waive-response-dialog.tsx b/lib/b-rfq/vendor-response/waive-response-dialog.tsx deleted file mode 100644 index 5ded4da3..00000000 --- a/lib/b-rfq/vendor-response/waive-response-dialog.tsx +++ /dev/null @@ -1,210 +0,0 @@ -// components/rfq/waive-response-dialog.tsx -"use client"; - -import { useState } from "react"; -import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogTrigger, -} from "@/components/ui/dialog"; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from "@/components/ui/form"; -import { Textarea } from "@/components/ui/textarea"; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import * as z from "zod"; -import { FileX, Loader2, AlertTriangle } from "lucide-react"; -import { useToast } from "@/hooks/use-toast"; -import { useRouter } from "next/navigation"; - -const waiveFormSchema = z.object({ - responseComment: z.string().min(1, "포기 사유를 입력해주세요"), - vendorComment: z.string().optional(), -}); - -type WaiveFormData = z.infer<typeof waiveFormSchema>; - -interface WaiveResponseDialogProps { - responseId: number; - attachmentType: string; - serialNo: string; - trigger?: React.ReactNode; - onSuccess?: () => void; -} - -export function WaiveResponseDialog({ - responseId, - attachmentType, - serialNo, - trigger, - onSuccess, -}: WaiveResponseDialogProps) { - const [open, setOpen] = useState(false); - const [isSubmitting, setIsSubmitting] = useState(false); - const { toast } = useToast(); - const router = useRouter(); - - const form = useForm<WaiveFormData>({ - resolver: zodResolver(waiveFormSchema), - defaultValues: { - responseComment: "", - vendorComment: "", - }, - }); - - const onSubmit = async (data: WaiveFormData) => { - setIsSubmitting(true); - - try { - const response = await fetch("/api/vendor-responses/waive", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - responseId, - responseComment: data.responseComment, - vendorComment: data.vendorComment, - }), - }); - - if (!response.ok) { - const error = await response.json(); - throw new Error(error.message || "응답 포기 처리 실패"); - } - - toast({ - title: "응답 포기 완료", - description: "해당 항목에 대한 응답이 포기 처리되었습니다.", - }); - - setOpen(false); - form.reset(); - - router.refresh(); - onSuccess?.(); - - } catch (error) { - console.error("Waive error:", error); - toast({ - title: "처리 실패", - description: error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.", - variant: "destructive", - }); - } finally { - setIsSubmitting(false); - } - }; - - return ( - <Dialog open={open} onOpenChange={setOpen}> - <DialogTrigger asChild> - {trigger || ( - <Button size="sm" variant="outline"> - <FileX className="h-3 w-3 mr-1" /> - 포기 - </Button> - )} - </DialogTrigger> - <DialogContent className="max-w-lg"> - <DialogHeader> - <DialogTitle className="flex items-center gap-2 text-orange-600"> - <FileX className="h-5 w-5" /> - 응답 포기 - </DialogTitle> - <div className="flex items-center gap-2 text-sm text-muted-foreground"> - <Badge variant="outline">{serialNo}</Badge> - <span>{attachmentType}</span> - </div> - </DialogHeader> - - <div className="bg-orange-50 border border-orange-200 rounded-lg p-4 mb-4"> - <div className="flex items-center gap-2 text-orange-800 text-sm font-medium mb-2"> - <AlertTriangle className="h-4 w-4" /> - 주의사항 - </div> - <p className="text-orange-700 text-sm"> - 응답을 포기하면 해당 항목에 대한 입찰 참여가 불가능합니다. - 포기 사유를 명확히 기입해 주세요. - </p> - </div> - - <Form {...form}> - <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6"> - {/* 포기 사유 (필수) */} - <FormField - control={form.control} - name="responseComment" - render={({ field }) => ( - <FormItem> - <FormLabel className="text-red-600"> - 포기 사유 <span className="text-red-500">*</span> - </FormLabel> - <FormControl> - <Textarea - placeholder="응답을 포기하는 사유를 구체적으로 입력하세요..." - className="resize-none" - rows={4} - {...field} - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 내부 코멘트 (선택) */} - <FormField - control={form.control} - name="vendorComment" - render={({ field }) => ( - <FormItem> - <FormLabel>내부 코멘트 (선택)</FormLabel> - <FormControl> - <Textarea - placeholder="내부 참고용 코멘트를 입력하세요..." - className="resize-none" - rows={2} - {...field} - /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 버튼 */} - <div className="flex justify-end gap-2"> - <Button - type="button" - variant="outline" - onClick={() => setOpen(false)} - disabled={isSubmitting} - > - 취소 - </Button> - <Button - type="submit" - variant="destructive" - disabled={isSubmitting} - > - {isSubmitting && <Loader2 className="h-4 w-4 mr-2 animate-spin" />} - {isSubmitting ? "처리 중..." : "포기하기"} - </Button> - </div> - </form> - </Form> - </DialogContent> - </Dialog> - ); -}
\ No newline at end of file |
