Fehlte in Phase 4: das Image soll wie bei der Kantone-App über einen
Versions-Tag gebaut, vor dem Veröffentlichen getestet und in die Gitea-
Registry gestellt werden.
Der Plan hält dazu die Punkte fest, die dort nachträglich korrigiert werden
mussten - vor allem, Werte aus ${{ ... }} nicht direkt in die Shell zu
schreiben, weil Tag-Namen Sonderzeichen enthalten dürfen und der Job ein
Registry-Token hält.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GR4bNaj9GtRu57J4Niii8o
134 lines
5.5 KiB
Markdown
134 lines
5.5 KiB
Markdown
# 📦 Kinderkleider-Börse (Web-App)
|
|
|
|
Eine schlanke, mobile-optimierte Web-App zum Katalogisieren, Präsentieren und Reservieren von zu klein gewordener Kinderkleidung für Familie, Freunde und Nachbarn.
|
|
|
|
---
|
|
|
|
## 🚀 Zielsetzungs & Kern-Features
|
|
|
|
- **Schnelles Erfassen (Mobile First):** Foto direkt mit dem Smartphone aufnehmen, Grösse & Kategorie wählen, fertig.
|
|
- **Übersichtliche Galerie & Filter:** Schnelle Filterung nach Konfektionsgrösse, Kategorie, Geschlecht und Saison.
|
|
- **Einfaches Reservierungssystem:** Interessierte können Kleidungsstücke mit einem Klick reservieren.
|
|
- **Bildoptimierung:** Automatische Skalierung und WebP-Komprimierung beim Upload, um Speicherplatz und Bandbreite zu sparen.
|
|
|
|
---
|
|
|
|
## 🛠 Technologiestack (Python-basiert)
|
|
|
|
- **Backend:** Python 3.11+ mit [FastAPI](https://fastapi.tiangolo.com/) (hohe Performance, automatische OpenAPI/Swagger-Dokumentation)
|
|
- **Datenbank & ORM:** SQLite mit [SQLAlchemy](https://www.sqlalchemy.org/) & [Alembic](https://alembic.sqlalchemy.org/) (Migrations)
|
|
- **Bildverarbeitung:** Pillow (PIL) für WebP-Konvertierung und Resizing
|
|
- **Frontend (Optionen):**
|
|
- *Variante A (Single File / Monolith):* Jinja2 Templates + HTMX + Tailwind CSS (sehr schnell zu entwickeln, kein Node.js Build-Step nötig)
|
|
- *Variante B (Decoupled):* Vue.js / React SPA (greift auf die REST-API zu)
|
|
- **Deployment:** Docker & Docker Compose (leicht auf Unraid / Server auszuführen)
|
|
|
|
---
|
|
|
|
## 🗄 Datenbank-Schema
|
|
|
|
### 1. `categories`
|
|
| Feld | Typ | Beschreibung |
|
|
|---|---|---|
|
|
| `id` | INTEGER (PK) | Eindeutige ID |
|
|
| `name` | VARCHAR(50) | Name (z. B. Hosen, Jacken, Schuhe, Pullover) |
|
|
| `slug` | VARCHAR(50) | URL-freundlicher Name |
|
|
|
|
### 2. `items` (Haupttabelle)
|
|
| Feld | Typ | Beschreibung |
|
|
|---|---|---|
|
|
| `id` | INTEGER / UUID (PK) | Eindeutige ID |
|
|
| `title` | VARCHAR(100) | Kurzer Titel (z. B. "Warme Winterjacke rot") |
|
|
| `description` | TEXT | Optionale Details oder Mängel |
|
|
| `size` | VARCHAR(20) | Konfektionsgrösse (z. B. `98/104`, `24`, `80`) |
|
|
| `gender` | VARCHAR(10) | `boy`, `girl`, `unisex` |
|
|
| `season` | VARCHAR(15) | `spring_summer`, `autumn_winter`, `all_year` |
|
|
| `condition` | VARCHAR(20) | `new`, `very_good`, `good`, `worn` |
|
|
| `status` | VARCHAR(20) | `available`, `reserved`, `given_away` |
|
|
| `category_id` | FK -> `categories.id` | Zuordnung zur Kategorie |
|
|
| `reserved_by` | VARCHAR(100) | Name/Kontakt der Person, die es reserviert hat |
|
|
| `created_at` | TIMESTAMP | Erstellungsdatum |
|
|
| `updated_at` | TIMESTAMP | Letztes Update |
|
|
|
|
### 3. `item_images`
|
|
| Feld | Typ | Beschreibung |
|
|
|---|---|---|
|
|
| `id` | INTEGER / UUID (PK) | Eindeutige ID |
|
|
| `item_id` | FK -> `items.id` | Referenz zum Kleidungsstück |
|
|
| `image_url` | VARCHAR(255) | Pfad zur Bilddatei (z. B. `/static/uploads/img_1234.webp`) |
|
|
| `is_primary` | BOOLEAN | Hauptbild für Galerie-Vorschau |
|
|
|
|
---
|
|
|
|
## 🔌 API-Endpunkte (FastAPI REST)
|
|
|
|
### Kleidung verwalten & durchsuchen
|
|
- `GET /api/v1/items`
|
|
- **Query-Params:** `?size=98/104&category_id=2&status=available&gender=unisex`
|
|
- **Response:** Liste gefilterter Kleidungsstücke mit Primärbild.
|
|
- `GET /api/v1/items/{id}`
|
|
- **Response:** Einzelnes Kleidungsstück inklusive aller Bilder und Details.
|
|
- `POST /api/v1/items`
|
|
- **Content-Type:** `multipart/form-data`
|
|
- **Body:** JSON-Daten + Bild-Uploads.
|
|
- `PATCH /api/v1/items/{id}`
|
|
- **Body:** Partial Update für Status, Titel, Beschreibung etc.
|
|
- `DELETE /api/v1/items/{id}`
|
|
- **Description:** Kleidungsstück und zugehörige Bilder löschen.
|
|
|
|
### Reservierung & Status
|
|
- `POST /api/v1/items/{id}/reserve`
|
|
- **Body:** `{"reserved_by": "Familie Meier"}`
|
|
- `POST /api/v1/items/{id}/release`
|
|
- Setzt Status zurück auf `available` und löscht `reserved_by`.
|
|
- `POST /api/v1/items/{id}/mark-given`
|
|
- Setzt Status auf `given_away`.
|
|
|
|
### Stammdaten
|
|
- `GET /api/v1/categories`
|
|
- `GET /api/v1/sizes`
|
|
|
|
---
|
|
|
|
## 📂 Empfohlene Projekt-Struktur
|
|
|
|
```text
|
|
kinderkleider-app/
|
|
├── app/
|
|
├── database.py # DB-Engine & Session Setup
|
|
├── models.py # SQLAlchemy Modelle
|
|
├── schemas.py # Pydantic Schemas (Request/Response validation)
|
|
├── crud.py # Datenbank-Zugriffslogik
|
|
├── main.py # FastAPI App Entrypoint & Routen
|
|
├── utils.py # Bild-Komprimierung & Helper
|
|
│ ├── static/ # Uploaded Images & CSS
|
|
│ └── templates/ # Jinja2 Templates (falls HTML direkt gerendert wird)
|
|
├── Dockerfile
|
|
├── docker-compose.yml
|
|
├── requirements.txt
|
|
└── README.md
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Meilensteine / Roadmap
|
|
|
|
- [ ] **Phase 1: Backend Basic MVP**
|
|
- [ ] FastAPI Setup mit SQLite & SQLAlchemy
|
|
- [ ] Datenmodelle & Migrationen anlegen
|
|
- [ ] CRUD Endpunkte für `items` und `categories` testen (Swagger UI)
|
|
- [ ] **Phase 2: Bild-Handling & Speicher**
|
|
- [ ] `multipart/form-data` Upload via FastAPI
|
|
- [ ] Pillow-Integration zur Konvertierung aller Uploads nach WebP (max. 1200px Breite)
|
|
- [ ] **Phase 3: Frontend Setup**
|
|
- [ ] Mobile-First Layout mit Tailwind CSS
|
|
- [ ] Filterleiste für Grösse, Kategorie & Status
|
|
- [ ] Reservierungs-Modal / Button
|
|
- [ ] **Phase 4: Containerisierung & Deployment**
|
|
- [ ] `Dockerfile` & `docker-compose.yml` schreiben
|
|
- [ ] Persistence per Volume-Mount für Datenbank & Bild-Uploads
|
|
- [ ] Gitea Actions: Image bei einem Versions-Tag (`v*`) bauen, testen und in
|
|
die Registry stellen — gleiches Vorgehen wie bei der Kantone-App
|
|
(`.gitea/workflows/docker-image.yml` dort als Vorlage)
|
|
- [ ] Zweite Compose-Datei zum Starten des fertigen Images (ohne Quellcode)
|