From a2bc455f654e011c53968b0d3a14389d7259847e Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Wed, 3 Sep 2025 10:35:57 +0000
Subject: (최겸) 구매 입찰 개발(벤더 응찰 개발 및 기본계약 요청 개발 필)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/bidding/bidding-conditions-edit.tsx | 304 +++++++++++++++++++++++++
 1 file changed, 304 insertions(+)
 create mode 100644 components/bidding/bidding-conditions-edit.tsx

(limited to 'components/bidding/bidding-conditions-edit.tsx')

diff --git a/components/bidding/bidding-conditions-edit.tsx b/components/bidding/bidding-conditions-edit.tsx
new file mode 100644
index 00000000..a78bb0e0
--- /dev/null
+++ b/components/bidding/bidding-conditions-edit.tsx
@@ -0,0 +1,304 @@
+"use client"
+
+import * as React from "react"
+import { useRouter } from "next/navigation"
+import { useTransition } from "react"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Textarea } from "@/components/ui/textarea"
+import { Label } from "@/components/ui/label"
+import { Switch } from "@/components/ui/switch"
+import {
+  Select,
+  SelectContent,
+  SelectItem,
+  SelectTrigger,
+  SelectValue,
+} from "@/components/ui/select"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Pencil, Save, X } from "lucide-react"
+import { getBiddingConditions, updateBiddingConditions } from "@/lib/bidding/service"
+import { useToast } from "@/hooks/use-toast"
+
+interface BiddingConditionsEditProps {
+  biddingId: number
+  initialConditions?: any | null
+}
+
+export function BiddingConditionsEdit({ biddingId, initialConditions }: BiddingConditionsEditProps) {
+  const router = useRouter()
+  const { toast } = useToast()
+  const [isPending, startTransition] = useTransition()
+  const [isEditing, setIsEditing] = React.useState(false)
+  const [conditions, setConditions] = React.useState({
+    paymentTerms: initialConditions?.paymentTerms || "",
+    taxConditions: initialConditions?.taxConditions || "",
+    incoterms: initialConditions?.incoterms || "",
+    contractDeliveryDate: initialConditions?.contractDeliveryDate 
+      ? new Date(initialConditions.contractDeliveryDate).toISOString().split('T')[0] 
+      : "",
+    shippingPort: initialConditions?.shippingPort || "",
+    destinationPort: initialConditions?.destinationPort || "",
+    isPriceAdjustmentApplicable: initialConditions?.isPriceAdjustmentApplicable || false,
+    sparePartOptions: initialConditions?.sparePartOptions || "",
+  })
+
+  const handleSave = () => {
+    startTransition(async () => {
+      try {
+        const result = await updateBiddingConditions(biddingId, conditions)
+        
+        if (result.success) {
+          toast({
+            title: "성공",
+            description: result.message,
+          })
+          setIsEditing(false)
+          router.refresh()
+        } else {
+          toast({
+            title: "오류",
+            description: result.error,
+            variant: "destructive",
+          })
+        }
+      } catch (error) {
+        console.error('Error updating bidding conditions:', error)
+        toast({
+          title: "오류",
+          description: "입찰 조건 업데이트 중 오류가 발생했습니다.",
+          variant: "destructive",
+        })
+      }
+    })
+  }
+
+  const handleCancel = () => {
+    setConditions({
+      paymentTerms: initialConditions?.paymentTerms || "",
+      taxConditions: initialConditions?.taxConditions || "",
+      incoterms: initialConditions?.incoterms || "",
+      contractDeliveryDate: initialConditions?.contractDeliveryDate 
+        ? new Date(initialConditions.contractDeliveryDate).toISOString().split('T')[0] 
+        : "",
+      shippingPort: initialConditions?.shippingPort || "",
+      destinationPort: initialConditions?.destinationPort || "",
+      isPriceAdjustmentApplicable: initialConditions?.isPriceAdjustmentApplicable || false,
+      sparePartOptions: initialConditions?.sparePartOptions || "",
+    })
+    setIsEditing(false)
+  }
+
+  if (!isEditing) {
+    return (
+      <Card className="mt-6">
+        <CardHeader className="flex flex-row items-center justify-between">
+          <CardTitle>입찰 조건</CardTitle>
+          <Button
+            variant="outline"
+            size="sm"
+            onClick={() => setIsEditing(true)}
+            className="flex items-center gap-2"
+          >
+            <Pencil className="w-4 h-4" />
+            수정
+          </Button>
+        </CardHeader>
+        <CardContent>
+          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-sm">
+            <div>
+              <Label className="text-muted-foreground">지급조건</Label>
+              <p className="font-medium">{conditions.paymentTerms || "미설정"}</p>
+            </div>
+            <div>
+              <Label className="text-muted-foreground">세금조건</Label>
+              <p className="font-medium">{conditions.taxConditions || "미설정"}</p>
+            </div>
+            <div>
+              <Label className="text-muted-foreground">운송조건</Label>
+              <p className="font-medium">{conditions.incoterms || "미설정"}</p>
+            </div>
+            <div>
+              <Label className="text-muted-foreground">계약 납품일</Label>
+              <p className="font-medium">
+                {conditions.contractDeliveryDate 
+                  ? new Date(conditions.contractDeliveryDate).toLocaleDateString('ko-KR')
+                  : "미설정"
+                }
+              </p>
+            </div>
+            <div>
+              <Label className="text-muted-foreground">선적지</Label>
+              <p className="font-medium">{conditions.shippingPort || "미설정"}</p>
+            </div>
+            <div>
+              <Label className="text-muted-foreground">도착지</Label>
+              <p className="font-medium">{conditions.destinationPort || "미설정"}</p>
+            </div>
+            <div>
+              <Label className="text-muted-foreground">연동제 적용</Label>
+              <p className="font-medium">{conditions.isPriceAdjustmentApplicable ? "적용 가능" : "적용 불가"}</p>
+            </div>
+            {conditions.sparePartOptions && (
+              <div className="col-span-full">
+                <Label className="text-muted-foreground">스페어파트 옵션</Label>
+                <p className="font-medium">{conditions.sparePartOptions}</p>
+              </div>
+            )}
+          </div>
+        </CardContent>
+      </Card>
+    )
+  }
+
+  return (
+    <Card className="mt-6">
+      <CardHeader className="flex flex-row items-center justify-between">
+        <CardTitle>입찰 조건 수정</CardTitle>
+        <div className="flex items-center gap-2">
+          <Button
+            variant="outline"
+            size="sm"
+            onClick={handleCancel}
+            disabled={isPending}
+            className="flex items-center gap-2"
+          >
+            <X className="w-4 h-4" />
+            취소
+          </Button>
+          <Button
+            size="sm"
+            onClick={handleSave}
+            disabled={isPending}
+            className="flex items-center gap-2"
+          >
+            <Save className="w-4 h-4" />
+            저장
+          </Button>
+        </div>
+      </CardHeader>
+      <CardContent className="space-y-6">
+        <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
+          <div className="space-y-2">
+            <Label htmlFor="paymentTerms">지급조건 *</Label>
+            <Input
+              id="paymentTerms"
+              placeholder="예: 월말결제, 60일"
+              value={conditions.paymentTerms}
+              onChange={(e) => setConditions(prev => ({
+                ...prev,
+                paymentTerms: e.target.value
+              }))}
+            />
+          </div>
+
+          <div className="space-y-2">
+            <Label htmlFor="taxConditions">세금조건 *</Label>
+            <Input
+              id="taxConditions"
+              placeholder="예: VAT 별도, 원천세 3.3%"
+              value={conditions.taxConditions}
+              onChange={(e) => setConditions(prev => ({
+                ...prev,
+                taxConditions: e.target.value
+              }))}
+            />
+          </div>
+
+          <div className="space-y-2">
+            <Label htmlFor="incoterms">운송조건(인코텀즈) *</Label>
+            <Select 
+              value={conditions.incoterms}
+              onValueChange={(value) => setConditions(prev => ({
+                ...prev,
+                incoterms: value
+              }))}
+            >
+              <SelectTrigger>
+                <SelectValue placeholder="인코텀즈 선택" />
+              </SelectTrigger>
+              <SelectContent>
+                <SelectItem value="EXW">EXW (Ex Works)</SelectItem>
+                <SelectItem value="FCA">FCA (Free Carrier)</SelectItem>
+                <SelectItem value="CPT">CPT (Carriage Paid To)</SelectItem>
+                <SelectItem value="CIP">CIP (Carriage and Insurance Paid to)</SelectItem>
+                <SelectItem value="DAP">DAP (Delivered at Place)</SelectItem>
+                <SelectItem value="DPU">DPU (Delivered at Place Unloaded)</SelectItem>
+                <SelectItem value="DDP">DDP (Delivered Duty Paid)</SelectItem>
+                <SelectItem value="FAS">FAS (Free Alongside Ship)</SelectItem>
+                <SelectItem value="FOB">FOB (Free on Board)</SelectItem>
+                <SelectItem value="CFR">CFR (Cost and Freight)</SelectItem>
+                <SelectItem value="CIF">CIF (Cost, Insurance, and Freight)</SelectItem>
+              </SelectContent>
+            </Select>
+          </div>
+
+          <div className="space-y-2">
+            <Label htmlFor="contractDeliveryDate">계약 납품일</Label>
+            <Input
+              id="contractDeliveryDate"
+              type="date"
+              value={conditions.contractDeliveryDate}
+              onChange={(e) => setConditions(prev => ({
+                ...prev,
+                contractDeliveryDate: e.target.value
+              }))}
+            />
+          </div>
+
+          <div className="space-y-2">
+            <Label htmlFor="shippingPort">선적지</Label>
+            <Input
+              id="shippingPort"
+              placeholder="예: 부산항, 인천항"
+              value={conditions.shippingPort}
+              onChange={(e) => setConditions(prev => ({
+                ...prev,
+                shippingPort: e.target.value
+              }))}
+            />
+          </div>
+
+          <div className="space-y-2">
+            <Label htmlFor="destinationPort">도착지</Label>
+            <Input
+              id="destinationPort"
+              placeholder="예: 현장 직납, 창고 납품"
+              value={conditions.destinationPort}
+              onChange={(e) => setConditions(prev => ({
+                ...prev,
+                destinationPort: e.target.value
+              }))}
+            />
+          </div>
+        </div>
+
+        <div className="flex items-center space-x-2">
+          <Switch
+            id="isPriceAdjustmentApplicable"
+            checked={conditions.isPriceAdjustmentApplicable}
+            onCheckedChange={(checked) => setConditions(prev => ({
+              ...prev,
+              isPriceAdjustmentApplicable: checked
+            }))}
+          />
+          <Label htmlFor="isPriceAdjustmentApplicable">연동제 적용 가능</Label>
+        </div>
+
+        <div className="space-y-2">
+          <Label htmlFor="sparePartOptions">스페어파트 옵션</Label>
+          <Textarea
+            id="sparePartOptions"
+            placeholder="스페어파트 관련 옵션을 입력하세요"
+            value={conditions.sparePartOptions}
+            onChange={(e) => setConditions(prev => ({
+              ...prev,
+              sparePartOptions: e.target.value
+            }))}
+            rows={3}
+          />
+        </div>
+      </CardContent>
+    </Card>
+  )
+}
-- 
cgit v1.2.3

