profile-stats: lifetime roll-up header on the profile

Implements the profile-stats change (specs/profile-stats):

- getActivityStats(ownerId, { publicOnly }) in activities.server.ts: one indexed
  aggregate over stored columns (count, sum distance/ascent/elapsed duration) +
  a rolling last-4-weeks count. No cache table, no schema change, no GPX parsing
  (design §D1).
- Profile loader computes it scoped to the viewer (public-only for visitors,
  full totals for the owner); ProfileStats header renders count · distance ·
  ascent · time + "N in the last 4 weeks" via the shared StatRow + stats.ts
  formatters; hidden when there are no visible activities.
- i18n journal.profileStats.* in en + de.

Tests: ProfileStats component (jsdom: totals, empty, last-4-weeks toggle);
e2e asserts the owner roll-up counts their activities. typecheck + lint + unit
(journal 318) green; verified in the browser.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ullrich Schäfer 2026-06-13 07:25:06 +02:00
parent 9845718dee
commit 3d3c56aaf4
No known key found for this signature in database
GPG key ID: A32FF691A0F752D9
10 changed files with 194 additions and 10 deletions

View file

@ -138,6 +138,14 @@ export default defineConfig({
baseURL: "http://localhost:3000",
},
},
{
name: "profile-stats",
testMatch: "profile-stats.test.ts",
use: {
...devices["Desktop Chrome"],
baseURL: "http://localhost:3000",
},
},
],
webServer: process.env.CI
? [