diff --git a/frontend/opsce/features/assets/AssetQRCode.tsx b/frontend/opsce/features/assets/AssetQRCode.tsx new file mode 100644 index 00000000..f23ae1d9 --- /dev/null +++ b/frontend/opsce/features/assets/AssetQRCode.tsx @@ -0,0 +1,161 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { QrCode, Download, Printer, AlertCircle } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { toast } from '@/components/ui/toast'; +import { api } from '@/lib/api'; + +interface AssetQRCodeProps { + assetId: string; + assetName: string; + size?: number; +} + +export function AssetQRCode({ assetId, assetName, size = 200 }: AssetQRCodeProps) { + const [qrCodeDataUri, setQrCodeDataUri] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + if (!assetId) return; + + const fetchQR = async () => { + setLoading(true); + setError(null); + try { + const response = await api.get(`/assets/${assetId}/qr?format=base64`, { + responseType: 'blob', + }); + + const blob = response.data as Blob; + const reader = new FileReader(); + reader.onloadend = () => { + setQrCodeDataUri(reader.result as string); + setLoading(false); + }; + reader.onerror = () => { + setError('Failed to load QR code'); + setLoading(false); + }; + reader.readAsDataURL(blob); + } catch (err) { + console.error('Failed to fetch QR code:', err); + setError('Failed to load QR code'); + setLoading(false); + } + }; + + fetchQR(); + }, [assetId]); + + const handleDownloadPNG = () => { + if (!qrCodeDataUri) return; + const link = document.createElement('a'); + link.href = qrCodeDataUri; + link.download = `${assetName.replace(/\s+/g, '_')}_qr.png`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + toast.success('QR code downloaded'); + }; + + const handlePrint = () => { + if (!qrCodeDataUri) return; + const printWindow = window.open('', '_blank'); + if (!printWindow) { + toast.error('Please allow pop-ups to print'); + return; + } + + printWindow.document.write(` + + + QR Code - ${assetName} + + + +
+

${assetName}

+

ID: ${assetId}

+ QR Code +

Scan to view asset details

+
+ + + + `); + printWindow.document.close(); + }; + + if (loading) { + return ( +
+
+
+

Loading QR code...

+
+
+ ); + } + + if (error || !qrCodeDataUri) { + return ( +
+
+ +

{error || 'QR code unavailable'}

+ +
+
+ ); + } + + return ( +
+
+ +

QR Code

+
+ +
+ {`QR +
+ +
+ + +
+
+ ); +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 2a376a59..b54b81d7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -51,7 +51,7 @@ "postcss": "^8.5.6", "tailwindcss": "^4.1.18", "ts-jest": "^29.4.4", - "typescript": "^5" + "typescript": "^5.9.3" } }, "node_modules/@alloc/quick-lru": {