Fix: Route-Namen (orte/ort-ausfaelle) und /api/users ergänzt

This commit is contained in:
rene 2026-05-21 22:17:03 +02:00
parent 39981c0d17
commit 957c4a9707
4 changed files with 74 additions and 9 deletions

View file

@ -32,8 +32,8 @@
onMount(async () => {
[orte, ausfaelle] = await Promise.all([
api.get<Veranstaltungsort[]>('/veranstaltungsorte', { sort: 'name' }),
api.get<OrtAusfall[]>('/ort_ausfaelle', { sort: 'von' }),
api.get<Veranstaltungsort[]>('/orte', { sort: 'name' }),
api.get<OrtAusfall[]>('/ort-ausfaelle', { sort: 'von' }),
]);
loading = false;
});
@ -55,10 +55,10 @@
try {
const data = { name: fName.trim(), adresse: fAdresse.trim() || null, typ: fTyp, aktiv: fAktiv };
if (editOrtId) {
const u = await api.put<Veranstaltungsort>('/veranstaltungsorte/' + editOrtId, data);
const u = await api.put<Veranstaltungsort>('/orte/' + editOrtId, data);
orte = orte.map(o => o.id === editOrtId ? u : o);
} else {
const n = await api.post<Veranstaltungsort>('/veranstaltungsorte', data);
const n = await api.post<Veranstaltungsort>('/orte', data);
orte = [...orte, n].sort((a, b) => a.name.localeCompare(b.name));
}
showOrtForm = false;
@ -71,7 +71,7 @@
async function ortLoeschen(id: string) {
if (!confirm('Ort wirklich löschen? Alle verknüpften Termine verlieren die Ortzuordnung.')) return;
await api.del('/veranstaltungsorte/' + id);
await api.del('/orte/' + id);
orte = orte.filter(o => o.id !== id);
ausfaelle = ausfaelle.filter(a => a.ort_id !== id);
}
@ -86,7 +86,7 @@
if (aVon > aBis) { ausfallError = 'Bis muss nach Von liegen.'; return; }
ausfallError = ''; ausfallSaving = true;
try {
const n = await api.post<OrtAusfall>('/ort_ausfaelle', {
const n = await api.post<OrtAusfall>('/ort-ausfaelle', {
ort_id: aOrtId, von: aVon, bis: aBis, grund: aGrund.trim() || null,
});
ausfaelle = [...ausfaelle, n].sort((a, b) => a.von.localeCompare(b.von));
@ -99,7 +99,7 @@
}
async function ausfallLoeschen(id: string) {
await api.del('/ort_ausfaelle/' + id);
await api.del('/ort-ausfaelle/' + id);
ausfaelle = ausfaelle.filter(a => a.id !== id);
}

View file

@ -67,8 +67,8 @@
isAdmin()
? api.get<any[]>('/users', { rolle: 'trainer' })
: Promise.resolve([]),
api.get<Veranstaltungsort[]>('/veranstaltungsorte', { sort: 'name', aktiv: 'true' }),
api.get<OrtAusfall[]>('/ort_ausfaelle', { sort: 'von' }),
api.get<Veranstaltungsort[]>('/orte', { sort: 'name', aktiv: 'true' }),
api.get<OrtAusfall[]>('/ort-ausfaelle', { sort: 'von' }),
]);
loading = false;
});

View file

@ -0,0 +1,18 @@
import { json } from '@sveltejs/kit';
import { getDb, rows } from '$lib/server/db';
import { requireAuth } from '$lib/server/auth';
export async function GET({ request, url }) {
const u = await requireAuth(request);
const db = getDb();
const rolle = url.searchParams.get('rolle');
let query = 'SELECT id, verein_id, email, name, rolle, created FROM users WHERE verein_id = ?';
const params: unknown[] = [u.verein_id];
if (rolle) { query += ' AND rolle = ?'; params.push(rolle); }
query += ' ORDER BY name';
const users = db.prepare(query).all(...params);
return json(users);
}

View file

@ -0,0 +1,47 @@
import { json, error } from '@sveltejs/kit';
import { getDb } from '$lib/server/db';
import { requireAuth, hashPassword } from '$lib/server/auth';
export async function GET({ request, params }) {
const u = await requireAuth(request);
const db = getDb();
const row = db.prepare(
'SELECT id, verein_id, email, name, rolle, created FROM users WHERE id = ? AND verein_id = ?'
).get(params.id, u.verein_id);
if (!row) throw error(404, 'User nicht gefunden');
return json(row);
}
export async function PUT({ request, params }) {
const u = await requireAuth(request);
const db = getDb();
const body = await request.json();
const existing = db.prepare('SELECT id FROM users WHERE id = ? AND verein_id = ?').get(params.id, u.verein_id);
if (!existing) throw error(404, 'User nicht gefunden');
const fields: string[] = [];
const vals: unknown[] = [];
if (body.name !== undefined) { fields.push('name = ?'); vals.push(body.name); }
if (body.email !== undefined) { fields.push('email = ?'); vals.push(body.email.toLowerCase()); }
if (body.rolle !== undefined) { fields.push('rolle = ?'); vals.push(body.rolle || null); }
if (body.password) { fields.push('password_hash = ?'); vals.push(await hashPassword(body.password)); }
if (!fields.length) throw error(400, 'Keine Felder zum Aktualisieren');
fields.push("updated = strftime('%Y-%m-%dT%H:%M:%SZ','now')");
vals.push(params.id, u.verein_id);
db.prepare(`UPDATE users SET ${fields.join(', ')} WHERE id = ? AND verein_id = ?`).run(...vals);
const row = db.prepare('SELECT id, verein_id, email, name, rolle, created FROM users WHERE id = ?').get(params.id);
return json(row);
}
export async function DELETE({ request, params }) {
const u = await requireAuth(request);
if (u.sub === params.id) throw error(400, 'Eigenen Account nicht löschbar');
const db = getDb();
const result = db.prepare('DELETE FROM users WHERE id = ? AND verein_id = ?').run(params.id, u.verein_id);
if (result.changes === 0) throw error(404, 'User nicht gefunden');
return new Response(null, { status: 204 });
}