1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
'use client';
import { useState } from 'react';
import { uploadBuyerSignature } from './buyer-signature';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Upload, Loader2 } from 'lucide-react';
import { toast } from 'sonner';
import { BuyerSignature } from '@/db/schema';
const DEFAULT_SHI_ADDRESS = '경기도 성남시 분당구 판교로 227번길 23';
const DEFAULT_SHI_CEO_NAME = '최성안';
interface BuyerSignatureUploadFormProps {
initialSignature?: BuyerSignature | null;
}
export function BuyerSignatureUploadForm({ initialSignature }: BuyerSignatureUploadFormProps) {
const [isUploading, setIsUploading] = useState(false);
const [preview, setPreview] = useState<string | null>(null);
const [shiAddress, setShiAddress] = useState(initialSignature?.shiAddress ?? DEFAULT_SHI_ADDRESS);
const [shiCeoName, setShiCeoName] = useState(initialSignature?.shiCeoName ?? DEFAULT_SHI_CEO_NAME);
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setPreview(reader.result as string);
};
reader.readAsDataURL(file);
}
};
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsUploading(true);
const formData = new FormData(e.currentTarget);
formData.set('shiAddress', shiAddress);
formData.set('shiCeoName', shiCeoName);
try {
const result = await uploadBuyerSignature(formData);
if (result.success) {
toast.success('서명이 성공적으로 업로드되었습니다.');
setPreview(null);
(e.target as HTMLFormElement).reset();
} else {
toast.error(result.error || '업로드에 실패했습니다.');
}
} catch (error) {
toast.error('업로드 중 오류가 발생했습니다.');
} finally {
setIsUploading(false);
}
};
return (
<Card>
<CardHeader>
<CardTitle>구매자 서명 업로드</CardTitle>
<CardDescription>
삼성중공업 서명 이미지를 업로드하세요. 이 서명은 계약서에 자동으로 적용됩니다.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="file">서명 이미지</Label>
<Input
id="file"
name="file"
type="file"
accept="image/*"
onChange={handleFileChange}
required
disabled={isUploading}
/>
<p className="text-sm text-muted-foreground">
PNG, JPG, JPEG 형식 (최대 5MB)
</p>
</div>
<div className="space-y-2">
<Label htmlFor="shiAddress">삼성중공업 주소</Label>
<Input
id="shiAddress"
name="shiAddress"
value={shiAddress}
onChange={(event) => setShiAddress(event.target.value)}
required
disabled={isUploading}
/>
</div>
<div className="space-y-2">
<Label htmlFor="shiCeoName">대표이사 이름</Label>
<Input
id="shiCeoName"
name="shiCeoName"
value={shiCeoName}
onChange={(event) => setShiCeoName(event.target.value)}
required
disabled={isUploading}
/>
</div>
{preview && (
<div className="border rounded-lg p-4 bg-gray-50">
<Label className="text-sm font-medium mb-2 block">미리보기</Label>
<img
src={preview}
alt="서명 미리보기"
className="max-h-32 object-contain"
/>
</div>
)}
<Alert>
<AlertDescription>
업로드한 서명은 즉시 활성화되며, 새로운 계약서에 자동으로 적용됩니다.
</AlertDescription>
</Alert>
<Button
type="submit"
disabled={isUploading || !preview}
className="w-full"
>
{isUploading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
업로드 중...
</>
) : (
<>
<Upload className="mr-2 h-4 w-4" />
서명 업로드
</>
)}
</Button>
</form>
</CardContent>
</Card>
);
}
|