fix:improved admin dashboard on mobile

This commit is contained in:
2026-03-04 16:25:46 +01:00
parent f9d79c3879
commit 835f0941dc
4 changed files with 288 additions and 64 deletions

View File

@@ -100,18 +100,18 @@ function AdminDrinkkaartPage() {
return ( return (
<div> <div>
{/* Header */} {/* Header */}
<header className="border-white/10 border-b bg-[#214e51]/95 px-6 py-5"> <header className="border-white/10 border-b bg-[#214e51]/95 px-4 py-4 sm:px-6 sm:py-5">
<div className="mx-auto flex max-w-2xl items-center gap-4"> <div className="mx-auto flex max-w-2xl items-center gap-3 sm:gap-4">
<Link to="/admin" className="text-sm text-white/60 hover:text-white"> <Link to="/admin" className="text-sm text-white/60 hover:text-white">
Admin Admin
</Link> </Link>
<h1 className="font-['Intro',sans-serif] text-2xl text-white"> <h1 className="font-['Intro',sans-serif] text-white text-xl sm:text-2xl">
Drinkkaart Beheer Drinkkaart Beheer
</h1> </h1>
</div> </div>
</header> </header>
<main className="mx-auto max-w-2xl space-y-8 px-6 py-8"> <main className="mx-auto max-w-2xl space-y-6 px-4 py-4 sm:space-y-8 sm:px-6 sm:py-8">
{/* Scan / State machine */} {/* Scan / State machine */}
<div className="rounded-2xl border border-white/10 bg-white/5 p-6"> <div className="rounded-2xl border border-white/10 bg-white/5 p-6">
{scanState.step === "idle" && ( {scanState.step === "idle" && (

View File

@@ -392,20 +392,23 @@ function AdminPage() {
return ( return (
<div> <div>
{/* Header */} {/* Header */}
<header className="border-white/10 border-b bg-[#214e51]/95 px-8 py-6"> <header className="border-white/10 border-b bg-[#214e51]/95 px-4 py-4 sm:px-8 sm:py-6">
<div className="mx-auto flex max-w-7xl items-center justify-between"> <div className="mx-auto flex max-w-7xl flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-4"> <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4">
<Link to="/" className="text-white hover:opacity-80"> <Link
to="/"
className="text-sm text-white hover:opacity-80 sm:text-base"
>
Terug naar website Terug naar website
</Link> </Link>
<h1 className="font-['Intro',sans-serif] text-3xl text-white"> <h1 className="font-['Intro',sans-serif] text-2xl text-white sm:text-3xl">
Admin Dashboard Admin Dashboard
</h1> </h1>
</div> </div>
<div className="flex items-center gap-3"> <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3">
<Link <Link
to="/admin/drinkkaart" to="/admin/drinkkaart"
className="inline-flex items-center rounded-lg border border-white/30 px-4 py-2 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white" className="inline-flex items-center justify-center rounded-lg border border-white/30 px-4 py-2 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white"
> >
Drinkkaart beheer Drinkkaart beheer
</Link> </Link>
@@ -422,30 +425,30 @@ function AdminPage() {
</header> </header>
{/* Main Content */} {/* Main Content */}
<main className="mx-auto max-w-7xl p-8"> <main className="mx-auto max-w-7xl px-4 py-4 sm:px-6 sm:py-6 lg:px-8 lg:py-8">
{/* Pending Admin Requests */} {/* Pending Admin Requests */}
{pendingRequests.length > 0 && ( {pendingRequests.length > 0 && (
<Card className="mb-6 border-yellow-500/30 bg-yellow-500/10"> <Card className="mb-4 border-yellow-500/30 bg-yellow-500/10 sm:mb-6">
<CardHeader> <CardHeader className="px-4 py-4 sm:px-6">
<CardTitle className="font-['Intro',sans-serif] text-xl text-yellow-200"> <CardTitle className="font-['Intro',sans-serif] text-lg text-yellow-200 sm:text-xl">
Openstaande Admin Aanvragen ({pendingRequests.length}) Openstaande Admin Aanvragen ({pendingRequests.length})
</CardTitle> </CardTitle>
<CardDescription className="text-yellow-200/60"> <CardDescription className="text-sm text-yellow-200/60">
Gebruikers die admin toegang hebben aangevraagd Gebruikers die admin toegang hebben aangevraagd
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="px-4 pb-4 sm:px-6 sm:pb-6">
<div className="space-y-3"> <div className="space-y-3">
{pendingRequests.map((request) => ( {pendingRequests.map((request) => (
<div <div
key={request.id} key={request.id}
className="flex items-center justify-between rounded-lg border border-yellow-500/20 bg-yellow-500/5 p-4" className="flex flex-col gap-3 rounded-lg border border-yellow-500/20 bg-yellow-500/5 p-3 sm:flex-row sm:items-center sm:justify-between sm:p-4"
> >
<div> <div className="min-w-0">
<p className="font-medium text-white"> <p className="truncate font-medium text-white">
{request.userName} {request.userName}
</p> </p>
<p className="text-sm text-white/60"> <p className="truncate text-sm text-white/60">
{request.userEmail} {request.userEmail}
</p> </p>
<p className="text-white/40 text-xs"> <p className="text-white/40 text-xs">
@@ -455,7 +458,7 @@ function AdminPage() {
)} )}
</p> </p>
</div> </div>
<div className="flex gap-2"> <div className="flex flex-col gap-2 sm:flex-row">
<Button <Button
onClick={() => handleApprove(request.id)} onClick={() => handleApprove(request.id)}
disabled={approveRequestMutation.isPending} disabled={approveRequestMutation.isPending}
@@ -463,7 +466,8 @@ function AdminPage() {
className="bg-green-600 text-white hover:bg-green-700" className="bg-green-600 text-white hover:bg-green-700"
> >
<Check className="mr-1 h-4 w-4" /> <Check className="mr-1 h-4 w-4" />
Goedkeuren <span className="hidden sm:inline">Goedkeuren</span>
<span className="sm:hidden">Goedkeuren</span>
</Button> </Button>
<Button <Button
onClick={() => handleReject(request.id)} onClick={() => handleReject(request.id)}
@@ -484,13 +488,13 @@ function AdminPage() {
)} )}
{/* Stats Cards */} {/* Stats Cards */}
<div className="mb-8 grid grid-cols-1 gap-6 md:grid-cols-4"> <div className="mb-8 grid grid-cols-2 gap-3 sm:grid-cols-3 sm:gap-4 lg:grid-cols-5 lg:gap-6">
<Card className="border-white/10 bg-white/5"> <Card className="border-white/10 bg-white/5">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardDescription className="text-white/60"> <CardDescription className="text-white/60 text-xs sm:text-sm">
Totaal inschrijvingen Totaal inschrijvingen
</CardDescription> </CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-4xl text-white"> <CardTitle className="font-['Intro',sans-serif] text-2xl text-white sm:text-3xl lg:text-4xl">
{stats?.total ?? 0} {stats?.total ?? 0}
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
@@ -501,15 +505,15 @@ function AdminPage() {
<Card className="border-white/10 bg-white/5"> <Card className="border-white/10 bg-white/5">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardDescription className="text-white/60"> <CardDescription className="text-white/60 text-xs sm:text-sm">
Vandaag ingeschreven Vandaag ingeschreven
</CardDescription> </CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-4xl text-white"> <CardTitle className="font-['Intro',sans-serif] text-2xl text-white sm:text-3xl lg:text-4xl">
{stats?.today ?? 0} {stats?.today ?? 0}
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<span className="text-sm text-white/40"> <span className="text-white/40 text-xs sm:text-sm">
Nieuwe registraties vandaag Nieuwe registraties vandaag
</span> </span>
</CardContent> </CardContent>
@@ -517,21 +521,21 @@ function AdminPage() {
<Card className="border-amber-400/20 bg-amber-400/5"> <Card className="border-amber-400/20 bg-amber-400/5">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardDescription className="text-amber-300/70"> <CardDescription className="text-amber-300/70 text-xs sm:text-sm">
Artiesten Artiesten
</CardDescription> </CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-4xl text-amber-300"> <CardTitle className="font-['Intro',sans-serif] text-2xl text-amber-300 sm:text-3xl lg:text-4xl">
{performerCount} {performerCount}
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="space-y-1"> <div className="space-y-1">
{stats?.byArtForm.slice(0, 4).map((item) => ( {stats?.byArtForm.slice(0, 2).map((item) => (
<div <div
key={item.artForm} key={item.artForm}
className="flex items-center justify-between text-xs" className="flex items-center justify-between text-xs"
> >
<span className="text-amber-300/70"> <span className="truncate text-amber-300/70">
{item.artForm || "Onbekend"} {item.artForm || "Onbekend"}
</span> </span>
<span className="text-amber-300">{item.count}</span> <span className="text-amber-300">{item.count}</span>
@@ -543,10 +547,10 @@ function AdminPage() {
<Card className="border-teal-400/20 bg-teal-400/5"> <Card className="border-teal-400/20 bg-teal-400/5">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
<CardDescription className="text-teal-300/70"> <CardDescription className="text-teal-300/70 text-xs sm:text-sm">
Bezoekers Bezoekers
</CardDescription> </CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-4xl text-teal-300"> <CardTitle className="font-['Intro',sans-serif] text-2xl text-teal-300 sm:text-3xl lg:text-4xl">
{watcherCount} {watcherCount}
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
@@ -564,7 +568,80 @@ function AdminPage() {
{totalWatcherAttendees} {totalWatcherAttendees}
</span> </span>
</div> </div>
<div className="hidden sm:flex sm:items-center sm:justify-between">
<span className="text-teal-300/70">Drinkkaart</span>
<span className="text-teal-300">{totalDrinkCardValue}</span>
</div>
</div>
</CardContent>
</Card>
<Card className="border-pink-400/20 bg-pink-400/5">
<CardHeader className="pb-2">
<CardDescription className="text-pink-300/70 text-xs sm:text-sm">
Vrijwillige Gifts
</CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-2xl text-white sm:text-3xl lg:text-4xl">
{stats?.today ?? 0}
</CardTitle>
</CardHeader>
<CardContent>
<span className="text-white/40 text-xs sm:text-sm">
Nieuwe registraties vandaag
</span>
</CardContent>
</Card>
<Card className="border-amber-400/20 bg-amber-400/5">
<CardHeader className="pb-2">
<CardDescription className="text-amber-300/70">
Artiesten
</CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-2xl text-amber-300 sm:text-3xl lg:text-4xl">
{performerCount}
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-1">
{stats?.byArtForm.slice(0, 2).map((item) => (
<div
key={item.artForm}
className="flex items-center justify-between text-xs"
>
<span className="truncate text-amber-300/70">
{item.artForm || "Onbekend"}
</span>
<span className="text-amber-300">{item.count}</span>
</div>
))}
</div>
</CardContent>
</Card>
<Card className="border-teal-400/20 bg-teal-400/5">
<CardHeader className="pb-2">
<CardDescription className="text-teal-300/70">
Bezoekers
</CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-2xl text-teal-300 sm:text-3xl lg:text-4xl">
{watcherCount}
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-1 text-xs">
{totalGuestCount > 0 && (
<div className="flex items-center justify-between">
<span className="text-teal-300/70">Inclusief gasten</span>
<span className="text-teal-300">+{totalGuestCount}</span>
</div>
)}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-teal-300/70">Totaal aanwezig</span>
<span className="font-semibold text-teal-300">
{totalWatcherAttendees}
</span>
</div>
<div className="hidden sm:flex sm:items-center sm:justify-between">
<span className="text-teal-300/70">Drinkkaart</span> <span className="text-teal-300/70">Drinkkaart</span>
<span className="text-teal-300">{totalDrinkCardValue}</span> <span className="text-teal-300">{totalDrinkCardValue}</span>
</div> </div>
@@ -577,12 +654,12 @@ function AdminPage() {
<CardDescription className="text-pink-300/70"> <CardDescription className="text-pink-300/70">
Vrijwillige Gifts Vrijwillige Gifts
</CardDescription> </CardDescription>
<CardTitle className="font-['Intro',sans-serif] text-4xl text-pink-300"> <CardTitle className="font-['Intro',sans-serif] text-2xl text-pink-300 sm:text-3xl lg:text-4xl">
{Math.round(totalGiftRevenue / 100)} {Math.round(totalGiftRevenue / 100)}
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<span className="text-sm text-white/40"> <span className="text-white/40 text-xs sm:text-sm">
Totale gift opbrengst Totale gift opbrengst
</span> </span>
</CardContent> </CardContent>
@@ -591,17 +668,17 @@ function AdminPage() {
{/* Filters */} {/* Filters */}
<Card className="mb-6 border-white/10 bg-white/5"> <Card className="mb-6 border-white/10 bg-white/5">
<CardHeader> <CardHeader className="px-4 py-4 sm:px-6 sm:py-6">
<CardTitle className="font-['Intro',sans-serif] text-white text-xl"> <CardTitle className="font-['Intro',sans-serif] text-lg text-white sm:text-xl">
Filters Filters
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="px-4 pb-4 sm:px-6 sm:pb-6">
<div className="grid grid-cols-1 gap-4 md:grid-cols-5"> <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 sm:gap-4 lg:grid-cols-5">
<div> <div>
<label <label
htmlFor="search" htmlFor="search"
className="mb-2 block text-sm text-white/60" className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
> >
Zoeken Zoeken
</label> </label>
@@ -612,7 +689,7 @@ function AdminPage() {
placeholder="Naam of email..." placeholder="Naam of email..."
value={search} value={search}
onChange={(e) => setSearch(e.target.value)} onChange={(e) => setSearch(e.target.value)}
className="border-white/20 bg-white/10 pl-10 text-white placeholder:text-white/40" className="border-white/20 bg-white/10 pl-10 text-sm text-white placeholder:text-white/40 sm:text-base"
/> />
</div> </div>
</div> </div>
@@ -620,7 +697,7 @@ function AdminPage() {
<div> <div>
<label <label
htmlFor="typeFilter" htmlFor="typeFilter"
className="mb-2 block text-sm text-white/60" className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
> >
Type Type
</label> </label>
@@ -632,7 +709,7 @@ function AdminPage() {
e.target.value as "performer" | "watcher" | "", e.target.value as "performer" | "watcher" | "",
) )
} }
className="w-full rounded-md border border-white/20 bg-white/10 px-3 py-2 text-white focus:outline-none focus:ring-2 focus:ring-white/20" className="w-full rounded-md border border-white/20 bg-white/10 px-3 py-2 text-sm text-white focus:outline-none focus:ring-2 focus:ring-white/20 sm:text-base"
> >
<option value="" className="bg-[#214e51]"> <option value="" className="bg-[#214e51]">
Alle types Alle types
@@ -649,7 +726,7 @@ function AdminPage() {
<div> <div>
<label <label
htmlFor="artForm" htmlFor="artForm"
className="mb-2 block text-sm text-white/60" className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
> >
Kunstvorm Kunstvorm
</label> </label>
@@ -658,14 +735,14 @@ function AdminPage() {
placeholder="Filter op kunstvorm..." placeholder="Filter op kunstvorm..."
value={artForm} value={artForm}
onChange={(e) => setArtForm(e.target.value)} onChange={(e) => setArtForm(e.target.value)}
className="border-white/20 bg-white/10 text-white placeholder:text-white/40" className="border-white/20 bg-white/10 text-sm text-white placeholder:text-white/40 sm:text-base"
/> />
</div> </div>
<div> <div>
<label <label
htmlFor="fromDate" htmlFor="fromDate"
className="mb-2 block text-sm text-white/60" className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
> >
Vanaf Vanaf
</label> </label>
@@ -674,14 +751,14 @@ function AdminPage() {
type="date" type="date"
value={fromDate} value={fromDate}
onChange={(e) => setFromDate(e.target.value)} onChange={(e) => setFromDate(e.target.value)}
className="border-white/20 bg-white/10 text-white [color-scheme:dark]" className="border-white/20 bg-white/10 text-sm text-white [color-scheme:dark] sm:text-base"
/> />
</div> </div>
<div> <div>
<label <label
htmlFor="toDate" htmlFor="toDate"
className="mb-2 block text-sm text-white/60" className="mb-1.5 block text-white/60 text-xs sm:mb-2 sm:text-sm"
> >
Tot Tot
</label> </label>
@@ -690,7 +767,7 @@ function AdminPage() {
type="date" type="date"
value={toDate} value={toDate}
onChange={(e) => setToDate(e.target.value)} onChange={(e) => setToDate(e.target.value)}
className="border-white/20 bg-white/10 text-white [color-scheme:dark]" className="border-white/20 bg-white/10 text-sm text-white [color-scheme:dark] sm:text-base"
/> />
</div> </div>
</div> </div>
@@ -698,24 +775,25 @@ function AdminPage() {
</Card> </Card>
{/* Export Button */} {/* Export Button */}
<div className="mb-6 flex items-center justify-between"> <div className="mb-4 flex flex-col gap-2 sm:mb-6 sm:flex-row sm:items-center sm:justify-between">
<p className="text-white/60"> <p className="text-sm text-white/60">
{pagination?.total ?? 0} registraties gevonden {pagination?.total ?? 0} registraties gevonden
</p> </p>
<Button <Button
onClick={handleExport} onClick={handleExport}
disabled={exportMutation.isPending} disabled={exportMutation.isPending}
className="bg-white text-[#214e51] hover:bg-white/90" className="w-full bg-white text-[#214e51] hover:bg-white/90 sm:w-auto"
> >
<Download className="mr-2 h-4 w-4" /> <Download className="mr-2 h-4 w-4" />
{exportMutation.isPending ? "Exporteren..." : "Exporteer CSV"} {exportMutation.isPending ? "Exporteren..." : "Exporteer CSV"}
</Button> </Button>
</div> </div>
{/* Registrations Table */} {/* Registrations Table / Cards */}
<Card className="border-white/10 bg-white/5"> <Card className="border-white/10 bg-white/5">
<CardContent className="p-0"> <CardContent className="p-0">
<div className="overflow-x-auto"> {/* Desktop Table */}
<div className="hidden overflow-x-auto lg:block">
<table className="w-full"> <table className="w-full">
<thead> <thead>
<tr className="border-white/10 border-b"> <tr className="border-white/10 border-b">
@@ -898,22 +976,163 @@ function AdminPage() {
</tbody> </tbody>
</table> </table>
</div> </div>
{/* Mobile Cards */}
<div className="lg:hidden">
{registrationsQuery.isLoading ? (
<div className="px-4 py-8 text-center text-white/60">
Laden...
</div>
) : sortedRegistrations.length === 0 ? (
<div className="px-4 py-8 text-center text-white/60">
Geen registraties gevonden
</div>
) : (
<div className="divide-y divide-white/5">
{sortedRegistrations.map((reg) => {
const isPerformer = reg.registrationType === "performer";
const guestCount = (() => {
if (!reg.guests) return 0;
try {
const g = JSON.parse(reg.guests as string);
return Array.isArray(g) ? g.length : 0;
} catch {
return 0;
}
})();
const detailLabel = isPerformer
? reg.artForm || "-"
: `${reg.drinkCardValue ?? 5} drinkkaart`;
const dateLabel = (() => {
try {
return new Date(reg.createdAt).toLocaleDateString(
"nl-BE",
{
day: "2-digit",
month: "2-digit",
year: "2-digit",
},
);
} catch {
return "-";
}
})();
return (
<div key={reg.id} className="p-4 hover:bg-white/5">
<div className="flex items-start justify-between gap-3">
<div className="min-w-0 flex-1">
<div className="flex items-center gap-2">
<span className="truncate font-medium text-white">
{reg.firstName} {reg.lastName}
</span>
</div>
<div className="mt-1 flex items-center gap-2 text-white/60 text-xs">
<span className="truncate">{reg.email}</span>
{reg.phone && (
<span className="shrink-0"> {reg.phone}</span>
)}
</div>
</div>
<div className="flex items-center gap-2">
<span
className={`shrink-0 rounded-full px-2 py-0.5 font-semibold text-xs ${isPerformer ? "bg-amber-400/15 text-amber-300" : "bg-teal-400/15 text-teal-300"}`}
>
{isPerformer ? "Artiest" : "Bezoeker"}
</span>
{reg.managementToken && (
<button
type="button"
title="Kopieer beheerlink"
onClick={() =>
handleCopyManageUrl(
reg.managementToken as string,
reg.id,
)
}
className="shrink-0 rounded p-1.5 text-white/40 transition-colors hover:bg-white/10 hover:text-white"
>
{copiedId === reg.id ? (
<ClipboardCheck className="h-4 w-4 text-green-400" />
) : (
<Clipboard className="h-4 w-4" />
)}
</button>
)}
</div>
</div>
<div className="mt-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-xs">
<div className="text-white/70">
<span className="text-white/40">Details:</span>{" "}
{detailLabel}
</div>
{guestCount > 0 && (
<div className="text-white/70">
<span className="text-white/40">Gasten:</span>{" "}
{guestCount}
</div>
)}
{(reg.giftAmount ?? 0) > 0 && (
<div className="text-pink-300">
<span className="text-white/40">Gift:</span>{" "}
{formatCents(reg.giftAmount)}
</div>
)}
{!isPerformer && (
<div>
<span className="text-white/40">Betaling:</span>{" "}
{reg.paymentStatus === "paid" ? (
<span className="inline-flex items-center gap-1 font-medium text-green-400">
<Check className="h-3 w-3" />
Betaald
</span>
) : reg.paymentStatus ===
"extra_payment_pending" ? (
<span className="inline-flex items-center gap-1 font-medium text-orange-400">
<span className="h-1 w-1 rounded-full bg-orange-400" />
Extra (
{((reg.paymentAmount ?? 0) / 100).toFixed(0)})
</span>
) : (
<span className="text-yellow-400">Open</span>
)}
</div>
)}
<div className="text-white/50">{dateLabel}</div>
</div>
</div>
);
})}
</div>
)}
</div>
</CardContent> </CardContent>
</Card> </Card>
{/* Pagination */} {/* Pagination */}
{pagination && pagination.totalPages > 1 && ( {pagination && pagination.totalPages > 1 && (
<div className="mt-6 flex items-center justify-center gap-2"> <div className="mt-4 flex items-center justify-center gap-2 sm:mt-6">
<Button <Button
onClick={() => setPage((p) => Math.max(1, p - 1))} onClick={() => setPage((p) => Math.max(1, p - 1))}
disabled={page === 1} disabled={page === 1}
variant="outline" variant="outline"
className="border-white/20 bg-transparent text-white hover:bg-white/10 disabled:opacity-50" size="sm"
className="border-white/20 bg-transparent px-2 text-sm text-white hover:bg-white/10 disabled:opacity-50 sm:px-4"
> >
Vorige <span className="hidden sm:inline">Vorige</span>
<span className="sm:hidden"></span>
</Button> </Button>
<span className="mx-4 text-white"> <span className="mx-2 text-sm text-white sm:mx-4">
Pagina {page} van {pagination.totalPages} <span className="sm:hidden">
{page}/{pagination.totalPages}
</span>
<span className="hidden sm:inline">
Pagina {page} van {pagination.totalPages}
</span>
</span> </span>
<Button <Button
onClick={() => onClick={() =>
@@ -921,9 +1140,11 @@ function AdminPage() {
} }
disabled={page === pagination.totalPages} disabled={page === pagination.totalPages}
variant="outline" variant="outline"
className="border-white/20 bg-transparent text-white hover:bg-white/10 disabled:opacity-50" size="sm"
className="border-white/20 bg-transparent px-2 text-sm text-white hover:bg-white/10 disabled:opacity-50 sm:px-4"
> >
Volgende <span className="hidden sm:inline">Volgende</span>
<span className="sm:hidden"></span>
</Button> </Button>
</div> </div>
)} )}

View File

@@ -427,7 +427,7 @@ function EditForm({ token, initialData, onCancel, onSaved }: EditFormProps) {
onChange={(e) => onChange={(e) =>
setFormData((p) => ({ ...p, extraQuestions: e.target.value })) setFormData((p) => ({ ...p, extraQuestions: e.target.value }))
} }
className="w-full border border-white/10 resize-none bg-transparent p-2 text-lg text-white placeholder:text-white/40 focus:outline-none" className="w-full resize-none border border-white/10 bg-transparent p-2 text-lg text-white placeholder:text-white/40 focus:outline-none"
/> />
</div> </div>

View File

@@ -34,6 +34,9 @@ export const web = await TanStackStart("web", {
LEMON_SQUEEZY_API_KEY: getEnvVar("LEMON_SQUEEZY_API_KEY"), LEMON_SQUEEZY_API_KEY: getEnvVar("LEMON_SQUEEZY_API_KEY"),
LEMON_SQUEEZY_STORE_ID: getEnvVar("LEMON_SQUEEZY_STORE_ID"), LEMON_SQUEEZY_STORE_ID: getEnvVar("LEMON_SQUEEZY_STORE_ID"),
LEMON_SQUEEZY_VARIANT_ID: getEnvVar("LEMON_SQUEEZY_VARIANT_ID"), LEMON_SQUEEZY_VARIANT_ID: getEnvVar("LEMON_SQUEEZY_VARIANT_ID"),
LEMON_SQUEEZY_DRINKKAART_VARIANT_ID: getEnvVar(
"LEMON_SQUEEZY_DRINKKAART_VARIANT_ID",
),
LEMON_SQUEEZY_WEBHOOK_SECRET: getEnvVar("LEMON_SQUEEZY_WEBHOOK_SECRET"), LEMON_SQUEEZY_WEBHOOK_SECRET: getEnvVar("LEMON_SQUEEZY_WEBHOOK_SECRET"),
}, },
domains: ["kunstenkamp.be", "www.kunstenkamp.be"], domains: ["kunstenkamp.be", "www.kunstenkamp.be"],