feat: enhance accessibility and testing with data-test attributes and improve error handling
This commit is contained in:
@@ -56,20 +56,21 @@ export default async function EventDetailPage({ params }: PageProps) {
|
||||
|
||||
if (!event) return <div>Veranstaltung nicht gefunden</div>;
|
||||
|
||||
const e = event as Record<string, unknown>;
|
||||
const eventData = event as Record<string, unknown>;
|
||||
|
||||
return (
|
||||
<CmsPageShell account={account} title={String(e.name)}>
|
||||
<CmsPageShell account={account} title={String(eventData.name)}>
|
||||
<div className="flex w-full flex-col gap-6">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">{String(e.name)}</h1>
|
||||
<h1 className="text-2xl font-bold">{String(eventData.name)}</h1>
|
||||
<Badge
|
||||
variant={STATUS_VARIANT[String(e.status)] ?? 'secondary'}
|
||||
variant={STATUS_VARIANT[String(eventData.status)] ?? 'secondary'}
|
||||
className="mt-1"
|
||||
>
|
||||
{STATUS_LABEL[String(e.status)] ?? String(e.status)}
|
||||
{STATUS_LABEL[String(eventData.status)] ??
|
||||
String(eventData.status)}
|
||||
</Badge>
|
||||
</div>
|
||||
<Button>
|
||||
@@ -86,7 +87,7 @@ export default async function EventDetailPage({ params }: PageProps) {
|
||||
<div>
|
||||
<p className="text-muted-foreground text-xs">Datum</p>
|
||||
<p className="font-semibold">
|
||||
{formatDate(e.event_date as string)}
|
||||
{formatDate(eventData.event_date as string)}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -97,7 +98,8 @@ export default async function EventDetailPage({ params }: PageProps) {
|
||||
<div>
|
||||
<p className="text-muted-foreground text-xs">Uhrzeit</p>
|
||||
<p className="font-semibold">
|
||||
{String(e.start_time ?? '—')} – {String(e.end_time ?? '—')}
|
||||
{String(eventData.start_time ?? '—')} –{' '}
|
||||
{String(eventData.end_time ?? '—')}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -107,7 +109,9 @@ export default async function EventDetailPage({ params }: PageProps) {
|
||||
<MapPin className="text-primary h-5 w-5" />
|
||||
<div>
|
||||
<p className="text-muted-foreground text-xs">Ort</p>
|
||||
<p className="font-semibold">{String(e.location ?? '—')}</p>
|
||||
<p className="font-semibold">
|
||||
{String(eventData.location ?? '—')}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -117,7 +121,7 @@ export default async function EventDetailPage({ params }: PageProps) {
|
||||
<div>
|
||||
<p className="text-muted-foreground text-xs">Anmeldungen</p>
|
||||
<p className="font-semibold">
|
||||
{registrations.length} / {String(e.capacity ?? '∞')}
|
||||
{registrations.length} / {String(eventData.capacity ?? '∞')}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -125,14 +129,14 @@ export default async function EventDetailPage({ params }: PageProps) {
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
{e.description ? (
|
||||
{eventData.description ? (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Beschreibung</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-muted-foreground text-sm whitespace-pre-wrap">
|
||||
{String(e.description)}
|
||||
{String(eventData.description)}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -47,19 +47,21 @@ export default async function EventsPage({ params, searchParams }: PageProps) {
|
||||
const events = await api.listEvents(acct.id, { page });
|
||||
|
||||
// Fetch registration counts for all events on this page
|
||||
const eventIds = events.data.map((e: Record<string, unknown>) =>
|
||||
String(e.id),
|
||||
const eventIds = events.data.map((eventItem: Record<string, unknown>) =>
|
||||
String(eventItem.id),
|
||||
);
|
||||
const registrationCounts = await api.getRegistrationCounts(eventIds);
|
||||
|
||||
// Pre-compute stats before rendering
|
||||
const uniqueLocationCount = new Set(
|
||||
events.data.map((e: Record<string, unknown>) => e.location).filter(Boolean),
|
||||
events.data
|
||||
.map((eventItem: Record<string, unknown>) => eventItem.location)
|
||||
.filter(Boolean),
|
||||
).size;
|
||||
|
||||
const totalCapacity = events.data.reduce(
|
||||
(sum: number, e: Record<string, unknown>) =>
|
||||
sum + (Number(e.capacity) || 0),
|
||||
(sum: number, eventItem: Record<string, unknown>) =>
|
||||
sum + (Number(eventItem.capacity) || 0),
|
||||
0,
|
||||
);
|
||||
|
||||
@@ -74,7 +76,7 @@ export default async function EventsPage({ params, searchParams }: PageProps) {
|
||||
</div>
|
||||
|
||||
<Link href={`/home/${account}/events/new`}>
|
||||
<Button>
|
||||
<Button data-test="events-new-btn">
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
{t('newEvent')}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user