summaryrefslogtreecommitdiff
path: root/components/bidding/bidding-conditions-edit.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/bidding/bidding-conditions-edit.tsx')
-rw-r--r--components/bidding/bidding-conditions-edit.tsx304
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>
+ )
+}