diff --git a/qr-web/Dockerfile b/qr-web/Dockerfile index a382e1a..e782fd3 100644 --- a/qr-web/Dockerfile +++ b/qr-web/Dockerfile @@ -4,6 +4,7 @@ WORKDIR /app COPY package.json pnpm-lock.yaml* ./ RUN pnpm install COPY . . +RUN mkdir -p /app/public ENV NEXT_TELEMETRY_DISABLED=1 RUN pnpm run build diff --git a/qr-web/src/components/ExportPanel.tsx b/qr-web/src/components/ExportPanel.tsx index e72da87..dd39c64 100644 --- a/qr-web/src/components/ExportPanel.tsx +++ b/qr-web/src/components/ExportPanel.tsx @@ -35,9 +35,15 @@ export function ExportPanel({ data, recipe, logoUrl, projectName }: ExportPanelP return qr; }, [data, recipe, logoUrl]); + const toBlob = (raw: Blob | Buffer | null): Blob | null => { + if (!raw) return null; + return raw instanceof Blob ? raw : new Blob([raw as BlobPart]); + }; + const handleSvg = useCallback(async () => { const qr = getQrInstance(); - const blob = await qr.getRawData('svg'); + const raw = await qr.getRawData('svg'); + const blob = toBlob(raw); if (!blob) return; const url = URL.createObjectURL(blob); const a = document.createElement('a'); @@ -49,7 +55,8 @@ export function ExportPanel({ data, recipe, logoUrl, projectName }: ExportPanelP const handlePng = useCallback(async () => { const qr = getQrInstance(); - const blob = await qr.getRawData('png'); + const raw = await qr.getRawData('png'); + const blob = toBlob(raw); if (!blob) return; const url = URL.createObjectURL(blob); const a = document.createElement('a'); @@ -61,7 +68,8 @@ export function ExportPanel({ data, recipe, logoUrl, projectName }: ExportPanelP const handlePdf = useCallback(async () => { const qr = getQrInstance(); - const blob = await qr.getRawData('png'); + const raw = await qr.getRawData('png'); + const blob = toBlob(raw); if (!blob) return; const arrayBuffer = await blob.arrayBuffer(); const pdfDoc = await PDFDocument.create(); @@ -84,7 +92,7 @@ export function ExportPanel({ data, recipe, logoUrl, projectName }: ExportPanelP page.drawText(urlText, { x: 50, y: 60, size: 10 }); } const pdfBytes = await pdfDoc.save(); - const url = URL.createObjectURL(new Blob([pdfBytes], { type: 'application/pdf' })); + const url = URL.createObjectURL(new Blob([pdfBytes as BlobPart], { type: 'application/pdf' })); const a = document.createElement('a'); a.href = url; a.download = `qr-${projectName || 'export'}.pdf`.replace(/[^a-z0-9.-]/gi, '-'); diff --git a/qr-web/src/components/ProjectsList.tsx b/qr-web/src/components/ProjectsList.tsx index ae728ef..9020b57 100644 --- a/qr-web/src/components/ProjectsList.tsx +++ b/qr-web/src/components/ProjectsList.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Stack, Text, Center } from '@mantine/core'; +import { Stack, Text } from '@mantine/core'; import classes from './ProjectsList.module.css'; export function ProjectsList() { diff --git a/qr-web/src/components/QrPreview.tsx b/qr-web/src/components/QrPreview.tsx index 5d0906c..b200b73 100644 --- a/qr-web/src/components/QrPreview.tsx +++ b/qr-web/src/components/QrPreview.tsx @@ -17,7 +17,8 @@ export function QrPreview({ data, recipe, logoUrl, size = 256 }: QrPreviewProps) const qrRef = useRef(null); useEffect(() => { - if (!ref.current) return; + const el = ref.current; + if (!el) return; const qr = new QRCodeStyling( buildQrStylingOptions(recipe, { width: size, @@ -27,12 +28,12 @@ export function QrPreview({ data, recipe, logoUrl, size = 256 }: QrPreviewProps) }) as ConstructorParameters[0], ); qrRef.current = qr; - qr.append(ref.current); + qr.append(el); return () => { - ref.current?.replaceChildren(); + el.replaceChildren(); qrRef.current = null; }; - }, [size]); + }, [data, logoUrl, recipe, size]); useEffect(() => { const qr = qrRef.current;