diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-14 05:28:01 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-14 05:28:01 +0000 |
| commit | 675b4e3d8ffcb57a041db285417d81e61284d900 (patch) | |
| tree | 254f3d6a6c0ce39ae8fba35618f3810e08945f19 /lib/rfq-last/vendor/edit-contract-dialog.tsx | |
| parent | 39f12cb19f29cbc5568057e154e6adf4789ae736 (diff) | |
(대표님) RFQ-last, tbe-last, 기본계약 템플릿 내 견적,입찰,계약 추가, env.dev NAS_PATH 수정
Diffstat (limited to 'lib/rfq-last/vendor/edit-contract-dialog.tsx')
| -rw-r--r-- | lib/rfq-last/vendor/edit-contract-dialog.tsx | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/lib/rfq-last/vendor/edit-contract-dialog.tsx b/lib/rfq-last/vendor/edit-contract-dialog.tsx new file mode 100644 index 00000000..62b851fa --- /dev/null +++ b/lib/rfq-last/vendor/edit-contract-dialog.tsx @@ -0,0 +1,237 @@ +"use client"; + +import * as React from "react"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import { Separator } from "@/components/ui/separator"; +import { Badge } from "@/components/ui/badge"; +import { Alert, AlertDescription } from "@/components/ui/alert"; +import { FileText, Shield, Globe, Info, Loader2 } from "lucide-react"; +import { toast } from "sonner"; +import { updateVendorContractRequirements } from "../service"; + +interface EditContractDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + rfqId: number; + vendor: { + detailId: number; + vendorId: number; + vendorName: string; + vendorCode?: string; + vendorCountry?: string; + agreementYn?: boolean; + ndaYn?: boolean; + generalGtcYn?: boolean; + projectGtcYn?: boolean; + gtcType?: "general" | "project" | "none"; + }; + onSuccess: () => void; +} + +export function EditContractDialog({ + open, + onOpenChange, + rfqId, + vendor, + onSuccess, +}: EditContractDialogProps) { + const [isLoading, setIsLoading] = React.useState(false); + + // 기본계약 상태 + const [contractAgreement, setContractAgreement] = React.useState(false); + const [contractNDA, setContractNDA] = React.useState(false); + const [contractGTC, setContractGTC] = React.useState<"general" | "project" | "none">("none"); + + // 국외 업체 확인 + const isInternational = React.useMemo(() => { + return vendor?.vendorCountry && + vendor.vendorCountry !== "KR" && + vendor.vendorCountry !== "한국"; + }, [vendor]); + + // 초기값 설정 + React.useEffect(() => { + if (open && vendor) { + setContractAgreement(vendor.agreementYn || false); + setContractNDA(vendor.ndaYn || false); + + // GTC 타입 결정 + if (vendor.gtcType) { + setContractGTC(vendor.gtcType); + } else if (vendor.generalGtcYn) { + setContractGTC("general"); + } else if (vendor.projectGtcYn) { + setContractGTC("project"); + } else { + setContractGTC("none"); + } + } + }, [open, vendor]); + + // 제출 처리 + const handleSubmit = async () => { + setIsLoading(true); + + try { + const result = await updateVendorContractRequirements({ + rfqId, + detailId: vendor.detailId, + contractRequirements: { + agreementYn: contractAgreement, + ndaYn: contractNDA, + gtcType: isInternational ? contractGTC : "none", + }, + }); + + if (result.success) { + toast.success("기본계약 요구사항이 업데이트되었습니다."); + onSuccess(); + onOpenChange(false); + } else { + toast.error(result.error || "업데이트에 실패했습니다."); + } + } catch (error) { + console.error("Update error:", error); + toast.error("오류가 발생했습니다."); + } finally { + setIsLoading(false); + } + }; + + return ( + <Dialog open={open} onOpenChange={onOpenChange}> + <DialogContent className="max-w-md"> + <DialogHeader> + <DialogTitle>기본계약 수정</DialogTitle> + <DialogDescription> + <div className="flex items-center gap-2 mt-2"> + <Badge variant="outline">{vendor?.vendorCode}</Badge> + <span className="text-sm font-medium">{vendor?.vendorName}</span> + {vendor?.vendorCountry && ( + <Badge + variant={isInternational ? "secondary" : "default"} + className="text-xs" + > + {vendor.vendorCountry} + </Badge> + )} + </div> + </DialogDescription> + </DialogHeader> + + <div className="space-y-4 py-4"> + {/* 필수 계약 */} + <div className="space-y-3"> + <Label className="text-sm font-semibold">필수 계약</Label> + <div className="space-y-2"> + <div className="flex items-center space-x-2"> + <Checkbox + id="edit-agreement" + checked={contractAgreement} + onCheckedChange={(checked) => setContractAgreement(!!checked)} + /> + <label + htmlFor="edit-agreement" + className="flex items-center gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" + > + <FileText className="h-4 w-4 text-blue-500" /> + 기술자료 제공 동의 + </label> + </div> + <div className="flex items-center space-x-2"> + <Checkbox + id="edit-nda" + checked={contractNDA} + onCheckedChange={(checked) => setContractNDA(!!checked)} + /> + <label + htmlFor="edit-nda" + className="flex items-center gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" + > + <Shield className="h-4 w-4 text-green-500" /> + 비밀유지 계약 (NDA) + </label> + </div> + </div> + </div> + + {/* GTC 선택 (국외 업체만) */} + {isInternational && ( + <> + <Separator /> + <div className="space-y-3"> + <div className="flex items-center justify-between"> + <Label className="text-sm font-semibold flex items-center gap-2"> + <Globe className="h-4 w-4" /> + GTC (General Terms & Conditions) + </Label> + <Badge variant="outline" className="text-xs"> + 국외 업체 + </Badge> + </div> + <RadioGroup + value={contractGTC} + onValueChange={(value: any) => setContractGTC(value)} + > + <div className="flex items-center space-x-2"> + <RadioGroupItem value="none" id="edit-gtc-none" /> + <label htmlFor="edit-gtc-none" className="text-sm"> + GTC 요구하지 않음 + </label> + </div> + <div className="flex items-center space-x-2"> + <RadioGroupItem value="general" id="edit-gtc-general" /> + <label htmlFor="edit-gtc-general" className="text-sm"> + General GTC + </label> + </div> + <div className="flex items-center space-x-2"> + <RadioGroupItem value="project" id="edit-gtc-project" /> + <label htmlFor="edit-gtc-project" className="text-sm"> + Project GTC + </label> + </div> + </RadioGroup> + </div> + </> + )} + + {/* 국내 업체 안내 */} + {!isInternational && ( + <Alert> + <Info className="h-4 w-4" /> + <AlertDescription> + 국내 업체는 GTC가 적용되지 않습니다. + </AlertDescription> + </Alert> + )} + </div> + + <DialogFooter> + <Button + variant="outline" + onClick={() => onOpenChange(false)} + disabled={isLoading} + > + 취소 + </Button> + <Button onClick={handleSubmit} disabled={isLoading}> + {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} + 저장 + </Button> + </DialogFooter> + </DialogContent> + </Dialog> + ); +}
\ No newline at end of file |
