diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-03 10:35:57 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-03 10:35:57 +0000 |
| commit | a2bc455f654e011c53968b0d3a14389d7259847e (patch) | |
| tree | 6ff60b8ef0880aaa4cf2c9d4f234772fb0a74537 /components/bidding/bidding-conditions-edit.tsx | |
| parent | bfe354f7633f62350e61eb784cbf1926079339d1 (diff) | |
(최겸) 구매 입찰 개발(벤더 응찰 개발 및 기본계약 요청 개발 필)
Diffstat (limited to 'components/bidding/bidding-conditions-edit.tsx')
| -rw-r--r-- | components/bidding/bidding-conditions-edit.tsx | 304 |
1 files changed, 304 insertions, 0 deletions
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> + ) +} |
