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
|
|
@ -11,6 +11,7 @@ const ACTIVITY: FederatableActivity = {
|
|||
id: "act-1",
|
||||
name: "Morning ride <3",
|
||||
description: 'Through the "forest" & hills',
|
||||
sportType: "ride",
|
||||
distance: 42_195,
|
||||
elevationGain: 512.4,
|
||||
duration: 2 * 3600 + 30 * 60,
|
||||
|
|
@ -50,6 +51,14 @@ describe("activityToNote", () => {
|
|||
expect(byName.get("distance-m")).toBe("42195");
|
||||
expect(byName.get("elevation-gain-m")).toBe("512");
|
||||
expect(byName.get("duration-s")).toBe("9000");
|
||||
expect(byName.get("sport")).toBe("ride");
|
||||
});
|
||||
|
||||
it("omits the sport attachment when sport is unset", async () => {
|
||||
const note = activityToNote({ ...ACTIVITY, sportType: null }, "bruno");
|
||||
const names = [];
|
||||
for await (const a of note.getAttachments()) names.push(String((a as { name: unknown }).name));
|
||||
expect(names).not.toContain("sport");
|
||||
});
|
||||
|
||||
it("omits stats it doesn't have", () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue