Files
kunstenkamp/apps/web/src/routes/__root.tsx
zias 19d784b2e5 feat(drinkkaart): implement QR scan and balance deduction interface
Convert /drinkkaart route from a redirect to a full admin scanning interface.
Add flow: scan QR → resolve user → select amount → confirm deduction → success.
Refactor QrScanner to use Html5Qrcode API for better control and cleanup.
Update event date/time to April 24, 2026 at 19:30.

BREAKING CHANGE: /drinkkaart now requires admin role and provides scanner UI
instead of redirecting to /account.
2026-03-15 14:47:36 +01:00

181 lines
4.2 KiB
TypeScript

import type { QueryClient } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import {
createRootRouteWithContext,
HeadContent,
Outlet,
Scripts,
} from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import { CookieConsent } from "@/components/CookieConsent";
import { SiteHeader } from "@/components/SiteHeader";
import { Toaster } from "@/components/ui/sonner";
import type { orpc } from "@/utils/orpc";
import appCss from "../index.css?url";
const siteUrl = "https://kunstenkamp.be";
const siteTitle = "Kunstenkamp Open Mic Night - Ongedesemd Woord";
const siteDescription =
"Doe mee met de Open Mic Night op 24 april! Een avond vol muziek, theater, dans, woordkunst en meer. Iedereen is welkom - van beginner tot professional.";
const eventImage = `${siteUrl}/assets/og-image.jpg`;
export interface RouterAppContext {
orpc: typeof orpc;
queryClient: QueryClient;
}
export const Route = createRootRouteWithContext<RouterAppContext>()({
head: () => ({
meta: [
{
charSet: "utf-8",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1",
},
{
title: siteTitle,
},
{
name: "description",
content: siteDescription,
},
{
name: "theme-color",
content: "#d82560",
},
// Open Graph
{
property: "og:type",
content: "website",
},
{
property: "og:url",
content: siteUrl,
},
{
property: "og:title",
content: siteTitle,
},
{
property: "og:description",
content: siteDescription,
},
{
property: "og:image",
content: eventImage,
},
{
property: "og:locale",
content: "nl_BE",
},
// Twitter Card
{
name: "twitter:card",
content: "summary_large_image",
},
{
name: "twitter:title",
content: siteTitle,
},
{
name: "twitter:description",
content: siteDescription,
},
{
name: "twitter:image",
content: eventImage,
},
],
links: [
{
rel: "stylesheet",
href: appCss,
},
{
rel: "canonical",
href: siteUrl,
},
{
rel: "icon",
type: "image/svg+xml",
href: "/favicon.png",
},
{
rel: "preconnect",
href: "https://analytics.zias.be",
},
],
scripts: [
{
src: "https://analytics.zias.be/js/script.file-downloads.hash.outbound-links.pageview-props.revenue.tagged-events.js",
defer: true,
"data-domain": "kunstenkamp.be",
"data-api": "https://analytics.zias.be/api/event",
},
{
children:
"window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }",
},
// JSON-LD Schema for Event
{
type: "application/ld+json",
children: JSON.stringify({
"@context": "https://schema.org",
"@type": "Event",
name: "Kunstenkamp Open Mic Night",
description:
"Een avond vol muziek, theater, dans, woordkunst en meer. Iedereen is welkom om zijn of haar talent te tonen.",
startDate: "2026-04-24T19:30:00+02:00",
eventStatus: "https://schema.org/EventScheduled",
eventAttendanceMode: "https://schema.org/OfflineEventAttendanceMode",
organizer: {
"@type": "Organization",
name: "Kunstenkamp",
url: siteUrl,
},
image: eventImage,
offers: {
"@type": "Offer",
price: "0",
priceCurrency: "EUR",
availability: "https://schema.org/InStock",
validFrom: "2026-03-16T19:00:00+01:00",
},
}),
},
],
}),
component: RootDocument,
});
function RootDocument() {
return (
<html lang="nl">
<head>
<HeadContent />
</head>
<body className="flex min-h-screen flex-col bg-[#214e51]">
<a
href="#main-content"
className="fixed top-0 left-0 z-[100] -translate-y-full bg-[#d82560] px-4 py-2 text-white transition-transform focus:translate-y-0"
>
Ga naar hoofdinhoud
</a>
<SiteHeader />
<main id="main-content" className="flex-1">
<Outlet />
</main>
<Toaster />
<CookieConsent />
<TanStackRouterDevtools position="bottom-left" />
<ReactQueryDevtools position="bottom" buttonPosition="bottom-right" />
<Scripts />
</body>
</html>
);
}