The admin events page fetched every event on each load and rendered them all, which grows without bound as the archive fills up. GET /api/events now takes optional page and pageSize parameters and returns total alongside the rows; pagination is opt-in, so the public pages and the admin filter dropdowns that pass neither still get the full list and the untouched response shape. Page size is selectable (10/25/50/100) and deleting the last event on a page falls back to the new last page instead of showing an empty table. The ?edit=<id> deep link no longer depends on the target being in the current page: when it is missing from the loaded rows the event is fetched directly, guarded by a ref so the modal opens once. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
46 lines
1.8 KiB
TypeScript
46 lines
1.8 KiB
TypeScript
import { fetchApi } from './client';
|
|
import type { Event } from './types';
|
|
|
|
export const eventsApi = {
|
|
getAll: (params?: { status?: string; upcoming?: boolean; page?: number; pageSize?: number }) => {
|
|
const query = new URLSearchParams();
|
|
if (params?.status) query.set('status', params.status);
|
|
if (params?.upcoming) query.set('upcoming', 'true');
|
|
// Passing page/pageSize switches the endpoint into paginated mode, which also
|
|
// returns `total`; without them the full list comes back as before.
|
|
if (params?.page) query.set('page', String(params.page));
|
|
if (params?.pageSize) query.set('pageSize', String(params.pageSize));
|
|
return fetchApi<{ events: Event[]; total?: number }>(`/api/events?${query}`);
|
|
},
|
|
|
|
getById: (id: string) => fetchApi<{ event: Event }>(`/api/events/${id}`),
|
|
|
|
getNext: () => fetchApi<{ event: Event | null }>('/api/events/next'),
|
|
|
|
getNextUpcoming: () => fetchApi<{ event: Event | null }>('/api/events/next/upcoming'),
|
|
|
|
create: (data: Partial<Event>) =>
|
|
fetchApi<{ event: Event }>('/api/events', {
|
|
method: 'POST',
|
|
body: JSON.stringify(data),
|
|
}),
|
|
|
|
update: (id: string, data: Partial<Event>) =>
|
|
fetchApi<{ event: Event }>(`/api/events/${id}`, {
|
|
method: 'PUT',
|
|
body: JSON.stringify(data),
|
|
}),
|
|
|
|
delete: (id: string) =>
|
|
fetchApi<{ message: string }>(`/api/events/${id}`, { method: 'DELETE' }),
|
|
|
|
duplicate: (id: string) =>
|
|
fetchApi<{ event: Event; message: string }>(`/api/events/${id}/duplicate`, { method: 'POST' }),
|
|
|
|
getSlugAliases: (id: string) =>
|
|
fetchApi<{ aliases: { slug: string; createdAt: string }[] }>(`/api/events/${id}/slug-aliases`),
|
|
|
|
deleteSlugAlias: (id: string, slug: string) =>
|
|
fetchApi<{ message: string }>(`/api/events/${id}/slug-aliases/${encodeURIComponent(slug)}`, { method: 'DELETE' }),
|
|
};
|