feat(cycles): add menstrual cycle tracking module

New unified-app module under apps/mana/apps/web/src/lib/modules/cycles.
Adds three Dexie tables (cycles, cycleDayLogs, cycleSymptoms) in db v7,
SYNC_APP_MAP entry, app-registry registration, branding (icon + entry +
APP_URLS), and a /cycles route.

Includes phase derivation (menstruation/follicular/ovulation/luteal),
heuristic next-period and fertile-window prediction (rolling mean over
last 6 cycles), 10 default symptoms, and 33 unit tests covering the
pure utilities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-07 14:35:33 +02:00
parent 575c5c36fd
commit fbab96c74b
17 changed files with 1780 additions and 0 deletions

View file

@ -136,6 +136,9 @@ export const APP_ICONS = {
dreams: svgToDataUrl(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><linearGradient id="dr" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#6366f1"/><stop offset="100%" style="stop-color:#312e81"/></linearGradient></defs><rect width="100" height="100" rx="22" fill="url(#dr)"/><path d="M62 30a22 22 0 1 0 18 34 18 18 0 0 1-18-34z" fill="white"/><circle cx="32" cy="38" r="1.6" fill="white"/><circle cx="26" cy="58" r="1.2" fill="white" fill-opacity="0.8"/><circle cx="40" cy="68" r="1.4" fill="white" fill-opacity="0.7"/><circle cx="22" cy="46" r="1" fill="white" fill-opacity="0.6"/></svg>`
),
cycles: svgToDataUrl(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><linearGradient id="cy" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#ec4899"/><stop offset="100%" style="stop-color:#be185d"/></linearGradient></defs><rect width="100" height="100" rx="22" fill="url(#cy)"/><circle cx="50" cy="50" r="26" stroke="white" stroke-width="4" fill="none"/><path d="M50 24a26 26 0 0 1 22 40" stroke="white" stroke-width="4" stroke-linecap="round" fill="none"/><circle cx="72" cy="64" r="3.5" fill="white"/><circle cx="50" cy="50" r="9" fill="white"/></svg>`
),
finance: svgToDataUrl(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><linearGradient id="fn" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#22c55e"/><stop offset="100%" style="stop-color:#16a34a"/></linearGradient></defs><rect width="100" height="100" rx="22" fill="url(#fn)"/><circle cx="50" cy="50" r="22" stroke="white" stroke-width="4" fill="none"/><path d="M50 34v32M42 42c0-4 3.5-6 8-6s8 2 8 6-3.5 5-8 5-8 2-8 6 3.5 6 8 6 8-2 8-6" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/></svg>`
),

View file

@ -632,6 +632,23 @@ export const MANA_APPS: ManaApp[] = [
status: 'development',
requiredTier: 'founder',
},
{
id: 'cycles',
name: 'Cycles',
description: {
de: 'Menstruationszyklus-Tracking',
en: 'Menstrual Cycle Tracking',
},
longDescription: {
de: 'Tracke deinen Zyklus mit Blutungstagen, Symptomen, Stimmung und Basaltemperatur. Phasen-Erkennung und Vorhersage für die nächste Periode und das fruchtbare Fenster.',
en: 'Track your cycle with flow days, symptoms, mood, and basal temperature. Phase detection and prediction of the next period and fertile window.',
},
icon: APP_ICONS.cycles,
color: '#ec4899',
comingSoon: false,
status: 'development',
requiredTier: 'founder',
},
{
id: 'events',
name: 'Events',
@ -812,6 +829,7 @@ export const APP_URLS: Record<AppIconId, { dev: string; prod: string }> = {
habits: { dev: 'http://localhost:5173/habits', prod: 'https://mana.how/habits' },
notes: { dev: 'http://localhost:5173/notes', prod: 'https://mana.how/notes' },
dreams: { dev: 'http://localhost:5173/dreams', prod: 'https://mana.how/dreams' },
cycles: { dev: 'http://localhost:5173/cycles', prod: 'https://mana.how/cycles' },
events: { dev: 'http://localhost:5173/events', prod: 'https://mana.how/events' },
finance: { dev: 'http://localhost:5173/finance', prod: 'https://mana.how/finance' },
places: { dev: 'http://localhost:5173/places', prod: 'https://mana.how/places' },