activity-sport-type: schema, contract, write/read paths, federation
Implements the activity-sport-type change (specs/activity-sport-type): - db: nullable `sport_type` column on journal.activities + SportType / SPORT_TYPES (text().$type<> convention). - api: optional sportType on the activity read + create schemas (mirrored SPORT_TYPES; @trails-cool/api stays zod-only). - write: ActivityInput + createActivity persist it; mapSportType() normalizes provider strings (Komoot bulk import passes tour.sport; Garmin unset); threaded through the unified importActivity. - read/display: sportType added to the detail/feed/profile loaders and the v1 REST endpoints; shared SportBadge (glyph + i18n label) on detail, feed, and profile; sport-aware feed verb; create-form <select>. - i18n: journal.activities.sport.* (labels + verbs) in en + de. - federation: `sport` PropertyValue on the Note when set. Tests: mapSportType unit table; federation asserts the sport attachment is present when set and omitted when unset. typecheck + lint + unit all green. E2E (create→badge) still to add. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ee76945f20
commit
2cb32cd2d3
25 changed files with 328 additions and 18 deletions
|
|
@ -1,30 +1,30 @@
|
|||
## 1. Data & contract
|
||||
|
||||
- [ ] 1.1 Add `SportType` union + `SPORT_TYPES` const to `@trails-cool/db`; add nullable `sportType: text("sport_type").$type<SportType>()` to `journal.activities`.
|
||||
- [ ] 1.2 `pnpm db:push` against the local DB (additive nullable column, no data migration).
|
||||
- [ ] 1.3 Add optional `sportType` to the activity read + create Zod schemas in `packages/api/src/activities.ts`.
|
||||
- [x] 1.1 Add `SportType` union + `SPORT_TYPES` const to `@trails-cool/db`; add nullable `sportType: text("sport_type").$type<SportType>()` to `journal.activities`.
|
||||
- [x] 1.2 Apply the additive nullable column to local DBs. (`pnpm db:push` is blocked by an unrelated pre-existing `remote_origin_iri` unique-constraint prompt; applied via a non-destructive `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` to dev + e2e. CI applies schema to a fresh DB.)
|
||||
- [x] 1.3 Add optional `sportType` to the activity read + create Zod schemas in `packages/api/src/activities.ts` (mirrored `SPORT_TYPES`; api is zod-only/standalone).
|
||||
|
||||
## 2. Write path
|
||||
|
||||
- [ ] 2.1 Add `sportType?: SportType` to `ActivityInput` and persist it in `createActivity` (`apps/journal/app/lib/activities.server.ts`).
|
||||
- [ ] 2.2 Add `mapSportType(raw: string): SportType` helper with the normalization table; unit-test it.
|
||||
- [ ] 2.3 Thread `sportType` through the unified `importActivity` input; pass `mapSportType(tour.sport)` from the Komoot bulk import; leave Garmin unset.
|
||||
- [ ] 2.4 Parse the `sportType` form field in `activitiesNewAction` and add the `<select>` to `activities.new.tsx` (optional, i18n labels).
|
||||
- [x] 2.1 Add `sportType?: SportType` to `ActivityInput` and persist it in `createActivity` (`apps/journal/app/lib/activities.server.ts`).
|
||||
- [x] 2.2 Add `mapSportType(raw)` helper with the normalization table; unit-test it (`sport-type.ts` + `sport-type.test.ts`).
|
||||
- [x] 2.3 Thread `sportType` through the unified `importActivity` input; pass `mapSportType(tour.sport)` from the Komoot bulk import; leave Garmin unset.
|
||||
- [x] 2.4 Parse the `sportType` form field in `activitiesNewAction` and add the `<select>` to `activities.new.tsx` (optional, i18n labels).
|
||||
|
||||
## 3. Read path & display
|
||||
|
||||
- [ ] 3.1 Add `sportType` to the detail, feed, and profile loaders' activity projections.
|
||||
- [ ] 3.2 Build a shared `SportBadge` (inline-SVG icon + i18n label); render it on the detail page, feed cards, and profile list.
|
||||
- [ ] 3.3 Derive the feed verb from the sport (generic fallback when unset).
|
||||
- [ ] 3.4 Add `journal.activities.sport.*` keys (label, per-sport names, per-sport verbs) to en + de.
|
||||
- [x] 3.1 Add `sportType` to the detail, feed, and profile loaders' activity projections (+ the v1 REST endpoints).
|
||||
- [x] 3.2 Build a shared `SportBadge` (emoji glyph + i18n label); render it on the detail page, feed cards, and profile list.
|
||||
- [x] 3.3 Derive the feed verb from the sport (generic fallback when unset).
|
||||
- [x] 3.4 Add `journal.activities.sport.*` keys (label, per-sport names, per-sport verbs) to en + de.
|
||||
|
||||
## 4. Federation
|
||||
|
||||
- [ ] 4.1 Append a `sport` PropertyValue attachment in `activityToNote()` when set; extend the federation-outbox test to assert it.
|
||||
- [x] 4.1 Append a `sport` PropertyValue attachment in `activityToNote()` when set; extend the federation-objects test to assert it (and that it's omitted when unset).
|
||||
|
||||
## 5. Tests & checks
|
||||
|
||||
- [ ] 5.1 Unit: `mapSportType` table (known sports, unknown → `other`, empty → `other`).
|
||||
- [ ] 5.2 Unit/integration: create→detail round-trip persists and returns `sportType`.
|
||||
- [x] 5.1 Unit: `mapSportType` table (known sports, unknown → `other`, empty → undefined).
|
||||
- [ ] 5.2 Round-trip (create→detail persists `sportType`) — folded into the E2E below.
|
||||
- [ ] 5.3 E2E: create an activity with a sport, assert the badge renders on the detail page.
|
||||
- [ ] 5.4 `pnpm typecheck && pnpm lint && pnpm test && pnpm test:e2e` green.
|
||||
- [ ] 5.4 `pnpm typecheck && pnpm lint && pnpm test && pnpm test:e2e` green. (typecheck/lint/unit green; e2e pending.)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue