Files
myeasycms-v2/apps/web/app/[locale]/home/[account]/events/[eventId]/page.tsx
T. Zehetbauer c6d564836f
Some checks failed
Workflow / ʦ TypeScript (push) Failing after 17m4s
Workflow / ⚫️ Test (push) Has been skipped
fix: add missing newlines at the end of JSON files; clean up formatting in page components
2026-04-02 11:02:58 +02:00

207 lines
7.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Link from 'next/link';
import {
CalendarDays,
MapPin,
Users,
Clock,
Pencil,
UserPlus,
} from 'lucide-react';
import { getTranslations } from 'next-intl/server';
import { createEventManagementApi } from '@kit/event-management/api';
import { formatDate } from '@kit/shared/dates';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { Badge } from '@kit/ui/badge';
import { Button } from '@kit/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card';
import { CmsPageShell } from '~/components/cms-page-shell';
import {
EVENT_STATUS_LABEL_KEYS,
EVENT_STATUS_VARIANT,
} from '~/lib/status-badges';
import { DeleteEventButton } from './delete-event-button';
interface PageProps {
params: Promise<{ account: string; eventId: string }>;
}
export default async function EventDetailPage({ params }: PageProps) {
const { account, eventId } = await params;
const client = getSupabaseServerClient();
const api = createEventManagementApi(client);
const t = await getTranslations('cms.events');
const [event, registrations] = await Promise.all([
api.getEvent(eventId),
api.getRegistrations(eventId),
]);
if (!event) return <div>{t('notFound')}</div>;
const eventData = event as Record<string, unknown>;
return (
<CmsPageShell account={account} title={String(eventData.name)}>
<div className="flex w-full flex-col gap-6">
{/* Action Buttons */}
<div className="flex justify-end gap-2">
<Button asChild variant="outline" size="sm">
<Link href={`/home/${account}/events/${eventId}/edit`}>
<Pencil className="mr-2 h-4 w-4" />
{t('edit')}
</Link>
</Button>
<DeleteEventButton eventId={eventId} accountSlug={account} />
</div>
{/* Header */}
<div className="flex items-center justify-between">
<div>
<Badge
variant={
EVENT_STATUS_VARIANT[String(eventData.status)] ?? 'secondary'
}
className="mt-1"
>
{t(
EVENT_STATUS_LABEL_KEYS[String(eventData.status)] ??
String(eventData.status),
)}
</Badge>
</div>
<Button>
<UserPlus className="mr-2 h-4 w-4" />
{t('register')}
</Button>
</div>
{/* Detail Cards */}
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<Card>
<CardContent className="flex items-center gap-3 p-4">
<CalendarDays className="text-primary h-5 w-5" />
<div>
<p className="text-muted-foreground text-xs">{t('date')}</p>
<p className="font-semibold">
{formatDate(eventData.event_date as string)}
</p>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="flex items-center gap-3 p-4">
<Clock className="text-primary h-5 w-5" />
<div>
<p className="text-muted-foreground text-xs">{t('time')}</p>
<p className="font-semibold">
{String(eventData.start_time ?? '—')} {' '}
{String(eventData.end_time ?? '—')}
</p>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="flex items-center gap-3 p-4">
<MapPin className="text-primary h-5 w-5" />
<div>
<p className="text-muted-foreground text-xs">{t('location')}</p>
<p className="font-semibold">
{String(eventData.location ?? '—')}
</p>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="flex items-center gap-3 p-4">
<Users className="text-primary h-5 w-5" />
<div>
<p className="text-muted-foreground text-xs">
{t('registrations')}
</p>
<p className="font-semibold">
{registrations.length} / {String(eventData.capacity ?? '∞')}
</p>
</div>
</CardContent>
</Card>
</div>
{/* Description */}
{eventData.description ? (
<Card>
<CardHeader>
<CardTitle>{t('description')}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground text-sm whitespace-pre-wrap">
{String(eventData.description)}
</p>
</CardContent>
</Card>
) : null}
{/* Registrations Table */}
<Card>
<CardHeader>
<CardTitle>
{t('registrationsCount', { count: registrations.length })}
</CardTitle>
</CardHeader>
<CardContent>
{registrations.length === 0 ? (
<p className="text-muted-foreground py-6 text-center text-sm">
{t('noRegistrations')}
</p>
) : (
<div className="overflow-x-auto rounded-md border">
<table className="w-full min-w-[640px] text-sm">
<thead>
<tr className="bg-muted/50 border-b">
<th scope="col" className="p-3 text-left font-medium">
{t('name')}
</th>
<th scope="col" className="p-3 text-left font-medium">
E-Mail
</th>
<th scope="col" className="p-3 text-left font-medium">
{t('parentName')}
</th>
<th scope="col" className="p-3 text-left font-medium">
{t('date')}
</th>
</tr>
</thead>
<tbody>
{registrations.map((reg: Record<string, unknown>) => (
<tr
key={String(reg.id)}
className="hover:bg-muted/30 border-b"
>
<td className="p-3 font-medium">
{String(reg.last_name ?? '')},{' '}
{String(reg.first_name ?? '')}
</td>
<td className="p-3">{String(reg.email ?? '—')}</td>
<td className="p-3">
{String(reg.parent_name ?? '—')}
</td>
<td className="p-3">
{formatDate(reg.created_at as string)}
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</CardContent>
</Card>
</div>
</CmsPageShell>
);
}