CSS (frontend/src/app.css): - .form-row: flex-direction column, volle Breite, margin-bottom 16px - .form-label: display block, font-weight 600, linksbündig - .form-input: width 100%, text-align left (statt right 90px), padding 10px 12px - textarea.form-input: resize vertical, min-height 80px - select.form-input: cursor pointer - .form-row--inline: Neue Variante für Ausnahmen (kurze Werte + Einheit) Dokumentation (.claude/rules/CODING_RULES.md): - Neue Regel Frontend §6: Formular-Standard (VERBINDLICH ab 2026-04-22) - Code-Beispiele für Standard-Layout (input, textarea, select) - Klare Regeln: Label = <label>, Pflichtfelder mit *, volle Breite, linksbündig - Inline-Variante nur für Ausnahmen (Zahlen mit Einheit) WICHTIG: Bestehende Formulare (Exercises, Clubs, Skills, TrainingPlanning) nutzen bereits größtenteils diese Struktur und profitieren automatisch von den CSS-Änderungen. Vorteile: - Konsistente UX über alle Formulare - Mobile-friendly (volle Breite, kein horizontal scrolling) - Bessere Lesbarkeit (Label als Überschrift) - Einfacher wartbar (ein Standard für alle) Nächster Schritt: Bestehende Formulare testen, ggf. kleine Anpassungen
4.1 KiB
4.1 KiB
Coding Rules – Mitai Jinkendo
Diese Regeln IMMER befolgen. Sie basieren auf Erfahrungen aus der Entwicklung.
Backend
1. Auth auf jeden Endpoint
# Jeder neue Endpoint braucht Auth:
@router.get("/neuer-endpoint")
def neuer_endpoint(session: dict = Depends(require_auth)):
pid = session['profile_id']
2. Profile-ID aus Session – nie aus Header
pid = session['profile_id'] # ✅
# Nicht: request.headers.get('X-Profile-Id') ❌
3. bcrypt für Passwörter
from auth import hash_pin, verify_pin
hashed = hash_pin(plain_password) # ✅
# Nicht: hashlib.sha256(...) ❌
4. PostgreSQL-Syntax
cur.execute("SELECT * FROM t WHERE id = %s AND active = true", (id,))
# Nicht: ? und active = 1 (SQLite-Syntax)
5. Rate Limiting für sensitive Endpoints
from slowapi import Limiter
@router.post("/sensitive")
@limiter.limit("5/minute")
def sensitive(request: Request, ...):
6. Universal CSV Import / Admin-Vorlagen
Neues Import-Zielmodul, Änderungen an csv_parser, Executor, DB-source/CHECK, oder System-CSV-Vorlagen:
- Pflichtlektüre und Checkliste:
.claude/docs/technical/UNIVERSAL_CSV_IMPORT_AGENT_GUIDE.md - Keine zweite DB-Connection im Importpfad; Zeilenfehler ohne „aborted transaction“ (SAVEPOINT-Muster wo nötig)
- Admin Create/Update von Systemvorlagen: Validierung über
validate_csv_templatenicht umgehen
Frontend
1. api.js für alle API-Calls
await api.listWeight() // ✅
await fetch('/api/weight') // ❌ kein Token
2. Fehlerbehandlung in async Funktionen
try {
const data = await api.meinEndpoint()
} catch(e) {
setError(e.message) // api.js wirft bereits Error mit detail-Text
}
3. Kein TypeScript
Das Projekt nutzt bewusst kein TypeScript – keine .ts/.tsx Dateien erstellen.
4. Keine neuen npm-Pakete ohne Absprache
Erst fragen, dann installieren.
5. CSS-Variablen statt Hardcoded-Farben
// ✅ Richtig:
style={{color: 'var(--accent)'}}
// ❌ Falsch:
style={{color: '#1D9E75'}}
6. Formular-Standard (VERBINDLICH ab 2026-04-22)
Alle neuen Formulare verwenden den Standard-Stil:
// ✅ Standard: Label oben, volle Breite, linksbündig
<div className="form-row">
<label className="form-label">Feldname *</label>
<input
type="text"
className="form-input"
value={formData.field}
onChange={(e) => updateFormField('field', e.target.value)}
required
/>
</div>
// ✅ Textarea
<div className="form-row">
<label className="form-label">Beschreibung</label>
<textarea
className="form-input"
rows={3}
value={formData.description}
onChange={(e) => updateFormField('description', e.target.value)}
/>
</div>
// ✅ Select
<div className="form-row">
<label className="form-label">Status</label>
<select
className="form-input"
value={formData.status}
onChange={(e) => updateFormField('status', e.target.value)}
>
<option value="active">Aktiv</option>
<option value="inactive">Inaktiv</option>
</select>
</div>
// ❌ NICHT: Inline-Layout mit Label links
// Nur für Ausnahmen (kurze Werte mit Einheit) nutzen:
<div className="form-row--inline">
<label className="form-label">Dauer</label>
<input type="number" className="form-input" value={duration} />
<span className="form-unit">min</span>
</div>
Regeln:
- Label ist
<label>mit Klasse.form-label(nicht<div>) - Input/Textarea/Select nutzen
.form-input - Volle Breite (100%), linksbündig
- Pflichtfelder mit
*im Label kennzeichnen - Inline-Variante (
.form-row--inline) nur für Ausnahmen (Zahlen mit Einheit)
Git & Deployment
1. Nie direkt auf main pushen
Immer über Pull Request in Gitea: develop → main
2. develop Branch nie löschen
Er ist permanent – nicht nach Merge löschen.
3. .env nie committen
Steht in .gitignore – nie entfernen.
4. Commit-Message Format
feat: neues Feature
fix: Bugfix
refactor: Umbau ohne Funktionsänderung
docs: Dokumentation
ci: CI/CD Änderungen
chore: Maintenance