feat: implement tenant OAuth flow and guest achievements

This commit is contained in:
2025-09-25 08:32:37 +02:00
parent ef6203c603
commit b22d91ed32
84 changed files with 5984 additions and 1399 deletions

View File

@@ -1,7 +1,8 @@
import React from 'react';
import { getEvents } from '../api';
import { Button } from '@/components/ui/button';
import { Link, useNavigate } from 'react-router-dom';
import { getEvents } from '../api';
import { isAuthError } from '../auth/tokens';
export default function EventsPage() {
const [rows, setRows] = React.useState<any[]>([]);
@@ -11,7 +12,15 @@ export default function EventsPage() {
React.useEffect(() => {
(async () => {
try { setRows(await getEvents()); } catch (e) { setError('Laden fehlgeschlagen'); } finally { setLoading(false); }
try {
setRows(await getEvents());
} catch (err) {
if (!isAuthError(err)) {
setError('Laden fehlgeschlagen');
}
} finally {
setLoading(false);
}
})();
}, []);
@@ -20,24 +29,32 @@ export default function EventsPage() {
<div className="mb-3 flex items-center justify-between">
<h1 className="text-lg font-semibold">Meine Events</h1>
<div className="flex gap-2">
<Button variant="secondary" onClick={() => nav('/admin/events/new')}>Neues Event</Button>
<Link to="/admin/settings"><Button variant="secondary">Einstellungen</Button></Link>
<Button variant="secondary" onClick={() => nav('/admin/events/new')}>
Neues Event
</Button>
<Link to="/admin/settings">
<Button variant="secondary">Einstellungen</Button>
</Link>
</div>
</div>
{loading && <div>Lade</div>}
{error && <div className="rounded border border-red-300 bg-red-50 p-2 text-sm text-red-700">{error}</div>}
{loading && <div>Lade ...</div>}
{error && (
<div className="rounded border border-red-300 bg-red-50 p-2 text-sm text-red-700">{error}</div>
)}
<div className="divide-y rounded border">
{rows.map((e) => (
<div key={e.id} className="flex items-center justify-between p-3">
{rows.map((event) => (
<div key={event.id} className="flex items-center justify-between p-3">
<div className="text-sm">
<div className="font-medium">{renderName(e.name)}</div>
<div className="text-muted-foreground">Slug: {e.slug} · Datum: {e.date ?? '-'}</div>
<div className="font-medium">{renderName(event.name)}</div>
<div className="text-muted-foreground">Slug: {event.slug} <EFBFBD> Datum: {event.date ?? '-'}</div>
</div>
<div className="flex items-center gap-2">
<Link to={`/admin/events/view?id=${e.id}`} className="text-sm underline">details</Link>
<Link to={`/admin/events/edit?id=${e.id}`} className="text-sm underline">bearbeiten</Link>
<Link to={`/admin/events/photos?id=${e.id}`} className="text-sm underline">fotos</Link>
<a className="text-sm underline" href={`/e/${e.slug}`} target="_blank">öffnen</a>
<div className="flex items-center gap-2 text-sm underline">
<Link to={`/admin/events/view?id=${event.id}`}>details</Link>
<Link to={`/admin/events/edit?id=${event.id}`}>bearbeiten</Link>
<Link to={`/admin/events/photos?id=${event.id}`}>fotos</Link>
<a href={`/e/${event.slug}`} target="_blank" rel="noreferrer">
<EFBFBD>ffnen
</a>
</div>
</div>
))}