"use client"; import { useRef, useState } from "react"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Loader2, PenLine, Upload } from "lucide-react"; import { useReportDesigner } from "@/contexts/ReportDesignerContext"; import { SignatureGenerator } from "../SignatureGenerator"; import { reportApi } from "@/lib/api/reportApi"; import { useToast } from "@/hooks/use-toast"; import type { ComponentConfig } from "@/types/report"; interface Props { component: ComponentConfig; /** 우측 패널: "style" | 모달: "data" | 미전달: 전체 표시 (하위 호환) */ section?: "style" | "data"; } export function SignatureProperties({ component, section }: Props) { const { updateComponent } = useReportDesigner(); const [signatureMethod, setSignatureMethod] = useState<"upload" | "generate">("upload"); const [uploadingImage, setUploadingImage] = useState(false); const fileInputRef = useRef(null); const { toast } = useToast(); const showStyle = !section || section === "style"; const showData = !section || section === "data"; const handleImageUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; if (!file.type.startsWith("image/")) { toast({ title: "오류", description: "이미지 파일만 업로드 가능합니다.", variant: "destructive" }); return; } if (file.size > 10 * 1024 * 1024) { toast({ title: "오류", description: "파일 크기는 10MB 이하여야 합니다.", variant: "destructive" }); return; } try { setUploadingImage(true); const result = await reportApi.uploadImage(file); if (result.success) { updateComponent(component.id, { imageUrl: result.data.fileUrl }); toast({ title: "성공", description: "이미지가 업로드되었습니다." }); } } catch { toast({ title: "오류", description: "이미지 업로드 중 오류가 발생했습니다.", variant: "destructive" }); } finally { setUploadingImage(false); if (fileInputRef.current) fileInputRef.current.value = ""; } }; return ( <> {/* 서명란 스타일 — 우측 패널(section="style")에서 표시 */} {showStyle && (
{component.type === "signature" ? "서명란 스타일" : "도장란 스타일"}
{/* 맞춤 방식 */}
{/* 레이블 표시 */}
updateComponent(component.id, { showLabel: e.target.checked })} className="h-4 w-4" />
{/* 레이블 텍스트 */} {component.showLabel !== false && ( <>
updateComponent(component.id, { labelText: e.target.value })} className="h-9" />
{/* 레이블 위치 (서명란만) */} {component.type === "signature" && (
)} )}
)} {/* 서명 입력 — 모달(section="data")에서 표시 */} {showData && (
{component.type === "signature" ? "서명 입력" : "도장 이미지"}
{component.type === "signature" ? ( <> {/* 서명 방식 선택 */}
{/* 이미지 업로드 */} {signatureMethod === "upload" && (

JPG, PNG, GIF, WEBP (최대 10MB)

{component.imageUrl && !component.imageUrl.startsWith("data:") && (

현재: {component.imageUrl}

)}
)} {/* 서명 만들기 */} {signatureMethod === "generate" && (
{ updateComponent(component.id, { imageUrl: dataUrl }); toast({ title: "성공", description: "서명이 적용되었습니다." }); }} />
)} ) : ( // 도장란 <>

JPG, PNG, GIF, WEBP (최대 10MB)

{component.imageUrl && !component.imageUrl.startsWith("data:") && (

현재: {component.imageUrl}

)}
{/* 이름 입력 (도장란만) */}
updateComponent(component.id, { personName: e.target.value })} placeholder="예: 홍길동" className="h-9" />

도장 옆에 표시될 이름

)}
)} ); }