Files
fotospiel-app/resources/js/admin/pages/EventDetailPage.tsx
2025-09-08 14:03:43 +02:00

78 lines
3.3 KiB
TypeScript

import React from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { getEvent, getEventStats, toggleEvent, createInviteLink } from '../api';
import { Button } from '@/components/ui/button';
export default function EventDetailPage() {
const [sp] = useSearchParams();
const id = Number(sp.get('id'));
const nav = useNavigate();
const [ev, setEv] = React.useState<any | null>(null);
const [stats, setStats] = React.useState<{ total: number; featured: number; likes: number } | null>(null);
const [invite, setInvite] = React.useState<string | null>(null);
async function load() {
const e = await getEvent(id);
setEv(e);
setStats(await getEventStats(id));
}
React.useEffect(() => { load(); }, [id]);
async function onToggle() {
const isActive = await toggleEvent(id);
setEv((o: any) => ({ ...(o || {}), is_active: isActive }));
}
async function onInvite() {
const link = await createInviteLink(id);
setInvite(link);
try { await navigator.clipboard.writeText(link); } catch {}
}
if (!ev) return <div className="p-4">Lade</div>;
const joinLink = `${location.origin}/e/${ev.slug}`;
const qrUrl = `/admin/qr?data=${encodeURIComponent(joinLink)}`;
return (
<div className="mx-auto max-w-3xl p-4 space-y-4">
<div className="flex items-center justify-between">
<h1 className="text-lg font-semibold">Event: {renderName(ev.name)}</h1>
<div className="flex gap-2">
<Button variant="secondary" onClick={onToggle}>{ev.is_active ? 'Deaktivieren' : 'Aktivieren'}</Button>
<Button variant="secondary" onClick={() => nav(`/admin/events/photos?id=${id}`)}>Fotos moderieren</Button>
</div>
</div>
<div className="rounded border p-3 text-sm">
<div>Slug: {ev.slug}</div>
<div>Datum: {ev.date ?? '-'}</div>
<div>Status: {ev.is_active ? 'Aktiv' : 'Inaktiv'}</div>
</div>
<div className="grid grid-cols-3 gap-3 text-center text-sm">
<div className="rounded border p-3"><div className="text-2xl font-semibold">{stats?.total ?? 0}</div><div>Fotos</div></div>
<div className="rounded border p-3"><div className="text-2xl font-semibold">{stats?.featured ?? 0}</div><div>Featured</div></div>
<div className="rounded border p-3"><div className="text-2xl font-semibold">{stats?.likes ?? 0}</div><div>Likes gesamt</div></div>
</div>
<div className="rounded border p-3">
<div className="mb-2 text-sm font-medium">Join-Link</div>
<div className="mb-2 flex items-center gap-2">
<input className="w-full rounded border p-2 text-sm" value={joinLink} readOnly />
<Button variant="secondary" onClick={() => navigator.clipboard.writeText(joinLink)}>Kopieren</Button>
</div>
<div className="mb-2 text-sm font-medium">QR</div>
<img src={qrUrl} alt="QR" width={200} height={200} className="rounded border" />
<div className="mt-3">
<Button variant="secondary" onClick={onInvite}>Einladungslink erzeugen</Button>
{invite && <div className="mt-2 text-xs text-muted-foreground">Erzeugt und kopiert: {invite}</div>}
</div>
</div>
</div>
);
}
function renderName(name: any): string {
if (typeof name === 'string') return name;
if (name && (name.de || name.en)) return name.de || name.en;
return JSON.stringify(name);
}