5 Commits

Author SHA1 Message Date
09df5d25b8 Scaffold the mobile member app: PWA shell, push, and app-shell tokens
New `mobile` Django app mounted at /app/ -- the installed PWA for Member
mode (M1-M7, see design_handoff_rosterchief_platform/README.md). Coach
mode (C1-C6) is a later phase and has no routes yet.

Foundation pieces:
- assets/mobile.css: Tailwind v4 theme reusing management.css's design
  tokens (same per-club --tenant-* theming pattern), plus the ice/coach
  accent and mobile's 14px card radius.
- PushSubscription model + pywebpush-based sender (mobile/services/push.py),
  wired to notifications.Notification via a post_save signal so the
  existing notification system gains a push channel without knowing about
  PWAs itself.
- Per-club manifest.webmanifest + service worker (served at /app/sw.js)
  + a server-rendered fallback home-screen icon (club initials on
  secondary_color) for clubs without an uploaded logo -- confirmed with
  the user as the fallback, never a generic RosterChief mark.
- App shell (base.html): navy header, person switcher (every child a
  signed-in parent manages, plus "Me"), bottom tab bar, safe-area insets.
  Vendored htmx + Alpine for the screens built on top of it.
- Placeholder views/routes for all seven M1-M7 screens so the shell is
  fully wired end-to-end before each screen is built out individually.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
2026-08-21 10:27:13 +02:00
adf1120358 Checkpoint: management app redesign, onboarding/signup workflow, and events calendar backend
Large uncommitted body of work accumulated across sessions on this branch --
committing as a checkpoint so it's tracked and future worktree-isolated agents
see the real codebase instead of a stale ancestor commit. Covers the
management app's dedicated Tailwind theme and templates, the club onboarding
requirement/signup workflow (club/services/onboarding.py, requirement/status
models, sign-up dashboard), fee/status auto-activation decoupling, referee
management, and the new events calendar grid service layer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
2026-08-19 23:34:43 +02:00
016206a79e Build the platform metrics dashboard
The dashboard leads with the numbers that are supposed to be zero, because a
dashboard of healthy counts is one nobody opens:

- Clubs with no season covering today. Seasons scope memberships, rosters and
  events, so such a club cannot take a signup or schedule a match -- and it fails
  silently, nothing errors, it is just inert.
- Dormant clubs: nothing on the calendar for 30 days. Churn signal.
- Admins pending MFA. RequireMFAMiddleware redirects them to enrolment, so they
  are locked out of their own club until they act: a support queue, not a stat.
- Outstanding money across every club.

Then the shape of the business: an onboarding funnel (clubs → with members → with
a team → with events, which separates working clubs from shells), feature-flag
adoption per club, and two charts -- signups and revenue per month.

Charts use chart.js, self-hosted rather than pulled from a CDN, for the same
reason as the fonts: no third-party in the render path. Two things the browser
taught me: the canvas needs a height-bounded wrapper (with maintainAspectRatio
off it sizes to its parent, and a parent with no height grew it to 3489px), and
chart.js cannot read daisyUI's CSS variables, so the charts re-render on a
data-theme change or keep the light palette in dark mode.

The month series is zero-filled: a chart that skips empty months draws a smooth
line straight over a month in which nothing happened.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 00:59:28 +02:00
fc51e1903c Self-host Ubuntu, JetBrains Mono, Roboto and Tourney
Ubuntu becomes the default sans and JetBrains Mono the default mono (via
--font-sans / --font-mono, which Tailwind wires to the body and <code>
defaults). Roboto and Tourney are opt-in utilities: `font-roboto`, and
`font-tourney` for display numerals like jersey numbers.

Self-hosted rather than linked from Google's CDN: a CDN <link> sends every
visitor's IP to a third party on each page load, which is an avoidable GDPR
liability for an EU club platform, and it puts someone else's uptime in our
render path. Files come from the @fontsource packages.

Two subsets each, with unicode-range: plain `latin` cannot render the Polish,
Czech or Turkish letters that turn up in member names, and the range means
latin-ext is only fetched by pages that actually contain those glyphs.

Tourney is variable on two axes, so font-stretch is declared as a range next to
the weight range -- declare only the weight and the browser clamps the width
axis to its default, making `font-stretch: 125%` (a wide shirt number) silently
do nothing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 22:30:02 +02:00
848a8578de build(ui): add Tailwind v4 + daisyUI 5 pipeline
daisyUI is an npm plugin, so the standalone Tailwind CLI can't load it; this
adds a real build. Themes are configured as `light --default, dark
--prefersdark`, so dark follows the OS with no JavaScript, and an explicit
data-theme (set by the toggle) overrides it.

The built CSS is committed, so `uv run manage.py runserver` remains all a
Python dev needs; `npm run watch` is only for those touching styles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 15:29:10 +02:00