Files
reactbin/specs/018-pagination-controls/tasks.md
agatha 0ad82e60ac Feat: Replace pagination bar with numbered page buttons and chevron controls
Adds « ‹ [1][2][3][4] › » navigation to the library. Page window
slides to keep the current page in view. Prev/next/first/last controls
are always rendered but disabled at their respective bounds. Also wires
up karmaConfig in angular.json so FirefoxHeadless is used for tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 18:11:18 +00:00

126 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks: Pagination Controls Redesign
**Input**: Design documents from `specs/018-pagination-controls/`
**Branch**: `018-pagination-controls`
**Scope**: Two files change — `library.component.ts` (template, styles, class) and `library.component.spec.ts` (tests). No API, no data model, no new files.
---
## Phase 1: Setup
**Purpose**: Baseline verification before touching the component.
- [X] T001 Confirm existing library component tests pass by running `ng test --include=**/library.component.spec.ts --watch=false` in ui/
---
## Phase 2: Foundational
**Purpose**: No blocking infrastructure work required — all three user stories build directly on the existing `LibraryComponent`. Skipped.
---
## Phase 3: User Story 1 — Page Number Navigation (Priority: P1) 🎯 MVP
**Goal**: Replace the "Page X of Y" text with up to four clickable numbered page buttons. User can jump directly to any visible page.
**Independent Test**: With more than four pages of images, four numbered buttons appear; clicking a button loads that page and the button shows as active.
### Tests for User Story 1 (REQUIRED per §5.1)
- [X] T002 [US1] Write failing tests for `pageWindow` getter covering: first page (→ [1,2,3,4]), last page (→ last 4), middle page (current in window), total pages < 4 (all shown) in ui/src/app/library/library.component.spec.ts
### Implementation for User Story 1
- [X] T003 [US1] Add `get pageWindow(): number[]` getter to `LibraryComponent` using the sliding-window algorithm from plan.md in ui/src/app/library/library.component.ts
- [X] T004 [US1] Add `goToPage(page: number)` method to `LibraryComponent` (navigate via router queryParam, call `load()`) in ui/src/app/library/library.component.ts
- [X] T005 [US1] Replace the `<span class="page-indicator">Page {{ currentPage }} of {{ totalPages }}</span>` with `*ngFor` numbered page buttons; add `.page-btn` and `.page-btn.active` styles; verify T002 tests pass in ui/src/app/library/library.component.ts
**Checkpoint**: Four numbered page buttons visible; clicking one loads the correct page; active button is highlighted.
---
## Phase 4: User Story 2 — Previous/Next Chevrons (Priority: P2)
**Goal**: Replace text "← Previous" / "Next →" buttons with chevrons that are always rendered but visually disabled and non-interactive when at the first or last page.
**Independent Test**: On page 1 is disabled; on last page is disabled; clicking either on a valid page advances or retreats by one.
### Tests for User Story 2 (REQUIRED per §5.1)
- [X] T006 [US2] Write failing tests for disabled attribute and non-interactivity: disabled on page 1, disabled on last page, enabled otherwise in ui/src/app/library/library.component.spec.ts
### Implementation for User Story 2
- [X] T007 [US2] Replace the `*ngIf`-gated ← Previous / Next → buttons with always-rendered `<button [disabled]="currentPage === 1"></button>` and `<button [disabled]="currentPage === totalPages"></button>`; add `.pag-btn:disabled` style; verify T006 tests pass in ui/src/app/library/library.component.ts
**Checkpoint**: and always visible; disabled at bounds; single-page step works.
---
## Phase 5: User Story 3 — First/Last Jump Buttons (Priority: P3)
**Goal**: Add « and » buttons that jump directly to page 1 and the last page, disabled when already there.
**Independent Test**: From any middle page, « jumps to page 1 and » jumps to the last page; both are disabled when already at the respective bound.
### Tests for User Story 3 (REQUIRED per §5.1)
- [X] T008 [US3] Write failing tests for `firstPage()` and `lastPage()` methods and disabled states of « » at page boundaries in ui/src/app/library/library.component.spec.ts
### Implementation for User Story 3
- [X] T009 [US3] Add `firstPage()` and `lastPage()` methods to `LibraryComponent`; add `<button [disabled]="currentPage === 1">«</button>` and `<button [disabled]="currentPage === totalPages">»</button>` to each end of the pagination bar; verify T008 tests pass in ui/src/app/library/library.component.ts
**Checkpoint**: Full bar renders as [1][2][3][4] »`; all disabled states correct.
---
## Phase 6: Polish & Cross-Cutting Concerns
- [X] T010 Apply final styles: consistent button sizing, gap spacing, and mobile-friendly layout (flex-wrap or min-width as needed) for the full pagination bar in ui/src/app/library/library.component.ts
- [X] T011 Run ESLint and Prettier on ui/src/app/library/ and resolve any issues
---
## Dependencies & Execution Order
- **T001**: Run first — baseline gate
- **T002 → T003 → T004 → T005**: Sequential (tests before implementation; each method before its template usage)
- **T006 → T007**: Sequential (tests before implementation)
- **T008 → T009**: Sequential (tests before implementation)
- **T010, T011**: After all story phases complete; can run in either order
### User Story Dependencies
- **US1 (P1)**: Independent — starts after T001
- **US2 (P2)**: Starts after US1 is complete (shares same template section)
- **US3 (P3)**: Starts after US2 is complete (adds to the same template section)
All three stories touch the same two files, so parallel execution is not applicable here.
---
## Implementation Strategy
### MVP (User Story 1 only)
1. T001: Baseline check
2. T002T005: Numbered buttons + goToPage
3. **Validate**: Four page buttons work, active state correct
4. Defer US2 and US3 if shipping early
### Full Delivery
1. T001 baseline → US1 (T002T005) → US2 (T006T007) → US3 (T008T009) → Polish (T010T011)
2. Each story checkpoint validates independence before moving on
---
## Notes
- `pageWindow` algorithm: `start = max(1, currentPage-1); end = min(totalPages, start+3); start = max(1, end-3); pages = [start..end]`
- No `[P]` markers — all tasks share the same two files and must run sequentially
- Entire pagination bar hidden when `totalPages <= 1` (existing behaviour; do not regress)