diff --git a/frontend/src/components/AgreementIdGenerator.tsx b/frontend/src/components/AgreementIdGenerator.tsx index d80d373..ebb7900 100644 --- a/frontend/src/components/AgreementIdGenerator.tsx +++ b/frontend/src/components/AgreementIdGenerator.tsx @@ -9,10 +9,16 @@ interface AgreementIdGeneratorProps { onGenerate?: (id: string) => void } +/** Detects canvas element support (unavailable during SSR or in very old browsers). */ +function isCanvasSupported(): boolean { + return typeof document !== 'undefined' && typeof HTMLCanvasElement !== 'undefined' +} + export function AgreementIdGenerator({ onGenerate }: AgreementIdGeneratorProps) { const toast = useToast() const [agreementId, setAgreementId] = useState('') const [qrDataUrl, setQrDataUrl] = useState('') + const [qrUnavailable, setQrUnavailable] = useState(false) const [showQR, setShowQR] = useState(false) const [copied, setCopied] = useState(false) const [shared, setShared] = useState(false) @@ -22,20 +28,27 @@ export function AgreementIdGenerator({ onGenerate }: AgreementIdGeneratorProps) setIsGenerating(true) const newId = generateAgreementId() setAgreementId(newId) + setQrDataUrl('') + setQrUnavailable(false) - // Generate QR code locally via the qrcode library - try { - const url = await QRCode.toDataURL(newId, { - width: 400, - margin: 2, - color: { - dark: '#1a2332', - light: '#ffffff', - }, - }) - setQrDataUrl(url) - } catch { - // Local QR generation failed; QR display will be skipped + // Generate QR code locally via the qrcode library, when canvas is available + if (isCanvasSupported()) { + try { + const url = await QRCode.toDataURL(newId, { + width: 400, + margin: 2, + color: { + dark: '#1a2332', + light: '#ffffff', + }, + }) + setQrDataUrl(url) + } catch { + // Local QR generation failed; fall back to the text-only display + setQrUnavailable(true) + } + } else { + setQrUnavailable(true) } setShowQR(true) @@ -165,6 +178,18 @@ export function AgreementIdGenerator({ onGenerate }: AgreementIdGeneratorProps) )} + {/* Text-only fallback when the QR code cannot be rendered (no canvas support) */} + {showQR && qrUnavailable && ( +
+

+ QR code isn't available in this browser. Use the ID below instead. +

+

+ {agreementId.match(/.{1,8}/g)?.join(' ') ?? agreementId} +

+
+ )} + {/* Action buttons */}