"use client"; import { useRef, useState, useEffect, useCallback } from "react"; import { Loader2, Check } from "lucide-react"; import { signContract } from "@/lib/supabase/contract-actions"; export default function SignatureCanvas({ contractId, contractTitle, }: { contractId: string; contractTitle: string; }) { const canvasRef = useRef(null); const [isDrawing, setIsDrawing] = useState(false); const [hasSignature, setHasSignature] = useState(false); const [signing, setSigning] = useState(false); const [signed, setSigned] = useState(false); const [error, setError] = useState(null); const lastPos = useRef<{ x: number; y: number } | null>(null); // Setup canvas useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; // Handle high-DPI displays const dpr = window.devicePixelRatio || 1; const rect = canvas.getBoundingClientRect(); canvas.width = rect.width * dpr; canvas.height = rect.height * dpr; ctx.scale(dpr, dpr); ctx.strokeStyle = "#1D9E75"; ctx.lineWidth = 2; ctx.lineCap = "round"; ctx.lineJoin = "round"; }, []); const getPos = ( e: React.MouseEvent | React.TouchEvent ): { x: number; y: number } => { const canvas = canvasRef.current; if (!canvas) return { x: 0, y: 0 }; const rect = canvas.getBoundingClientRect(); if ("touches" in e) { return { x: e.touches[0].clientX - rect.left, y: e.touches[0].clientY - rect.top, }; } return { x: e.clientX - rect.left, y: e.clientY - rect.top, }; }; const drawLine = useCallback((from: { x: number; y: number }, to: { x: number; y: number }) => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; ctx.beginPath(); ctx.moveTo(from.x, from.y); ctx.lineTo(to.x, to.y); ctx.stroke(); }, []); const handleStart = (e: React.MouseEvent | React.TouchEvent) => { e.preventDefault(); setIsDrawing(true); const pos = getPos(e); lastPos.current = pos; setHasSignature(true); }; const handleMove = (e: React.MouseEvent | React.TouchEvent) => { e.preventDefault(); if (!isDrawing || !lastPos.current) return; const pos = getPos(e); drawLine(lastPos.current, pos); lastPos.current = pos; }; const handleEnd = (e: React.MouseEvent | React.TouchEvent) => { e.preventDefault(); setIsDrawing(false); lastPos.current = null; }; const handleClear = () => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; ctx.clearRect(0, 0, canvas.width, canvas.height); setHasSignature(false); setError(null); }; const handleSign = async () => { if (!hasSignature) { setError("Please draw your signature first"); return; } setSigning(true); setError(null); try { const canvas = canvasRef.current; if (!canvas) return; const signatureData = canvas.toDataURL("image/png"); const result = await signContract(contractId, signatureData); if (!result.success) { setError(result.error || "Failed to sign contract"); return; } setSigned(true); } catch (e: any) { setError(e.message || "An unexpected error occurred"); } finally { setSigning(false); } }; if (signed) { return (

Thank you

Your contract “{contractTitle}” has been signed successfully.

); } return (

Your signature

Draw your signature below using your mouse, finger, or stylus.

{error && (
{error}
)}
); }