직접 서명 기능 추가
This commit is contained in:
@@ -11,6 +11,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
|
||||
import { Trash2, Settings, Database, Link2, Upload, Loader2 } from "lucide-react";
|
||||
import { useReportDesigner } from "@/contexts/ReportDesignerContext";
|
||||
import { QueryManager } from "./QueryManager";
|
||||
import { SignaturePad } from "./SignaturePad";
|
||||
import { reportApi } from "@/lib/api/reportApi";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
|
||||
@@ -636,48 +637,110 @@ export function ReportDesignerRightPanel() {
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
{/* 파일 업로드 */}
|
||||
<div>
|
||||
<Label className="text-xs">
|
||||
{selectedComponent.type === "signature" ? "서명 이미지" : "도장 이미지"}
|
||||
</Label>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={handleImageUpload}
|
||||
className="hidden"
|
||||
disabled={uploadingImage}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={uploadingImage}
|
||||
className="flex-1"
|
||||
>
|
||||
{uploadingImage ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
업로드 중...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Upload className="mr-2 h-4 w-4" />
|
||||
{selectedComponent.imageUrl ? "파일 변경" : "파일 선택"}
|
||||
</>
|
||||
{/* 서명란: 탭으로 직접 서명 / 이미지 업로드 선택 */}
|
||||
{selectedComponent.type === "signature" ? (
|
||||
<Tabs defaultValue="draw" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-2">
|
||||
<TabsTrigger value="draw" className="text-xs">
|
||||
직접 서명
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="upload" className="text-xs">
|
||||
이미지 업로드
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{/* 직접 서명 탭 */}
|
||||
<TabsContent value="draw" className="mt-3 space-y-2">
|
||||
<SignaturePad
|
||||
initialSignature={selectedComponent.imageUrl}
|
||||
onSignatureChange={(dataUrl) => {
|
||||
updateComponent(selectedComponent.id, {
|
||||
imageUrl: dataUrl,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
{/* 이미지 업로드 탭 */}
|
||||
<TabsContent value="upload" className="mt-3 space-y-2">
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={handleImageUpload}
|
||||
className="hidden"
|
||||
disabled={uploadingImage}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={uploadingImage}
|
||||
className="flex-1"
|
||||
>
|
||||
{uploadingImage ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
업로드 중...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Upload className="mr-2 h-4 w-4" />
|
||||
{selectedComponent.imageUrl ? "파일 변경" : "파일 선택"}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-gray-500">JPG, PNG, GIF, WEBP (최대 10MB)</p>
|
||||
{selectedComponent.imageUrl && !selectedComponent.imageUrl.startsWith("data:") && (
|
||||
<p className="truncate text-xs text-indigo-600">현재: {selectedComponent.imageUrl}</p>
|
||||
)}
|
||||
</Button>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
) : (
|
||||
// 도장란: 기존 방식 유지
|
||||
<div>
|
||||
<Label className="text-xs">도장 이미지</Label>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={handleImageUpload}
|
||||
className="hidden"
|
||||
disabled={uploadingImage}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={uploadingImage}
|
||||
className="flex-1"
|
||||
>
|
||||
{uploadingImage ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
업로드 중...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Upload className="mr-2 h-4 w-4" />
|
||||
{selectedComponent.imageUrl ? "파일 변경" : "파일 선택"}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="mt-1 text-xs text-gray-500">JPG, PNG, GIF, WEBP (최대 10MB)</p>
|
||||
{selectedComponent.imageUrl && !selectedComponent.imageUrl.startsWith("data:") && (
|
||||
<p className="mt-2 truncate text-xs text-indigo-600">
|
||||
현재: {selectedComponent.imageUrl}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-1 text-xs text-gray-500">JPG, PNG, GIF, WEBP (최대 10MB)</p>
|
||||
{selectedComponent.imageUrl && (
|
||||
<p className="mt-2 truncate text-xs text-indigo-600">
|
||||
현재: {selectedComponent.imageUrl}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 맞춤 방식 */}
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user