import { useQuery } from "@tanstack/react-query"; import { useEffect, useRef, useState } from "react"; import { orpc } from "@/utils/orpc"; interface QrCodeCanvasProps { token: string; } function QrCodeCanvas({ token }: QrCodeCanvasProps) { const canvasRef = useRef(null); useEffect(() => { if (!canvasRef.current || !token) return; // Dynamic import to avoid SSR issues import("qrcode").then((QRCode) => { if (canvasRef.current) { QRCode.toCanvas(canvasRef.current, token, { width: 280, margin: 2, color: { dark: "#214e51", light: "#ffffff" }, }); } }); }, [token]); return ; } function useCountdown(expiresAt: Date | undefined) { const [secondsLeft, setSecondsLeft] = useState(0); useEffect(() => { if (!expiresAt) return; const tick = () => { const diff = Math.max( 0, Math.floor((expiresAt.getTime() - Date.now()) / 1000), ); setSecondsLeft(diff); }; tick(); const interval = setInterval(tick, 1000); return () => clearInterval(interval); }, [expiresAt]); return secondsLeft; } export function QrCodeDisplay() { const { data, refetch, isLoading, isError } = useQuery( orpc.drinkkaart.getMyQrToken.queryOptions(), ); const expiresAt = data?.expiresAt ? new Date(data.expiresAt) : undefined; const secondsLeft = useCountdown(expiresAt); // Auto-refresh 60s before expiry useEffect(() => { if (!expiresAt) return; const refreshAt = expiresAt.getTime() - 60_000; const delay = refreshAt - Date.now(); if (delay <= 0) { refetch(); return; } const timer = setTimeout(() => refetch(), delay); return () => clearTimeout(timer); }, [expiresAt, refetch]); // Refresh on tab focus if token is about to expire useEffect(() => { const onVisibility = () => { if (document.visibilityState === "visible" && expiresAt) { if (Date.now() >= expiresAt.getTime() - 10_000) refetch(); } }; document.addEventListener("visibilitychange", onVisibility); return () => document.removeEventListener("visibilitychange", onVisibility); }, [expiresAt, refetch]); const minutes = Math.floor(secondsLeft / 60); const seconds = secondsLeft % 60; const countdownLabel = `${minutes}:${String(seconds).padStart(2, "0")}`; if (isLoading) { return (
); } if (isError || !data?.token) { return (

Kon QR-code niet laden

); } return (

{secondsLeft > 0 ? ( <> Vervalt over{" "} {countdownLabel} ) : ( Verlopen — vernieuwen... )}

); }