15 KiB
TASKS.md — Build-Checkliste CheckPoint Ehrenamt App
Eine Aufgabe pro Session. Nach Abhängigkeit geordnet — von oben nach unten abarbeiten. Pro Session: Tool, Ziel, Session-Prompt (zum Einfügen), Deliverables. Nach jeder Session: alle Häkchen setzen, committen, erst dann die nächste starten.
Tool-Legende: 🛠 Claude Code · 💻 Continue + Qwen · 🏛 Continue + Mistral Modell wechseln:
llama-switch→ [1] Architect / [2] Coder
Session 1 · Scaffold & Projektgerüst 🛠
Ziel: Lauffähiges Flask-Grundgerüst mit App-Factory, SQLite, zwei leeren Shell-Templates, Static-Einbindung und Team-Scoping-Stub.
Prompt:
Lies CLAUDE.md. Erstelle das Projektgerüst gemäß der vorgeschlagenen Struktur:
Flask-App-Factory, SQLAlchemy mit SQLite (instance/), requirements.txt,
zwei minimale Shell-Templates base_user.html (Klasse cp-shell-user) und
base_admin.html (Klasse cp-shell-admin), jeweils mit eingebundener tokens.css
und ihrem jeweiligen Komponenten-CSS, sowie ein leeres Team-Scoping (Helper,
der das aktive Team aus der Session liest). Zeig mir zuerst den Plan und die
Dateiliste, bevor du schreibst.
Deliverables:
- App startet lokal (
flask run) und zeigt eine leere Startseite base_user.htmlundbase_admin.htmlexistieren, je mit korrekter Shell-Klassetokens.cssin beiden eingebunden;components.cssnur inbase_user.html,components-admin.cssnur inbase_admin.html- SQLite initialisiert,
instance/in.gitignore - Team-Scoping-Helper vorhanden (noch ohne echte Logik)
requirements.txtminimal gehalten
Session 2 · Datenmodell & Mandanten 💻
Ziel: Alle Modelle aus CLAUDE.md, jedes mit team_id. Seed für das erste Team
(CheckPoint) inkl. Brand-Tokens und den zwei Chat-Kanälen.
Prompt:
@file app/models.py
@file CLAUDE.md
Erst den Ansatz erklären, dann implementieren — ein Modell nach dem anderen.
Baue die Modelle: team, user, planungszeitraum, einsatz, verfuegbarkeit,
zuteilung, dokument, kanal, nachricht. Jedes mit team_id. Danach ein Seed-Skript,
das das CheckPoint-Team mit Brand-Tokens und den Kanälen "ankuendigungen" und
"team" anlegt. Halte dich an die Feldvorgaben in CLAUDE.md.
Deliverables:
- Alle Modelle vorhanden, jedes mit
team_id - Beziehungen sauber (Einsatz↔Planungszeitraum, Zuteilung↔User/Einsatz)
- Seed legt CheckPoint-Team + 2 Kanäle an
- DB lässt sich anlegen, Seed läuft ohne Fehler
Session 3 · Auth & Admin-Anlage 💻
Ziel: Login (Nutzername + Passwort, gehasht), Session, Logout, Team-Scoping aktiv, Admin kann Nutzer anlegen. Keine Selbstregistrierung.
Prompt:
@file app/auth.py
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. Baue: Login mit Nutzername+Passwort (werkzeug-Hashing), Session,
Logout. Aktiviere das Team-Scoping (aktives Team aus der Session). Admin-geschützte
Route zum Anlegen neuer Nutzer (Rolle wählbar). Geschützte Routen leiten ohne
Login zur Anmeldung um. Ein Stück nach dem anderen.
Deliverables:
- Login/Logout funktioniert, Passwörter gehasht
- Geschützte Routen ohne Login → Redirect
- Admin kann Nutzer mit Rolle anlegen
- Alle Queries laufen team-gescoped
- 🏛 Mini-Review (Mistral): Auth gegen CLAUDE.md prüfen — als Liste, nicht umschreiben
Session 4a · User-Shell: Base-Layout, Theming & Dark-Mode-Fix 💻
Ziel: base_user.html final (Topbar, Bottom-Nav Start/Termine/Team/Profil,
FAB-Slot), User-Brand-Tokens pro Team in den <head> injizieren, Mockup-CSS auf
--cp-user-*-Tokens umstellen.
Prompt:
@file app/templates/base_user.html
@file app/static/components.css
@file app/static/tokens.css
@file CLAUDE.md
Ansatz zuerst. 1) base_user.html mit Topbar (Logo, Glocke, Avatar), Body-Klasse
cp-shell-user und Bottom-Nav (Start, Termine, Team, Profil). 2) User-Brand-Tokens
(--cp-user-brand-*) des aktiven Teams serverseitig in den <head> schreiben.
3) Im components.css alle fest verdrahteten Weißwerte (Topbar, Bottom-Nav,
.cp-page-Verlauf) auf --cp-user-*-Tokens umstellen, damit der Dunkelmodus greift.
Erst die Token-Umstellung erklären, dann umsetzen.
Deliverables:
base_user.htmlmit korrekter Bottom-Nav (4 Punkte, „Termine"), Klassecp-shell-user- User-Brand-Tokens kommen pro Team aus der DB in den
<head> - Keine festen Weiß-/Schwarzwerte mehr im
components.css - Hell- und Dunkelmodus optisch sauber (System-Umschaltung testen)
Session 4b · Admin-Shell: Sidebar, Off-Canvas & Theming 💻
Ziel: base_admin.html mit Desktop-Sidebar (Start, Planung, Dienste, Freigaben,
Team, Chat-Verwaltung, Profil, Abmelden), Admin-Brand-Tokens pro Team in den <head>,
mobiles Off-Canvas-Menü per Hamburger-Icon und kleinem Vanilla-JS.
Prompt:
@file app/templates/base_admin.html
@file app/static/components-admin.css
@file app/static/tokens.css
@file app/static/sidebar.js
@file CLAUDE.md
Ansatz zuerst. 1) base_admin.html mit Body-Klasse cp-shell-admin: Sidebar links
(Logo oben, Navigationspunkte Start/Planung/Dienste/Freigaben/Team/Chat-Verwaltung/
Profil, Abmelden unten abgetrennt) und Hauptbereich rechts. 2) Admin-Brand-Tokens
(--cp-admin-brand-*) serverseitig in den <head> schreiben. 3) components-admin.css
ausschließlich mit --cp-admin-*-Tokens aufbauen (Cards, Tabellen, Buttons gemäß
CLAUDE.md-Regeln). 4) Unter dem Breakpoint: Sidebar kollabiert zu einer schmalen
Topbar mit Hamburger-Icon; sidebar.js togglet eine Klasse, die die Sidebar als
Off-Canvas-Overlay einblendet, schließt bei Klick auf Overlay-Fläche oder einen
Menüpunkt. Vanilla, keine Bibliothek. Erst den Ansatz fürs Off-Canvas-Verhalten
erklären, dann umsetzen.
Deliverables:
base_admin.htmlmit Sidebar (alle 7 Punkte + Abmelden), Klassecp-shell-admin- Admin-Brand-Tokens kommen pro Team aus der DB in den
<head> components-admin.cssnutzt ausschließlich--cp-admin-*-Tokens, keine Vermischung mit User-Tokens- Sidebar kollabiert unter dem Breakpoint zu Hamburger + Off-Canvas-Overlay
- Hell- und Dunkelmodus der Arbeitsfläche sauber (Sidebar bleibt bewusst dunkel in beiden Modi)
- Touch-Ziele auch im Admin-Bereich ≥ 44px
Session 5 · Planungszeitraum & Einsätze (Admin) 💻
Ziel: Admin legt Planungszeiträume an und trägt Einsätze ein (Datum, Zeit, Art). Läuft in der Admin-Shell.
Prompt:
@file app/routes/planung.py
@file app/templates/base_admin.html
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. Admin-Ansichten (erweitern base_admin.html): Planungszeitraum
anlegen (Status in_planung) und darin Einsätze hinzufügen/bearbeiten/löschen
(Datum, Start/Ende, Art/Ort, je 2 Haupt- + 1 Springerplatz). Reine POST-Formulare,
kein JS. Liste der Einsätze eines Zeitraums als Cards/Tabelle im Admin-Stil.
Deliverables:
- Admin kann Zeitraum anlegen
- Admin kann Einsätze anlegen/bearbeiten/löschen
- Einsatz kennt seine Platzstruktur (2 + Springer)
- Alles team-gescoped, ohne JavaScript, in der Admin-Shell
Session 6 · Verfügbarkeit melden (Ehrenamtliche) 💻
Ziel: Ehrenamtliche melden pro Einsatz „kann / kann nicht", solange in_planung.
Prompt:
@file app/routes/planung.py
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. Ansicht für Ehrenamtliche: Liste der Einsätze im laufenden Zeitraum
mit Umschaltung kann/kann_nicht pro Einsatz (POST-Formular). Änderung nur bei Status
in_planung. Übersichtlich für mobile.
Deliverables:
- Ehrenamtliche sehen die Einsätze des aktuellen Zeitraums
- kann/kann_nicht wird gespeichert und ist änderbar (nur in_planung)
- Nach Veröffentlichung gesperrt
- Mobile sauber bedienbar (44px-Ziele)
Session 7 · Dienstplan bauen (Admin) 💻
Ziel: Admin verteilt manuell 2 Haupt + 1 Springer pro Einsatz, mit Fairness-Anzeige. Läuft in der Admin-Shell (Tabellen-Stil).
Prompt:
@file app/routes/dienste.py
@file app/templates/base_admin.html
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. Admin-Ansicht pro Einsatz (in der Admin-Shell, Tabelle im Stil aus
CLAUDE.md: Navy-Tabellenkopf, Statusspalten mit Text+Farbe): verfügbare Personen
auswählen und auf Haupt/Springer setzen. Pro Person anzeigen: Anzahl bisheriger
Einsätze und letzter Einsatz (Fairness-Hilfe). Einsatz als „unterbesetzt" markieren,
wenn zu wenige. Keine automatische Verteilung — nur Anzeige + manuelle Auswahl.
Deliverables:
- Admin kann Haupt- und Springerplätze besetzen
- Fairness-Anzeige (Anzahl + letzter Einsatz) pro Person sichtbar
- Unterbesetzte Einsätze klar markiert
- Tabelle nutzt ausschließlich
--cp-admin-*-Tokens - 🏛 Review (Mistral): Zuteilungslogik gegen CLAUDE.md prüfen
Session 8 · Veröffentlichen & persönliche Terminübersicht 💻
Ziel: Admin veröffentlicht den Zeitraum; jede:r sieht „Meine Termine" als Liste.
Prompt:
@file app/routes/dienste.py
@file app/templates/
@file CLAUDE.md
Ansatz zuerst. 1) Admin-Aktion „Veröffentlichen" (Status veroeffentlicht, sperrt
Verfügbarkeit). 2) Ansicht „Meine Termine": Liste der eigenen zugeteilten Einsätze,
chronologisch, mit Rolle (Haupt/Springer) und Status. Keine Kalenderansicht.
Deliverables:
- Veröffentlichen funktioniert und sperrt die Verfügbarkeit
- „Meine Termine" zeigt eigene Einsätze als Liste
- Haupt/Springer und Status erkennbar (nicht nur über Farbe)
Session 9 · Absage & Übernahme 💻
Ziel: Absage einer Hauptperson → Springer rückt automatisch nach → Springerplatz wird offen → „Übernehmen" für alle.
Prompt:
@file app/routes/dienste.py
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. Logik laut CLAUDE.md: Sagt eine Hauptperson ab, rückt der Springer
automatisch nach (status uebernommen) und der Springerplatz wird offen. Offene
Plätze erscheinen mit „Übernehmen"-Button; wer zuerst klickt, bekommt ihn (sauber
gegen Doppel-Klicks absichern). Kein Springer → Platz direkt offen.
Deliverables:
- Absage einer Hauptperson → Springer rückt automatisch nach
- Frei gewordener Springerplatz wird offen zum Übernehmen
- „Übernehmen" sicher gegen gleichzeitige Klicks
- Fall „kein Springer" korrekt behandelt
- 🏛 Review (Mistral): Übernahme-Logik prüfen (Randfälle!)
Session 10 · Dokumente & Freigabe 💻
Ziel: Upload (alle), Freigabe-Warteschlange (Admin), Liste Aktuell/Archiv.
Hinweis — gemischte Shell: Die Upload-/Listenansicht für Ehrenamtliche läuft in
der User-Shell (base_user.html), die Freigaben-Ansicht ausschließlich in der
Admin-Shell (base_admin.html). Beide Templates entsprechend ansprechen, nicht
vermischen.
Prompt:
@file app/routes/dokumente.py
@file app/templates/base_user.html
@file app/templates/base_admin.html
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. 1) Upload-Ansicht in der User-Shell (PDF/Word/Bild) mit Pflicht-Titel
→ Status wartet_auf_freigabe (nur Admin + Uploader sichtbar), dort auch die Liste
Aktuell/Archiv für Ehrenamtliche. 2) Freigaben-Ansicht in der Admin-Shell:
freigeben/ablehnen (optional Grund), Admin-Uploads direkt freigegeben, Verschieben
Aktuell↔Archiv. Dateigrößen-Limit und Dateityp-Prüfung serverseitig.
Deliverables:
- Upload landet in wartet_auf_freigabe (nicht öffentlich sichtbar), in der User-Shell
- Admin kann freigeben/ablehnen in der Admin-Shell, Admin-Uploads direkt sichtbar
- Liste Aktuell + Archiv (User-Shell), Verschieben durch Admin (Admin-Shell)
- Server prüft Dateityp und -größe
Session 11 · Chat (2 Kanäle, Polling) 💻
Ziel: Ankündigungen (nur Admin postet) + Team (alle). Nur Text. Neue Nachrichten
per fetch-Polling (einzige v1-JS-Ausnahme).
Prompt:
@file app/routes/chat.py
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. Zwei Kanäle: ankuendigungen (nur Admin darf posten, alle lesen) und
team (alle posten). Nur Text. Nachrichten chronologisch. Dazu ein kleiner
JSON-Endpunkt „neue Nachrichten seit X" und ~30 Zeilen Vanilla-JS, das im
Hintergrund pollt und neue Nachrichten anhängt. Kein Framework, kein WebSocket.
Deliverables:
- Beide Kanäle funktionieren, Rechte korrekt (Ankündigungen nur Admin)
- Nachrichten werden gespeichert und angezeigt (nur Text)
- Polling lädt neue Nachrichten ohne Seiten-Reload
- JS ist minimal und vanilla
Session 12 · Profil 💻
Ziel: Profilbild-Upload + Platzhalter für optionale freiwillige Angaben.
Prompt:
@file app/routes/profil.py
@file app/models.py
@file CLAUDE.md
Ansatz zuerst. Profil-Ansicht: Profilbild hochladen/ändern, Anzeigename, optionale
freiwillige Felder (vorerst ein, zwei Freitextfelder als Platzhalter — Struktur so,
dass Felder später leicht ergänzt werden). Nichts davon Pflicht.
Deliverables:
- Profilbild hochladbar
- Optionale Felder vorhanden, nichts Pflicht
- Struktur erlaubt späteres Ergänzen von Feldern
Session 13 · In-App-Benachrichtigungen 💻
Ziel: Dezente in-App-Hinweise (neuer Dienst, offener Dienst, neue Nachricht) in beiden Shells.
Prompt:
@file app/models.py
@file app/templates/base_user.html
@file app/templates/base_admin.html
@file CLAUDE.md
Ansatz zuerst. Einfaches Benachrichtigungsmodell + Anzeige: Glocke in der Topbar
der User-Shell mit Zähler, Liste beim Antippen; in der Admin-Shell entsprechend in
der Sidebar/Kopfbereich. Auslöser: neue Zuteilung, neuer offener Dienst, neue
Nachricht. Als gelesen markierbar. Kein Push, keine E-Mail.
Deliverables:
- Benachrichtigungen werden bei den drei Auslösern erzeugt
- Glocke/Hinweis zeigt ungelesene an, in beiden Shells passend platziert
- Als gelesen markierbar
Session 14 · Gesamt-Review 🏛
Ziel: Durchsicht des fertigen Stands gegen CLAUDE.md — Korrektheit, Konsistenz, Barrierearmut, Dunkelmodus.
Prompt:
@file CLAUDE.md
@file app/models.py
@file app/routes/
Review den aktuellen Stand gegen CLAUDE.md. Korrektheitsprobleme zuerst, dann
Konsistenz und Wartbarkeit, dann Barrierearmut und Dunkelmodus-Lücken. Nichts
umschreiben — alles als nummerierte Liste mit Fundstelle.
Deliverables:
- Review-Liste erstellt
- Gefundene Korrektheitsprobleme in 💻-Folgeschritten behoben
- A11y- und Dark-Mode-Lücken geschlossen
Session 15 · Deployment auf den VPS 🛠
Ziel: App läuft auf dem EU-VPS hinter einem produktiven Server.
Prompt:
Lies CLAUDE.md. Hilf mir beim Deployment auf einen EU-VPS: WSGI-Server (z. B.
gunicorn) hinter nginx, Umgebungsvariablen/Secrets, Persistenz für SQLite und
Uploads, einfaches Backup der DB, HTTPS. Gib mir die Schritte als Fish-Befehle,
wo Terminal nötig ist. Plan zuerst.
Deliverables:
- App läuft unter gunicorn hinter nginx
- HTTPS aktiv
- Secrets über Umgebungsvariablen, nicht im Code
- DB + Uploads persistent, einfaches DB-Backup eingerichtet
Future Log (nicht in v1)
1:1-Chat · Push-/E-Mail-Benachrichtigungen · E-Mail+Code-Login (Magic Link) · manueller Hell/Dunkel-Umschalter · automatische Fairness-Verteilung · weitere Rollen · Laptop-Spiegelung / Desktop-Fallback über LAN.