feat(documents): paginate search with a Pagination control
Frontend side of the /documents pagination work. The page.server.ts load reads ?page= from the URL, forwards page+size=50 to the backend, and exposes the new totalElements/pageNumber/pageSize/totalPages fields on `data`. +page.svelte renders a <Pagination> component below the result list; buildPageHref preserves every filter param and only updates page. The existing triggerSearch debounce flow intentionally drops `page` when any filter changes, so filter edits reset to page 0 automatically. <Pagination> uses plain <a href> links (not goto) so SvelteKit's default scroll restoration scrolls new pages to the top — the expected senior-UX behaviour. Decorative chevrons wrapped in aria-hidden spans, 44px touch targets, focus-visible ring, stacks vertically under 640px. The control hides itself when totalPages ≤ 1. Test coverage: 9 cases on Pagination (label, aria-current, prev/next enable/disable, makeHref invocation, decorative chevron, touch target), plus a filter-reset assertion on +page.svelte (page 5 → edit q → goto URL must drop page=). Adds i18n keys in de/en/es. Manual edit to api.ts pending a post-merge npm run generate:api against a rebuilt dev backend. (#315) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,8 @@ type ValidSort = (typeof VALID_SORTS)[number];
|
||||
const VALID_DIRS = ['asc', 'desc'] as const;
|
||||
type ValidDir = (typeof VALID_DIRS)[number];
|
||||
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
export async function load({ url, fetch }) {
|
||||
const q = url.searchParams.get('q') || '';
|
||||
const from = url.searchParams.get('from') || '';
|
||||
@@ -27,6 +29,7 @@ export async function load({ url, fetch }) {
|
||||
: 'desc';
|
||||
const tagQ = url.searchParams.get('tagQ') || '';
|
||||
const tagOp = url.searchParams.get('tagOp') === 'OR' ? 'OR' : 'AND';
|
||||
const page = Math.max(0, Number(url.searchParams.get('page') ?? '0') || 0);
|
||||
|
||||
const api = createApiClient(fetch);
|
||||
|
||||
@@ -44,14 +47,19 @@ export async function load({ url, fetch }) {
|
||||
tagQ: tagQ && !tags.length ? tagQ : undefined,
|
||||
tagOp: tagOp === 'OR' ? 'OR' : undefined,
|
||||
sort,
|
||||
dir: dir || undefined
|
||||
dir: dir || undefined,
|
||||
page,
|
||||
size: PAGE_SIZE
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
return {
|
||||
items: [] as DocumentSearchItem[],
|
||||
total: 0,
|
||||
totalElements: 0,
|
||||
pageNumber: 0,
|
||||
pageSize: PAGE_SIZE,
|
||||
totalPages: 0,
|
||||
q,
|
||||
from,
|
||||
to,
|
||||
@@ -77,7 +85,10 @@ export async function load({ url, fetch }) {
|
||||
|
||||
return {
|
||||
items: (result.data?.items ?? []) as DocumentSearchItem[],
|
||||
total: result.data?.total ?? 0,
|
||||
totalElements: result.data?.totalElements ?? 0,
|
||||
pageNumber: result.data?.pageNumber ?? page,
|
||||
pageSize: result.data?.pageSize ?? PAGE_SIZE,
|
||||
totalPages: result.data?.totalPages ?? 0,
|
||||
q,
|
||||
from,
|
||||
to,
|
||||
|
||||
Reference in New Issue
Block a user