import React, { useEffect, useState } from 'react'; import { AiOutlineUpload, AiOutlineEdit } from 'react-icons/ai'; import { MdCloudUpload } from 'react-icons/md'; import api from '../../../config/api'; import DrawSignatureCanvas from './DrawSignatureCanvas'; import { FaSpinner } from "react-icons/fa"; import { GrCheckboxSelected } from "react-icons/gr"; import { Bounce, toast } from "react-toastify"; import { FiCheck } from 'react-icons/fi'; interface Signature { id: string; email: string; signatureType: string; lastName: string; firstName: string font: string; initialsBlob: string; initialsStampedBlob: string; initialsHash: string; signatureHash: string; signatureBlob: string; signatureStampedBlob: string; default: boolean } interface AddSignatureModalProps { setShowAddSignature?: (value: boolean) => void; getAllSignatures: () => Promise; editingSignature?: Signature | null; } interface Account { id: number; isDefault: boolean; name: string; } interface UserData { id: string; firstName: string; lastName: string; email: string; language: string; account: Account; } interface SelectStyle { id: number, style: string } const AddSignatureModal: React.FC = ({ setShowAddSignature, getAllSignatures, editingSignature }) => { console.log("editingSignature", editingSignature) const [activeTab, setActiveTab] = useState<'SELECT' | 'DRAW' | 'UPLOAD'>('SELECT'); const [fullName, setFullName] = useState(''); const [initials, setInitials] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); const [signatures, setSignatures] = useState<{ fullSignature: string | null; initials: string | null; }>({ fullSignature: null, initials: null }); const signatureOptions = [ { id: 1, name: 'print', initials: 'LA', style: 'print' }, { id: 2, name: 'cursive', initials: 'LA', style: 'cursive' }, { id: 3, name: 'script', initials: 'LA', style: 'script' }, { id: 4, name: 'elegant', initials: 'LA', style: 'elegant' }, { id: 5, name: 'modern', initials: 'LA', style: 'modern' }, { id: 6, name: 'classic', initials: 'LA', style: 'classic' }, ]; const [checked, setChecked] = useState(false); const toggleCheckbox = () => setChecked(!checked); const [selectedSignature, setSelectedSignature] = useState( signatureOptions.length > 0 ? { id: signatureOptions[0].id, style: signatureOptions[0].style } : { id: 0, style: "" } ); console.log("selectedSignature", selectedSignature) // Store the actual file const [file1, setFile1] = useState(null); const [file2, setFile2] = useState(null); // Store the preview URL const [preview1, setPreview1] = useState(null); const [preview2, setPreview2] = useState(null); // User data const [user, setUser] = useState({ id: "", firstName: "", lastName: "", email: "", language: "", account: { id: 0, isDefault: false, name: "", }, }); const isEditMode = !!editingSignature; // Navigation items const navigationItems = [ { id: 'SELECT', label: 'SELECT', icon: }, { id: 'DRAW', label: 'DRAW', icon: }, { id: 'UPLOAD', label: 'UPLOAD', icon: }, ]; // Initialize form with editing signature data useEffect(() => { if (editingSignature) { setFullName(`${editingSignature.firstName} ${editingSignature.lastName}`); setInitials(`${editingSignature.firstName.slice(0, 1)}${editingSignature.lastName.slice(0, 1)}`); setActiveTab(editingSignature.signatureType as 'SELECT' | 'DRAW' | 'UPLOAD'); // Set font for SELECT tab const fontOption = signatureOptions.find(option => option.style === editingSignature.font); if (fontOption) { setSelectedSignature({ id: fontOption.id, style: fontOption.style }); } // Set signature blobs for all tabs if (editingSignature.signatureBlob && editingSignature.initialsBlob) { setSignatures({ fullSignature: `data:image/png;base64,${editingSignature.signatureBlob}`, initials: `data:image/png;base64,${editingSignature.initialsBlob}` }); // Set preview URLs for UPLOAD tab if (editingSignature.signatureType === 'UPLOAD') { setPreview1(`data:image/png;base64,${editingSignature.signatureBlob}`); setPreview2(`data:image/png;base64,${editingSignature.initialsBlob}`); } } if (editingSignature.default) { setChecked(editingSignature.default) } } }, [editingSignature]); const handleSignatureChange = (data: { fullSignature: string | null; initials: string | null }) => { setSignatures(data); }; // Cleanup preview URLs when component unmounts or image changes useEffect(() => { return () => { if (preview1) URL.revokeObjectURL(preview1); if (preview2) URL.revokeObjectURL(preview2); }; }, [preview1, preview2]); const handleImageChange = async ( e: React.ChangeEvent, setFile: React.Dispatch>, setPreview: React.Dispatch>, type: "fullSignature" | "initials" ) => { const file = e.target.files?.[0]; if (file) { setFile(file); const previewUrl = URL.createObjectURL(file); setPreview(previewUrl); // Convert to base64 const base64 = await convertToBase64(file); // Update the appropriate signature setSignatures((prev) => ({ ...prev, [type]: base64, })); } }; const convertToBase64 = (file: File): Promise => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result as string); reader.onerror = (error) => reject(error); }); }; const handleSubmit = async () => { setIsSubmitting(true); // Only validate for DRAW and UPLOAD if ((activeTab === 'DRAW' || activeTab === 'UPLOAD') && (!signatures.fullSignature || !signatures.initials)) { // alert('Please provide both signature and initials'); toast.error('Please provide both signature and initials in draw and upload case', { position: "top-center", autoClose: 2000, hideProgressBar: false, closeOnClick: false, pauseOnHover: true, draggable: true, progress: undefined, theme: "light", transition: Bounce, }); setIsSubmitting(false); return; } try { // Base payload const payload = { signatureType: activeTab, firstName: fullName.split(' ')[0] || user.firstName, lastName: fullName.split(' ')[1] || user.lastName, font: selectedSignature.style, default: checked }; // Only add signatures if not SELECT if (activeTab !== 'SELECT') { payload.signatureBase64 = signatures.fullSignature; payload.initialsBase64 = signatures.initials; } console.log("payload214", payload); let res; if (isEditMode && editingSignature) { // Update existing signature const updatePayload = { ...payload, signatureId: editingSignature.id }; res = await api.put(`/api/user/signatures`, updatePayload); console.log("handleUpdate", res); toast.success("Signature Updated Successfully", { position: "top-center", autoClose: 500, hideProgressBar: false, closeOnClick: false, pauseOnHover: true, draggable: true, progress: undefined, theme: "light", transition: Bounce, }); } else { // Create new signature res = await api.post(`/api/user/signatures`, payload); console.log("handleSubmit", res); toast.success("Signature Created Successfully", { position: "top-center", autoClose: 500, hideProgressBar: false, closeOnClick: false, pauseOnHover: true, draggable: true, progress: undefined, theme: "light", transition: Bounce, }); } if (res?.data) { await getAllSignatures(); setShowAddSignature?.(false); } } catch (error) { console.error("Error submitting signature:", error); toast.error(isEditMode ? "Failed to update signature" : "Failed to create signature", { position: "top-center", autoClose: 2000, hideProgressBar: false, closeOnClick: false, pauseOnHover: true, draggable: true, progress: undefined, theme: "light", transition: Bounce, }); } finally { setIsSubmitting(false); } }; // Fixed renderContent function for SELECT case with proper radio button styling const renderContent = () => { switch (activeTab) { case 'SELECT': return (

