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
|
|
@ -3,6 +3,7 @@ import { eq, and, inArray } from "drizzle-orm";
|
|||
import { getDb } from "../db.ts";
|
||||
import { syncImports } from "@trails-cool/db/schema/journal";
|
||||
import { createActivity } from "../activities.server.ts";
|
||||
import type { SportType } from "@trails-cool/db/schema/journal";
|
||||
|
||||
export async function recordImport(
|
||||
userId: string,
|
||||
|
|
@ -59,6 +60,9 @@ export async function importActivity(
|
|||
distance?: number | null;
|
||||
duration?: number | null;
|
||||
startedAt?: Date | null;
|
||||
// Already normalized to our enum by the caller (see mapSportType);
|
||||
// undefined when the provider supplied no sport.
|
||||
sportType?: SportType;
|
||||
},
|
||||
): Promise<{ activityId: string }> {
|
||||
const activityId = await createActivity(userId, {
|
||||
|
|
@ -67,6 +71,7 @@ export async function importActivity(
|
|||
distance: input.distance,
|
||||
duration: input.duration,
|
||||
startedAt: input.startedAt,
|
||||
sportType: input.sportType,
|
||||
});
|
||||
await recordImport(userId, provider, externalWorkoutId, activityId);
|
||||
return { activityId };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue