feat(mangas): per-field sort options + direction toggle on the catalog (0.88.0)
Sort the manga catalog by created / updated / title / author with an independent asc/desc direction control. An omitted `order` defaults per field (dates newest-first, text A→Z), matching the UI, so a bare `?sort=<field>` means the same thing in the browser and over the API; `sort=recent` remains a back-compat alias for `created`. - Backend: SortField/SortOrder parsed with validation (structured 422 on bad input), per-field default_order, NULLS LAST only on the nullable author key, and migration 0033 indexing mangas(updated_at DESC, id) to back the default sort and its id tie-break. - Frontend: catalog sort field + direction (SegmentedControl) on desktop and a mobile bottom sheet; pure helpers in $lib/mangaSort; keyboard-accessible direction control; visible Direction labels and a sheet "Done" button. - Tests: backend integration coverage (defaults, alias, invalid input, ascending-id tie-break), frontend unit + e2e. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
16
backend/migrations/0033_mangas_updated_at_index.sql
Normal file
16
backend/migrations/0033_mangas_updated_at_index.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- Back the default catalog ordering. Since 0.88.0 the catalog list defaults to
|
||||
-- `ORDER BY updated_at DESC, id` (the no-filter default path), but the only
|
||||
-- existing updated_at index on mangas is the PARTIAL `mangas_missing_cover_idx`
|
||||
-- (WHERE cover_image_path IS NULL), which Postgres can't use for the unfiltered
|
||||
-- ordering. `created_at` and `lower(title)` already have full indexes from
|
||||
-- 0001; this gives the new default sort column the same treatment.
|
||||
--
|
||||
-- `id` is included as a trailing key so the index also covers the stable
|
||||
-- `, id` tie-break the listing appends for deterministic pagination.
|
||||
--
|
||||
-- Not CONCURRENTLY: sqlx::migrate! wraps each migration in a transaction, and
|
||||
-- CREATE INDEX CONCURRENTLY can't run inside one. The table is small at our
|
||||
-- scale, so a brief lock on an online deploy is acceptable.
|
||||
|
||||
CREATE INDEX IF NOT EXISTS mangas_updated_at_idx
|
||||
ON mangas (updated_at DESC, id);
|
||||
Reference in New Issue
Block a user