diff --git a/README.md b/README.md index 8a66d43..fcd429b 100644 --- a/README.md +++ b/README.md @@ -1,135 +1,85 @@ # REKORD -**Rekord & Record: dein Training, festgehalten.** +Selbstgehosteter Trainings-Tracker für Gym, Laufen und Radfahren. Läuft im +Browser, speichert auf deinem Server, gehört dir. -Ein leichtgewichtiger, selbst gehosteter Trainings-Tracker fürs Gym, Laufen -und Radfahren. Läuft in jedem modernen Browser, speichert auf deiner Platte -und wertet deine Fitnessdaten nicht aus. Kein Abo, kein Konto bei einem -Anbieter, keine Datenkraken. +Eine SQLite-Datei als Zustand, ein Python-Backend aus der Standardbibliothek, +ein HTML/CSS/JS-Frontend ohne Framework. Kein Cloud-Konto, keine Telemetrie. -## Warum REKORD? - -- **Kein Vendor Lock-in.** Alles läuft bei dir: Backend auf deinem Server, - Zustand in einer portablen SQLite-Datei. Export jederzeit als JSON oder - CSV, Import genauso. Zieh um oder hör auf - deine Daten gehören dir. -- **Leichtgewichtig.** Python-Standardbibliothek + SQLite im Backend, ein - HTML-, ein CSS-, ein JS-File im Frontend. Kein Framework, kein - Build-Schritt, keine Node-Installation. Läuft auf einem Mini-PC, einem - alten Laptop oder in einem Container. -- **Browserbasiert.** Keine App, kein Store, keine Installation. Aufschlagen, - loslegen - auf jedem Gerät mit Browser. -- **Cross-Device Sync.** Der Zustand liegt serverseitig. Öffne die App am - Handy, am Laptop oder am Desktop-Rechner - es ist derselbe Stand. Mehrere - Benutzer mit eigenen Konten und getrennten Daten sind eingebaut. -- **UX zuerst.** Sätze eintragen mit einer Box (Zahl + Einheit in einem - Feld), Set-Kette durch Abhaken, "Alles zurücksetzen", Verlauf inline - bearbeiten, Wochenübersicht, Statistik mit Differenz zur ersten Messung. - Der Tracker reibt sich nicht in den Weg zwischen dich und die Übung. -- **Dein Take aufs Aufzeichnen.** Die App zeichnet auf - Gewichte, Reps, - Cardio-Felder - und zeigt die Entwicklung über die Zeit. Sie verkauft - nichts, personalisiert nichts und schickt nichts nach Hause. -- **Open Source.** AGPL-3.0. Nachvollziehbar, erweiterbar, auditierbar. - -## Features im Überblick +## Was es kann **Training erfassen** -- Gym mit Push/Pull/Legs (frei konfigurierbar) plus Laufen und Radfahren +- Gym mit Push/Pull/Legs (frei konfigurierbar), dazu Laufen und Radfahren - Eingabe als eine Box: Zahl links, Einheit fest rechts (kg, reps, km, min, min/km, bpm, m) -- Set-Abhaken als "Set n [ ]": der ganze Button ist klickbar, das Set hakt - eine Kette ab - ohne Lücken -- Reset-Satz und "Alles zurücksetzen" laden das letzte abgeschlossene - Training -- Vorbefüllung beim Start (optional): "Letztes Training vorbefüllen" oder - "Plan-Gewichte vorbefüllen" (startKg aus der Config, auch ohne Verlauf) +- Sätze abhaken als "Set n [ ]"; der ganze Button ist klickbar, die Kette + hakt ohne Lücken ab +- "Reset-Satz" und "Alles zurücksetzen" holen das letzte abgeschlossene + Training; optional startet eine Session direkt mit dem letzten Workout + oder mit den Plan-Gewichten - Übungen per Drag & Drop sortieren, Übungen aus anderen Tagen spontan hinzufügen -- Fragezeichen pro Übung: Erklärung plus die passende Maschine +- Fragezeichen pro Übung: kurze Erklärung (herstellerunabhängig) -**Sessions & Verlauf** +**Verlauf & Statistik** - "Session starten" / "Session abschließen", mehrere Sessions am Tag -- Keine Geister: erst abgeschlossene Sessions erscheinen im Verlauf -- Verlauf als Liste oder Wochenübersicht, inline bearbeitbar (Datum, Zeiten, - Abhak-Status, Werte) und löschbar -- Statistik: bestes Gewicht je Trainingstag mit Balken, Differenz zur ersten - Messung +- Verlauf als Liste oder Wochenübersicht; inline bearbeitbar und löschbar +- Statistik: bestes Gewicht je Trainingstag, Differenz zur ersten Messung **Ansicht & Einstellungen** -- Deutsch und Englisch (Server-Standard und pro Benutzer) -- Farbthema: Dunkel, System (folgt dem Gerät), Hell - plus OLED-Dark-Schalter -- Akzentfarbe aus zehn Farben (inklusive Weiß) -- Gewichtseinheit kg oder lb, Start-Ansicht wählbar -- Einstellungen serverseitig, gelten auf allen Geräten +- Deutsch und Englisch +- Themes: Dunkel, System, Hell - plus OLED-Dark-Schalter +- Akzentfarbe aus zehn Farben, Gewichtseinheit kg/lb, Start-Ansicht wählbar +- Einstellungen liegen serverseitig, gelten auf allen Geräten **Mehrbenutzer** -- Eigene Konten mit Kennwort (gehasht), Daten strikt getrennt +- Konten mit Kennwort (gehasht), Daten getrennt pro Benutzer - Der erste Benutzer ist Administrator und verwaltet Konten und Kennwörter -- Einmaliger Einrichtungs-Wizard beim ersten Start (Sprache, Modus, - Darstellung) **Daten** - Export/Import als JSON und CSV (Backup, Umzug, Tabellen-Auswertung) -- Workouts über eine kleine API abrufbar (`/api/workouts`) -- Demo-Daten (`demo-data.json`) zum direkten Ausprobieren +- Workouts über eine kleine API (`/api/workouts`) +- Demo-Verlauf (`demo-data.json`) zum Ausprobieren -## Schnellstart +## Starten -Python (nur Standardbibliothek, kein `pip install`): +Python (nur Standardbibliothek): ```bash python3 server.py 8080 ``` -Oder mit Docker: +Oder Docker: ```bash docker compose up -d ``` -Danach im Browser: `http://:8080/` +Danach im Browser: `http://:8080/`. Beim ersten Start führt ein kurzer +Wizard durch Sprache, Einzel- oder Mehrbenutzermodus und Darstellung. -Beim ersten Start führt dich ein kurzer Wizard durch Sprache, Einzel- oder -Mehrbenutzermodus und Darstellung - danach ist die App einsatzbereit. +## Plan anpassen -## Den Übungsplan anpassen +Übungen, Sätze, Gewichte und Erklärungen stehen in `config.json` - ohne +Code-Eingriff. Schema: [TECH.md](TECH.md). -Alle Übungen, Sätze, Gewichte, Maschinen und Erklärungen stehen in -`config.json` - ohne Code-Eingriff. Das komplette Schema steht in der -[technischen Dokumentation](TECH.md). - -## Automatischer Build (CI/CD) - -Ein Push auf `main` baut automatisch ein Docker-Image und legt es in der -Gitea-Registry ab (`git.somantis.net/j4stmarkus/trainingsplan`). Dafür läuft -ein Gitea-Actions-Runner auf dem Server; die Workflow-Datei liegt unter -`.gitea/workflows/build-image.yml`. Die CasaOS-Installation -(`docker-compose.casaos.yml`) bezieht die App aus diesem Registry-Image. -Fürs lokale Entwickeln bleibt `docker-compose.yml` mit `build: .` bestehen. - -## Daten & Privatsphäre +## Daten - Alles liegt in `data/state.db` (SQLite) - backupbar, überlebt Neustart und Container-Rebuild -- Datenverzeichnis frei wählbar (`TRAINING_STATE_DIR`) -- Keine externen Dienste, keine Telemetrie, keine Analyse deiner Daten +- Datenverzeichnis per `TRAINING_STATE_DIR` frei wählbar +- Keine externen Dienste, keine Telemetrie -## Roadmap +## Mehr -Die geplante Weiterentwicklung (Übungskatalog in der App bearbeiten, -herstellerunabhängige Info-Texte mit Bildern/Schritten, Plugin-System mit -Ollama/Cloud-Coach, Wearable-Import, CLI-Harness) steht in -[ROADMAP.md](ROADMAP.md). - -## Design - -Die verbindliche Design-Sprache (Tokens, Komponenten, Zustaende, Anti- -Patterns) steht in [DESIGN.md](DESIGN.md) - wiederverwendbar für weitere -Projekte. +- [TECH.md](TECH.md) - Architektur, API, Datenmodell +- [DESIGN.md](DESIGN.md) - Design-Sprache (Tokens, Komponenten, Anti-Patterns) +- [ROADMAP.md](ROADMAP.md) - geplante Erweiterungen ## Lizenz diff --git a/ROADMAP.md b/ROADMAP.md index 83bc1da..2b6172c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,63 +1,62 @@ # REKORD - Roadmap -Interne Roadmap. Prioritaeten: P1 = naechste Iterationen, P2 = bald, P3 = -spaeter. Status: Idee / Geplant / In Arbeit / Fertig. +Was geplant ist, und was schon steht. Priorität: P1 = als Nächstes, P2 = bald, +P3 = später. Status: Fertig / Teilweise / Geplant. -Zielrichtung: breiteres Feature-Set, einfachere Erweiterung des -Uebungs-/Maschinen-Katalogs, herstellerunabhaengige Inhalte, sanfte -Integration (Plugins, lokale Modelle) statt Monolithen. Architektur-Leitplanken -bleiben: Config-getrieben, leichtgewichtig, Daten lokal, keine Telemetrie. +Leitplanken bleiben: config-getrieben, leichtgewichtig, Daten lokal, keine +Telemetrie. ---- +## Umgesetzt -## Phase 1 - Inhalte & Bedienbarkeit +- Config-getriebener Plan (`config.json`), SQLite-Zustand serverseitig +- Gym (Push/Pull/Legs), Laufen, Radfahren; Cardio-Felder aus der Config +- Set-Kette, Reset-Satz, "Alles zurücksetzen", Vorbefüllung (letztes Workout + oder Plan-Gewichte) +- Übungen per Drag & Drop sortieren, Übungen aus anderen Tagen hinzufügen +- Verlauf als Liste und Wochenübersicht, Inline-Bearbeitung, Löschen +- Statistik: bestes Gewicht je Tag, Differenz zur ersten Messung +- Mehrbenutzer mit Admin, Kennwort ändern/zurücksetzen, Server-Reset +- Einrichtungs-Wizard (Sprache, Darstellung, Modus) +- i18n de/en, Themes dunkel/system/hell + OLED, zehn Akzentfarben +- Export/Import JSON/CSV, Workouts-API, Demo-Daten +- Übungs-Infos herstellerunabhängig; mobile-taugliche Satz-Zeile -| Prioritaet | Thema | Status | Notiz | +## Offen + +### Inhalte & Bedienbarkeit + +| Prio | Thema | Status | Notiz | |---|---|---|---| -| P1 | **Uebungen/Maschinen in der App bearbeiten** | Idee | Heute aendert man `config.json` von Hand. Ziel: Uebungen, Tage, Maschinen und Info-Texte direkt in der App anlegen/bearbeiten (persistiert neben der Config), damit ein Nicht-Programmierer den Plan ohne Dateieditor pflegt. | -| P1 | **Info-Texte erweitern** | Idee | Neben dem Freitext: optionale Bilder (URL oder Upload), Schritte als Checkliste, ein "wertvoller Link" (z.B. zu einer neutralen Anatomie-/Form-Quelle). Wichtig: **nicht hersteller-spezifisch** - die Technogym-Referenzen aus der Config sind nur Platzhalter; der Katalog soll generisch sein. | -| P1 | **Uebungsvarianten & Maschinen-Tags** | Idee | Eine Uebung mit mehreren Varianten (KH, Maschine, Kabel) und deren Verfuegbarkeit; beim Training schnell zwischen den Geräten wechseln, die im Studio stehen. | -| P1 | **Set-Vorlagen pro Uebung** | Idee | Im Plan definierte Satz-Vorlagen (Anzahl, Ziel-Reps, Pause) als Startpunkt - schon teilweise da ("Plan-Gewichte vorbefuellen"), aber noch nicht pro Satz steuerbar. | -| P2 | **Gewichtseinheiten pro Uebung** | Idee | z.B. Bodyweight (kein kg), Bandwiderstand, Maschinen-Gewicht inkl. Hebel - neben dem globalen kg/lb. | +| P1 | Übungen/Maschinen in der App bearbeiten | Geplant | Statt `config.json` von Hand: Übungen, Tage und Info-Texte direkt in der App pflegen. | +| P1 | Info-Texte erweitern | Geplant | Optional Bilder, Schritte als Checkliste, ein Link (neutral, nicht herstellerspezifisch). | +| P1 | Übungsvarianten & Maschinen-Tags | Geplant | Eine Übung mit Varianten (KH, Maschine, Kabel) und schnellem Wechsel im Training. | +| P2 | Set-Vorlagen pro Übung | Teilweise | Plan-Gewichte vorbefüllen gibt es; noch nicht pro Satz steuerbar (Ziel-Reps, Pause). | +| P2 | Einheiten pro Übung | Geplant | Bodyweight, Band, Maschinen-Gewicht - neben dem globalen kg/lb. | -## Phase 2 - Integration & Automation +### Integration -| Prioritaet | Thema | Status | Notiz | +| Prio | Thema | Status | Notiz | |---|---|---|---| -| P1 | **Plugin-System** | Idee | Kleine Plugins (JS im Browser und/oder Server-Skripte) mit klaren Hooks: nach Session-Speichern, beim Export, beim Anzeigen einer Uebung, beim Abschluss. Registrierung in der Config. So bleiben Erweiterungen ausserhalb des Kerns. | -| P1 | **Ollama/Cloud-Coach** | Idee | Plugin, das Form-Tipps/Zusammenfassungen per API generiert - **local-first** (Ollama), Cloud nur mit expliziter Zustimmung und eigener Wahl des Anbieters/Keys. Keine Daten gehen ohne Erlaubnis nach aussen. | -| P2 | **Webhooks bei Events** | Idee | Nach "Session abgeschlossen", "Benutzer angelegt" etc. - fuer eigene Automation (Backup, Benachrichtigungen, Hausautomation). | -| P2 | **API-Keys pro Benutzer** | Idee | Neben den Login-Tokens: eigene read/write Keys pro Benutzer fuer Scripts, ohne das Konto freizugeben. | -| P2 | **Effizienter Harness (CLI)** | Idee | Kleines Kommandozeilen-/Script-Interface (`rekord`-CLI oder Python-Client) gegen die API: Workouts eintragen/abrufen, Statistiken ziehen - fuer Cron-Jobs, TUI, Automation. | -| P3 | **Wearable-Import** | Idee | Garmin/Apple/Fitbit/Samsung-Health-Exporte (CSV/JSON) als Plugin importieren; Puls etc. an Cardio-Sessions anhaengen. Kein Live-Sync in Phase 1. | +| P1 | Plugin-System | Geplant | Kleine Plugins mit Hooks (nach Session-Speichern, beim Export, beim Anzeigen). | +| P1 | Ollama/Cloud-Coach | Geplant | Form-Tipps/Zusammenfassungen per API - local-first (Ollama), Cloud nur auf Wunsch. | +| P2 | Webhooks bei Events | Geplant | Nach "Session abgeschlossen" o.ä. für eigene Automation. | +| P2 | API-Keys pro Benutzer | Geplant | Read/write Keys für Scripts, ohne das Konto freizugeben. | +| P2 | CLI-Harness | Geplant | Kleines Kommandozeilen-Interface gegen die API (Cron, TUI). | +| P3 | Wearable-Import | Geplant | Garmin/Apple/Fitbit/Samsung-Exporte (CSV/JSON) als Plugin. | -## Phase 3 - Analyse & UX +### Analyse & UX -| Prioritaet | Thema | Status | Notiz | +| Prio | Thema | Status | Notiz | |---|---|---|---| -| P1 | **Volumen & 1RM-Schaetzung** | Idee | Trainingsvolumen (kg × Reps) je Uebung/Tag, 1RM-Schaetzung (z.B. Epley) als zusaetzliche Statistik-Kennzahl. | -| P2 | **Wochenvergleich & Trends** | Idee | Statistik ueber Wochen hinweg (nicht nur "Differenz zur ersten Messung"): gleitende Durchschnitte, PR-Markierungen, Verlaufs-Graph (ohne externe Chart-Lib, wenn moeglich). | -| P2 | **PWA / Offline** | Idee | Als installierbare App (Service Worker, App-Icon) - nicht kritisch, da serverseitig, aber schoener auf dem Handy. | -| P2 | **Sessions am selben Tag bessern** | Idee | Mehrere Sessions pro Tag sind drin; UX fuer "morgens laufen, abends Gym" vereinfachen (schneller Aktivitaets-/Tag-Wechsel). | +| P1 | Volumen & 1RM-Schätzung | Geplant | kg × Reps je Übung/Tag, 1RM-Schätzung als zusätzliche Kennzahl. | +| P2 | Wochenvergleich & Trends | Geplant | Gleitende Durchschnitte, PR-Markierungen, Verlauf ohne Chart-Lib. | +| P2 | PWA / Offline | Geplant | Installierbar auf dem Handy (Service Worker, Icon). | +| P2 | Mehrere Sessions am Tag | Teilweise | Funktioniert; Aktivitäts-/Tag-Wechsel im UI vereinfachen. | -## Phase 4 - Qualitaet & Betrieb +### Qualität -| Prioritaet | Thema | Status | Notiz | +| Prio | Thema | Status | Notiz | |---|---|---|---| -| P2 | **Barrierefreiheit (a11y)** | Idee | Tastatur-Navigation, Kontraste, Screenreader-Labels systematisch pruefen. | -| P2 | **Backup/Retention** | Idee | Automatische Export-Erinnerung oder in-App-Backup-Timer; Dokumentation fuer Rotation. | -| P3 | **Mehrsprachigkeit ausbauen** | Idee | i18n-Architektur ist da (de/en); weitere Sprachen als Community-Beitrag. | -| P3 | **Mehr-Server / Replikation** | Idee | Datenhaltung bleibt SQLite; falls noetig: Import/Export als Synchronisationsweg dokumentieren statt Live-Replikation. | - ---- - -## Konzepte in einem Satz - -- **Content in der App statt in der Datei** - der Uebungskatalog wird Teil des - Produkts, nicht des Repos. -- **Herstellerunabhaengig** - Maschinen-Referenzen sind Hinweise, keine - Abhaengigkeit; Links/Medien sind optional und austauschbar. -- **Plugins statt Kern-Zerfaserung** - alles, was nicht jeder braucht - (Coach, Sync, Import), wird Plugin. -- **Local-first** - lokale Modelle (Ollama) sind der Default, Cloud nur auf - ausdruecklichen Wunsch. \ No newline at end of file +| P2 | Barrierefreiheit | Teilweise | Fokus, Kontraste, Labels gepflegt; systematischer Test offen. | +| P2 | Backup/Erinnerung | Geplant | Export gibt es; automatische Backup-Erinnerung offen. | +| P3 | Weitere Sprachen | Geplant | i18n-Architektur (de/en) steht; weitere Sprachen als Beitrag. | diff --git a/app.js b/app.js index d55ec24..6e7536b 100644 --- a/app.js +++ b/app.js @@ -931,6 +931,7 @@ function buildSetRow(a, model, ex, entry, i) { row.appendChild(rBox); entry.wInput = wBox.querySelector("input"); entry.rInput = rBox.querySelector("input"); + row.appendChild(el("span", "set-gap")); const reset = el("button", "icon-btn", ""); reset.type = "button"; diff --git a/styles.css b/styles.css index db8e6b9..d0f3d1c 100644 --- a/styles.css +++ b/styles.css @@ -405,7 +405,7 @@ h3 { font-size: 15px; font-weight: 700; } .ex-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(460px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(min(460px, 100%), 1fr)); gap: 14px; align-items: start; } @@ -438,12 +438,18 @@ h3 { font-size: 15px; font-weight: 700; } .set-row { display: grid; - grid-template-columns: auto auto auto auto auto; + grid-template-columns: auto auto auto 1fr auto auto; gap: 6px; align-items: center; padding: 6px 8px; } +.set-gap { min-width: 0; } + +@media (max-width: 480px) { + .field-box { width: 72px; } +} + .set-rows { overflow: hidden; } .set-row.is-done { background: var(--bg-subtle); }