Choose Signature Style

Select from pre-designed signature styles

{signatureOptions.map((option) => (
setSelectedSignature({ id: option.id, style: option.style })} > {/* Custom Radio Button */}
{selectedSignature.id === option.id && (
)}
{/* Hidden native radio button for accessibility */} setSelectedSignature({ id: option.id, style: option.style })} className="sr-only" />
Signed by:
{fullName || option.name}
dca3e646-62cd-4cc...
DS
{initials || option.initials}
))}
); case 'DRAW': return (
); case 'UPLOAD': return (

Upload Signature

Upload your signature images

{/* Upload 1 - Full Signature */}
handleImageChange(e, setFile1, setPreview1, "fullSignature")} />
{/* Upload 2 - Initials */}
handleImageChange(e, setFile2, setPreview2, "initials")} />
); default: return null; } }; const getUserDetails = async () => { try { let res = await api.get(`/api/user/details`); console.log("getuser", res); let currUser = res?.data; setUser(currUser); // Only set default values if not in edit mode if (!isEditMode) { setFullName(currUser.firstName + " " + currUser.lastName); setInitials(currUser.firstName.slice(0, 1) + currUser.lastName.slice(0, 1)); } } catch (error) { console.error("Error fetching user details:", error); } }; useEffect(() => { getUserDetails(); }, []); return (
{/* Mobile Navigation - Fixed at top on mobile only */}
{/* Scrollable area (mobile: inputs + nav + content) */}

{isEditMode ? 'Edit Signature' : 'Add Signature'}

{/* Mobile Inputs */}
setFullName(e.target.value)} placeholder="Enter full name" className="w-full px-2 py-2 text-xs border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
setInitials(e.target.value)} placeholder="Enter initials" className="w-full px-2 py-2 text-xs border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
{/* Mobile Navigation - Sticky inside scroll */}
{/* Main Content */}
{renderContent()}
{/* Checkbox - Fixed */}
{/* Footer Buttons - Fixed */}
{/* Desktop Sidebar Navigation */}
{/* Header - Fixed */}

{isEditMode ? 'Edit Signature' : 'Add Signature'}

{isEditMode ? 'Update your digital signature' : 'Create your digital signature'}

{/* Form Inputs - Fixed */}
setFullName(e.target.value)} placeholder="Enter full name" className="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
setInitials(e.target.value)} placeholder="Enter initials" className="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
{/* Navigation Menu - Fixed */}
{/* Spacer for desktop */}
{/* Main Content Area */}
{/* Content - Scrollable */}
{renderContent()}
{/* Checkbox - Fixed */}
{/* Footer Buttons - Fixed */}
); }; export default AddSignatureModal;