import React from 'react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { ArrowLeft, Loader2, Mail, Sparkles, Trash2, Users } from 'lucide-react'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { AdminLayout } from '../components/AdminLayout'; import { EventMember, getEvent, getEventMembers, inviteEventMember, removeEventMember, TenantEvent, } from '../api'; import { isAuthError } from '../auth/tokens'; import { ADMIN_EVENTS_PATH } from '../constants'; type InviteForm = { email: string; name: string; role: string; }; const emptyInvite: InviteForm = { email: '', name: '', role: 'member', }; export default function EventMembersPage() { const params = useParams<{ slug?: string }>(); const [searchParams] = useSearchParams(); const slug = params.slug ?? searchParams.get('slug') ?? null; const navigate = useNavigate(); const [event, setEvent] = React.useState(null); const [members, setMembers] = React.useState([]); const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(null); const [invite, setInvite] = React.useState(emptyInvite); const [inviting, setInviting] = React.useState(false); const [membersUnavailable, setMembersUnavailable] = React.useState(false); React.useEffect(() => { if (!slug) { setError('Kein Event-Slug angegeben.'); setLoading(false); return; } let cancelled = false; (async () => { try { setLoading(true); const eventData = await getEvent(slug); if (cancelled) return; setEvent(eventData); const response = await getEventMembers(slug); if (cancelled) return; setMembers(response.data); setMembersUnavailable(false); } catch (err) { if (err instanceof Error && err.message.includes('Mitgliederverwaltung')) { setMembersUnavailable(true); } else if (!isAuthError(err)) { setError('Mitglieder konnten nicht geladen werden.'); } } finally { if (!cancelled) { setLoading(false); } } })(); return () => { cancelled = true; }; }, [slug]); async function handleInvite(event: React.FormEvent) { event.preventDefault(); if (!slug) return; if (!invite.email.trim()) { setError('Bitte gib eine E-Mail-Adresse ein.'); return; } setInviting(true); try { const member = await inviteEventMember(slug, { email: invite.email.trim(), name: invite.name.trim() || undefined, role: invite.role, }); setMembers((prev) => [member, ...prev]); setInvite(emptyInvite); setMembersUnavailable(false); } catch (err) { if (err instanceof Error && err.message.includes('Mitgliederverwaltung')) { setMembersUnavailable(true); } else if (!isAuthError(err)) { setError('Einladung konnte nicht verschickt werden.'); } } finally { setInviting(false); } } async function handleRemove(member: EventMember) { if (!slug) return; if (!window.confirm(`${member.name} wirklich entfernen?`)) return; try { await removeEventMember(slug, member.id); setMembers((prev) => prev.filter((entry) => entry.id !== member.id)); } catch (err) { if (!isAuthError(err)) { setError('Mitglied konnte nicht entfernt werden.'); } } } const actions = ( ); return ( {error && ( Fehler {error} )} {loading ? ( ) : !event ? ( Event nicht gefunden Bitte kehre zur Eventliste zurueck. ) : ( <> {renderName(event.name)} Status: {event.status === 'published' ? 'Veroeffentlicht' : 'Entwurf'}

Mitglieder

{membersUnavailable ? ( Feature noch nicht aktiviert Die Mitgliederverwaltung ist fuer dieses Event noch nicht verfuegbar. Bitte kontaktiere den Support, um das Feature freizuschalten. ) : members.length === 0 ? ( ) : (
{members.map((member) => (

{member.name}

{member.email}

Status: {member.status ?? 'aktiv'} {member.joined_at && Beigetreten: {formatDate(member.joined_at)}}
{mapRole(member.role)}
))}
)}

Neues Mitglied einladen

setInvite((prev) => ({ ...prev, email: event.target.value }))} required />
setInvite((prev) => ({ ...prev, name: event.target.value }))} />
)}
); } function EmptyState({ message }: { message: string }) { return (

{message}

); } function MembersSkeleton() { return (
{Array.from({ length: 3 }).map((_, index) => (
))}
); } function renderName(name: TenantEvent['name']): string { if (typeof name === 'string') { return name; } return name?.de ?? name?.en ?? Object.values(name ?? {})[0] ?? 'Unbenanntes Event'; } function mapRole(role: string): string { switch (role) { case 'tenant_admin': return 'Tenant-Admin'; case 'member': return 'Mitglied'; case 'guest': return 'Gast'; default: return role; } } function formatDate(value: string | null | undefined): string { if (!value) return '--'; const date = new Date(value); if (Number.isNaN(date.getTime())) return '--'; return date.toLocaleDateString('de-DE', { day: '2-digit', month: 'short', year: 'numeric' }); }