"use client" import * as React from "react" import { useState } from "react" import { useRouter } from "next/navigation" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" 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 { Badge } from "@/components/ui/badge" import { ScrollArea } from "@/components/ui/scroll-area" import { CalendarIcon, Save, Send, AlertCircle } from "lucide-react" import { Calendar } from "@/components/ui/calendar" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Alert, AlertDescription } from "@/components/ui/alert" import { formatDate, cn } from "@/lib/utils" import { toast } from "sonner" interface QuotationResponseTabProps { quotation: { id: number status: string totalPrice: string | null currency: string | null validUntil: Date | null remark: string | null rfq: { id: number rfqCode: string | null materialCode: string | null dueDate: Date | null status: string | null item?: { itemName: string | null } | null } | null vendor: { vendorName: string } | null } } const CURRENCIES = [ { value: "KRW", label: "KRW (원)" }, { value: "USD", label: "USD (달러)" }, { value: "EUR", label: "EUR (유로)" }, { value: "JPY", label: "JPY (엔)" }, { value: "CNY", label: "CNY (위안)" }, ] export function QuotationResponseTab({ quotation }: QuotationResponseTabProps) { const [totalPrice, setTotalPrice] = useState(quotation.totalPrice?.toString() || "") const [currency, setCurrency] = useState(quotation.currency || "KRW") const [validUntil, setValidUntil] = useState( quotation.validUntil ? new Date(quotation.validUntil) : undefined ) const [remark, setRemark] = useState(quotation.remark || "") const [isLoading, setIsLoading] = useState(false) const router = useRouter() const rfq = quotation.rfq const isDueDatePassed = rfq?.dueDate ? new Date(rfq.dueDate) < new Date() : false const canSubmit = quotation.status === "Draft" && !isDueDatePassed const canEdit = ["Draft", "Revised"].includes(quotation.status) && !isDueDatePassed const handleSaveDraft = async () => { setIsLoading(true) try { const { updateTechSalesVendorQuotation } = await import("@/lib/techsales-rfq/service") const result = await updateTechSalesVendorQuotation({ id: quotation.id, currency, totalPrice, validUntil: validUntil!, remark, updatedBy: 1 // TODO: 실제 사용자 ID로 변경 }) if (result.error) { toast.error(result.error) } else { toast.success("임시 저장되었습니다.") // 페이지 새로고침 대신 router.refresh() 사용 router.refresh() } } catch { toast.error("저장 중 오류가 발생했습니다.") } finally { setIsLoading(false) } } const handleSubmit = async () => { if (!totalPrice || !currency || !validUntil) { toast.error("모든 필수 항목을 입력해주세요.") return } setIsLoading(true) try { const { submitTechSalesVendorQuotation } = await import("@/lib/techsales-rfq/service") const result = await submitTechSalesVendorQuotation({ id: quotation.id, currency, totalPrice, validUntil: validUntil!, remark, updatedBy: 1 // TODO: 실제 사용자 ID로 변경 }) if (result.error) { toast.error(result.error) } else { toast.success("견적서가 제출되었습니다.") // 페이지 새로고침 대신 router.refresh() 사용 router.refresh() } } catch { toast.error("제출 중 오류가 발생했습니다.") } finally { setIsLoading(false) } } const getStatusBadgeVariant = (status: string) => { switch (status) { case "Draft": return "secondary" case "Submitted": return "default" case "Revised": return "outline" case "Rejected": return "destructive" case "Accepted": return "success" default: return "secondary" } } const getStatusLabel = (status: string) => { switch (status) { case "Draft": return "초안" case "Submitted": return "제출됨" case "Revised": return "수정됨" case "Rejected": return "반려됨" case "Accepted": return "승인됨" default: return status } } return (
{/* 견적서 상태 정보 */} 견적서 상태 {getStatusLabel(quotation.status)} 현재 견적서 상태 및 마감일 정보
견적서 상태
{getStatusLabel(quotation.status)}
RFQ 마감일
{rfq?.dueDate ? formatDate(rfq.dueDate) : "N/A"}
남은 시간
{isDueDatePassed ? ( 마감됨 ) : rfq?.dueDate ? ( {Math.ceil((new Date(rfq.dueDate).getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24))}일 ) : ( "N/A" )}
{isDueDatePassed && ( RFQ 마감일이 지났습니다. 견적서를 수정하거나 제출할 수 없습니다. )} {!canEdit && !isDueDatePassed && ( 현재 상태에서는 견적서를 수정할 수 없습니다. )}
{/* 견적 응답 폼 */} 견적 응답 총 가격, 통화, 유효기간을 입력해주세요. {/* 총 가격 */}
setTotalPrice(e.target.value)} disabled={!canEdit} className="text-right" />
{/* 통화 */}
{/* 유효기간 */}
date < new Date()} initialFocus />
{/* 비고 */}