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

@@ -2,6 +2,7 @@ import React from 'react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { createEvent, updateEvent } from '../api';
import { isAuthError } from '../auth/tokens';
import { useNavigate, useSearchParams } from 'react-router-dom';
export default function EventFormPage() {
@@ -13,10 +14,12 @@ export default function EventFormPage() {
const [date, setDate] = React.useState('');
const [active, setActive] = React.useState(true);
const [saving, setSaving] = React.useState(false);
const [error, setError] = React.useState<string | null>(null);
const isEdit = !!id;
async function save() {
setSaving(true);
setError(null);
try {
if (isEdit) {
await updateEvent(Number(id), { name, slug, date, is_active: active });
@@ -24,21 +27,31 @@ export default function EventFormPage() {
await createEvent({ name, slug, date, is_active: active });
}
nav('/admin/events');
} finally { setSaving(false); }
} catch (e) {
if (!isAuthError(e)) {
setError('Speichern fehlgeschlagen');
}
} finally {
setSaving(false);
}
}
return (
<div className="mx-auto max-w-md p-4 space-y-3">
<div className="mx-auto max-w-md space-y-3 p-4">
<h1 className="text-lg font-semibold">{isEdit ? 'Event bearbeiten' : 'Neues Event'}</h1>
{error && <div className="rounded border border-red-300 bg-red-50 p-2 text-sm text-red-700">{error}</div>}
<Input placeholder="Name" value={name} onChange={(e) => setName(e.target.value)} />
<Input placeholder="Slug" value={slug} onChange={(e) => setSlug(e.target.value)} />
<Input placeholder="Datum" type="date" value={date} onChange={(e) => setDate(e.target.value)} />
<label className="flex items-center gap-2 text-sm"><input type="checkbox" checked={active} onChange={(e) => setActive(e.target.checked)} /> Aktiv</label>
<label className="flex items-center gap-2 text-sm">
<input type="checkbox" checked={active} onChange={(e) => setActive(e.target.checked)} /> Aktiv
</label>
<div className="flex gap-2">
<Button onClick={save} disabled={saving || !name || !slug}>{saving ? 'Speichern…' : 'Speichern'}</Button>
<Button onClick={save} disabled={saving || !name || !slug}>
{saving ? 'Speichern <20>' : 'Speichern'}
</Button>
<Button variant="secondary" onClick={() => nav(-1)}>Abbrechen</Button>
</div>
</div>
);
}