fix(events): server-side search/pagination to remove first-100 cap (#346)
Counters and search on Admin → Events were bounded to the first 100 rows
returned from /admin/events?page=1&limit=100, so on instances with more
events the totals were wrong and search couldn't find anything outside
that window. The dashboard's expiring list had the same first-100 issue.
Backend
- adminEvents.js: extend search to include customer_email so the column
shown in the table is actually queryable.
- adminDashboard.js: add totalEvents to /dashboard/stats so the events
page can render an accurate "All (N)" / Total Events counter without
walking the full table on the client.
Frontend
- events.service.ts: getEvents() now accepts search + the full status
enum (active|inactive|archived|draft|expiring); response type matches
the actual {events, pagination} shape.
- admin.service.ts: DashboardStats gains totalEvents.
- EventsListPage.tsx: rewired around server-side pagination, status
filter, and 300ms-debounced search; Prev/Next + range/page indicator
below the table; placeholderData keeps the previous page visible
during fetches; stat cards and "All (N)" pull from /dashboard/stats so
totals stay accurate regardless of the visible page; archive/delete
invalidates dashboard-stats so cards refresh.
- AdminDashboard.tsx: expiring list now fetches getEvents(1, 5,
'expiring') directly instead of slicing the first 100 client-side. As
a side effect the dashboard's "expiring" definition now matches the
backend (was excluding events expiring within the next 24h).
This commit is contained in:
@@ -10,6 +10,7 @@ export interface DashboardStats {
|
||||
viewsTrend: number;
|
||||
downloadsTrend: number;
|
||||
archivedEvents: number;
|
||||
totalEvents: number;
|
||||
}
|
||||
|
||||
export interface SystemHealth {
|
||||
|
||||
@@ -64,11 +64,16 @@ interface UpdateEventData {
|
||||
default_photo_sort?: string;
|
||||
}
|
||||
|
||||
export type EventStatusFilter = 'active' | 'inactive' | 'archived' | 'draft' | 'expiring';
|
||||
|
||||
interface EventsListResponse {
|
||||
events: Event[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
pagination: {
|
||||
page: number;
|
||||
limit: number;
|
||||
total: number;
|
||||
totalPages: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const eventsService = {
|
||||
@@ -76,16 +81,20 @@ export const eventsService = {
|
||||
async getEvents(
|
||||
page: number = 1,
|
||||
limit: number = 20,
|
||||
status?: 'active' | 'inactive' | 'archived' | 'draft'
|
||||
status?: EventStatusFilter,
|
||||
search?: string
|
||||
): Promise<EventsListResponse> {
|
||||
const params = new URLSearchParams({
|
||||
page: page.toString(),
|
||||
limit: limit.toString(),
|
||||
});
|
||||
|
||||
|
||||
if (status) {
|
||||
params.append('status', status);
|
||||
}
|
||||
if (search) {
|
||||
params.append('search', search);
|
||||
}
|
||||
|
||||
const response = await api.get<EventsListResponse>(`/admin/events?${params}`);
|
||||
const data: any = response.data;
|
||||
|
||||
Reference in New Issue
Block a user