Make table page size a configurable setting, not a hardcoded 20

Pagination just landed hardcoded to 20 rows everywhere; add a way to
change that instead of leaving it fixed for every table in the app.

pageSize joins dateFormat/timeFormat on the existing display settings
object (server-side default 20, 5-500 range enforced by the PUT
schema) rather than becoming its own settings section, since it's the
same kind of thing -- an admin-configured, globally-applied display
preference read by every signed-in role via the already-public GET
/api/settings/display endpoint, same as the date/time format already
works.

Renamed the "Date & Time" settings tab/page/route to "Display" (still
just one component, now covering both date/time format and table
pagination) since its scope no longer matches the old name -- kept
Settings.tsx's usual pattern of one page per concern rather than
adding a second, oddly-scoped tab just for one number field.

New web/src/utils/pageSize.ts mirrors utils/date.ts's existing
module-level "set once at startup, read anywhere without prop-
drilling" pattern; usePagination()'s pageSize parameter now defaults
to getPageSize() instead of a literal 20, evaluated fresh on every
call so it picks up a saved change without touching any of the ten
pages already using the hook.

Verified server-side against a temp SQLite DB: pageSize defaults to
20, a partial update sets it without disturbing dateFormat/timeFormat
and vice versa, and it persists across a fresh settings read. Also
checked the default-parameter mechanics directly (re-evaluates the
global value on every call rather than capturing it once, and an
explicit override still wins).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
bobbanandClaude Sonnet 5 committed 2026-09-18 23:58:14 +02:00
1 parent 7bf9b03839
commit b40234a557
10 files changed
+180 -123

No files matched your search

+4 -1
View File
@@ -66,7 +66,10 @@ const updateSchema = z.object({
.optional(),
providerColors: z.record(z.string()).optional(),
integrationColors: z.record(z.string()).optional(),
display: z.object({ dateFormat: z.enum(["ymd", "dmy", "mdy"]), timeFormat: z.enum(["24h", "12h"]) }).partial().optional(),
display: z
.object({ dateFormat: z.enum(["ymd", "dmy", "mdy"]), timeFormat: z.enum(["24h", "12h"]), pageSize: z.number().int().min(5).max(500) })
.partial()
.optional(),
});
settingsRouter.put("/", requireRole("admin"), asyncHandler(async (req, res) => {
+3 -1
View File
@@ -53,6 +53,8 @@ export type TimeFormat = "24h" | "12h";
export interface DisplaySettings {
dateFormat: DateFormat;
timeFormat: TimeFormat;
/** Rows per page for every paginated table in the app. */
pageSize: number;
}
export interface AppSettings {
@@ -82,7 +84,7 @@ const DEFAULTS: AppSettings = {
},
providerColors: {},
integrationColors: {},
display: { dateFormat: "ymd", timeFormat: "24h" },
display: { dateFormat: "ymd", timeFormat: "24h", pageSize: 20 },
};
const KEYS = Object.keys(DEFAULTS) as (keyof AppSettings)[];