feat: complete CMS v2 with Docker, Fischerei, Meetings, Verband modules + UX audit fixes
Major changes: - Docker Compose: full Supabase stack (11 services) equivalent to supabase CLI - Fischerei module: 16 DB tables, waters/species/stocking/catch books/competitions - Sitzungsprotokolle module: meeting protocols, agenda items, task tracking - Verbandsverwaltung module: federation management, member clubs, contacts, fees - Per-account module activation via Modules page toggle - Site Builder: live CMS data in Puck blocks (courses, events, membership registration) - Public registration APIs: course signup, event registration, membership application - Document generation: PDF member cards, Excel reports, HTML labels - Landing page: real Com.BISS content (no filler text) - UX audit fixes: AccountNotFound component, shared status badges, confirm dialog, pagination, duplicate heading removal, emoji→badge replacement, a11y fixes - QA: healthcheck fix, API auth fix, enum mismatch fix, password required attribute
This commit is contained in:
@@ -6,6 +6,7 @@ import type { CreateEventInput } from '../schema/event.schema';
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
export function createEventManagementApi(client: SupabaseClient<Database>) {
|
||||
const PAGE_SIZE = 25;
|
||||
const db = client;
|
||||
|
||||
return {
|
||||
@@ -14,10 +15,28 @@ export function createEventManagementApi(client: SupabaseClient<Database>) {
|
||||
.eq('account_id', accountId).order('event_date', { ascending: false });
|
||||
if (opts?.status) query = query.eq('status', opts.status);
|
||||
const page = opts?.page ?? 1;
|
||||
query = query.range((page - 1) * 25, page * 25 - 1);
|
||||
query = query.range((page - 1) * PAGE_SIZE, page * PAGE_SIZE - 1);
|
||||
const { data, error, count } = await query;
|
||||
if (error) throw error;
|
||||
return { data: data ?? [], total: count ?? 0 };
|
||||
const total = count ?? 0;
|
||||
return { data: data ?? [], total, page, pageSize: PAGE_SIZE, totalPages: Math.max(1, Math.ceil(total / PAGE_SIZE)) };
|
||||
},
|
||||
|
||||
async getRegistrationCounts(eventIds: string[]) {
|
||||
if (eventIds.length === 0) return {} as Record<string, number>;
|
||||
const { data, error } = await client
|
||||
.from('event_registrations')
|
||||
.select('event_id', { count: 'exact', head: false })
|
||||
.in('event_id', eventIds)
|
||||
.in('status', ['pending', 'confirmed']);
|
||||
if (error) throw error;
|
||||
|
||||
const counts: Record<string, number> = {};
|
||||
for (const row of data ?? []) {
|
||||
const eid = (row as Record<string, unknown>).event_id as string;
|
||||
counts[eid] = (counts[eid] ?? 0) + 1;
|
||||
}
|
||||
return counts;
|
||||
},
|
||||
|
||||
async getEvent(eventId: string) {
|
||||
|
||||
Reference in New Issue
Block a user