v1.0.0:6 — paginate workout history (infinite scroll)
Two surfaces had invisible 50-row caps that this commit removes.
Exercise history popup (clock button in WorkoutForm):
- /api/exercises/[id] now accepts ?offset=N&limit=N (default 25,
max 100) and returns { exercise, history, hasMore }. Pagination
uses take: limit + 1 to detect hasMore without a second COUNT
round-trip.
- Query rewritten to use Prisma's setLogs.some filter — single SQL
that hits the (userId, deletedAt, date) composite index, instead
of fetching all set logs then grouping in JS.
- ExerciseHistoryPopup now uses an IntersectionObserver on a
sentinel div. When sentinel scrolls into view (root: the popup
itself, not the viewport), fetches next page and appends. Status
row at the bottom shows a spinner while loading and "End of
history" when done.
- Container max height bumped from h-64 -> h-80 for a bit more
breathing room on first render.
Workout history page (/main/workouts):
- Page still server-renders the first 50 workouts (instant paint
+ correct date filter forwarding). Now uses take: PAGE_SIZE + 1
to detect hasMore.
- New WorkoutsList client component takes initial workouts +
hasMore + filter values as props. IntersectionObserver on a
sentinel below the cards auto-fetches the next page from
/api/workouts?offset=N&limit=50&q=...&dateFrom=...&dateTo=...
when scrolled to. Filters round-trip through URL params, so a
filter change re-renders the page from scratch with a fresh
first page.
- "End of history · N workouts" line shown once everything is
loaded.
Tests:
- tests/routes-exercise-history.test.ts: 6 new tests covering
auth, cross-user 404, first-page hasMore=true, second-page
hasMore=false + no overlap, set-log filter scoped to the
queried exerciseId, soft-deleted workouts excluded.
- All 87 tests pass.
No schema changes, no migration. /data untouched.
This commit is contained in:
@@ -4,23 +4,22 @@ import { v_1_0_0_2 } from './v1.0.0.2'
|
||||
import { v_1_0_0_3 } from './v1.0.0.3'
|
||||
import { v_1_0_0_4 } from './v1.0.0.4'
|
||||
import { v_1_0_0_5 } from './v1.0.0.5'
|
||||
import { v_1_0_0_6 } from './v1.0.0.6'
|
||||
|
||||
/**
|
||||
* Version graph for the `proof-of-work` package.
|
||||
*
|
||||
* v1.0.0:1 — initial release, seeded cutover from the legacy
|
||||
* `workout-log` package.
|
||||
* v1.0.0:1 — initial release, seeded cutover from `workout-log`.
|
||||
* v1.0.0:2 — CSP fix.
|
||||
* v1.0.0:3 — post-cutover seed strip.
|
||||
* v1.0.0:4 — removes the default admin@local credentials; operator
|
||||
* must run the StartOS Action to bootstrap the first admin.
|
||||
* v1.0.0:5 — internal cleanup (removes caloriesBurned raw-SQL
|
||||
* workaround). No user-facing change.
|
||||
*
|
||||
* StartOS picks `current` as the install target; `other` lists every
|
||||
* node that can upgrade into `current`.
|
||||
* v1.0.0:4 — removes default admin@local credentials; operator must
|
||||
* run StartOS Action to bootstrap the first admin.
|
||||
* v1.0.0:5 — internal cleanup (caloriesBurned raw-SQL workaround).
|
||||
* v1.0.0:6 — paginate workout history (infinite scroll); removes
|
||||
* invisible 50-row caps on the clock-button popup and
|
||||
* the /main/workouts page.
|
||||
*/
|
||||
export const versionGraph = VersionGraph.of({
|
||||
current: v_1_0_0_5,
|
||||
other: [v_1_0_0_1, v_1_0_0_2, v_1_0_0_3, v_1_0_0_4],
|
||||
current: v_1_0_0_6,
|
||||
other: [v_1_0_0_1, v_1_0_0_2, v_1_0_0_3, v_1_0_0_4, v_1_0_0_5],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user