shinkan-jinkendo/.claude/rules/CODING_RULES.md
Lars cbb783222c
Some checks failed
Deploy Development / deploy (push) Successful in 36s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 5s
Test Suite / playwright-tests (push) Failing after 14s
refactor: Standardisiere Formular-Layout (Label oben, volle Breite, linksbündig)
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
2026-04-22 17:11:40 +02:00

157 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Coding Rules Mitai Jinkendo
Diese Regeln IMMER befolgen. Sie basieren auf Erfahrungen aus der Entwicklung.
## Backend
### 1. Auth auf jeden Endpoint
```python
# 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
```python
pid = session['profile_id'] # ✅
# Nicht: request.headers.get('X-Profile-Id') ❌
```
### 3. bcrypt für Passwörter
```python
from auth import hash_pin, verify_pin
hashed = hash_pin(plain_password) # ✅
# Nicht: hashlib.sha256(...) ❌
```
### 4. PostgreSQL-Syntax
```python
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
```python
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_template` nicht umgehen
## Frontend
### 1. api.js für alle API-Calls
```javascript
await api.listWeight() // ✅
await fetch('/api/weight') // ❌ kein Token
```
### 2. Fehlerbehandlung in async Funktionen
```javascript
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
```javascript
// ✅ Richtig:
style={{color: 'var(--accent)'}}
// ❌ Falsch:
style={{color: '#1D9E75'}}
```
### 6. Formular-Standard (VERBINDLICH ab 2026-04-22)
**Alle neuen Formulare verwenden den Standard-Stil:**
```jsx
// ✅ 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
```