22
33import React , { useEffect , useState } from 'react' ;
44import QRCode from 'qrcode' ;
5+ import { useMediaQuery } from '@/hooks/useMediaQuery' ;
56
67interface ReceiptQrCodeProps {
78 value : string ;
@@ -10,9 +11,12 @@ interface ReceiptQrCodeProps {
1011
1112export default function ReceiptQrCode ( { value, label } : ReceiptQrCodeProps ) {
1213 const [ dataUrl , setDataUrl ] = useState ( '' ) ;
14+ const [ isGenerating , setIsGenerating ] = useState ( true ) ;
15+ const prefersReducedMotion = useMediaQuery ( '(prefers-reduced-motion: reduce)' ) ;
1316
1417 useEffect ( ( ) => {
1518 let cancelled = false ;
19+ setIsGenerating ( true ) ;
1620
1721 QRCode . toDataURL ( value , {
1822 width : 128 ,
@@ -21,28 +25,42 @@ export default function ReceiptQrCode({ value, label }: ReceiptQrCodeProps) {
2125 errorCorrectionLevel : 'M' ,
2226 } )
2327 . then ( ( url ) => {
24- if ( ! cancelled ) setDataUrl ( url ) ;
28+ if ( ! cancelled ) {
29+ setDataUrl ( url ) ;
30+ setIsGenerating ( false ) ;
31+ }
2532 } )
2633 . catch ( ( ) => {
27- if ( ! cancelled ) setDataUrl ( '' ) ;
34+ if ( ! cancelled ) {
35+ setDataUrl ( '' ) ;
36+ setIsGenerating ( false ) ;
37+ }
2838 } ) ;
2939
3040 return ( ) => {
3141 cancelled = true ;
3242 } ;
3343 } , [ value ] ) ;
3444
35- if ( ! dataUrl ) return null ;
36-
3745 return (
3846 < div className = "receipt-qr-wrapper flex flex-col items-center gap-1 pt-2 border-t dark:border-gray-700" >
39- < img
40- src = { dataUrl }
41- alt = { label ?? 'Transaction verification QR code' }
42- className = "receipt-qr-code w-32 h-32"
43- width = { 128 }
44- height = { 128 }
45- />
47+ { isGenerating ? (
48+ < div
49+ role = "status"
50+ aria-live = "polite"
51+ className = "receipt-qr-loading flex h-32 w-32 items-center justify-center rounded border border-dashed border-gray-300 bg-gray-50 text-[10px] uppercase tracking-wide text-gray-500 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-400"
52+ >
53+ { prefersReducedMotion ? 'Generating QR code…' : 'Generating QR code…' }
54+ </ div >
55+ ) : dataUrl ? (
56+ < img
57+ src = { dataUrl }
58+ alt = { label ?? 'Transaction verification QR code' }
59+ className = "receipt-qr-code h-32 w-32"
60+ width = { 128 }
61+ height = { 128 }
62+ />
63+ ) : null }
4664 < span className = "receipt-qr-label text-[9px] text-gray-500 uppercase tracking-wide" >
4765 Scan to verify
4866 </ span >
0 commit comments