Files
haushalt/CLAUDE.md
Marek Lenczewski 27b34eb90f Task module
2026-04-12 10:06:17 +02:00

6.5 KiB

Haushalt

Basis-Software mit 3 geplanten Apps: Task Manager, Shopping List, Meal Planner.

Aktueller Stand: Task module implementiert (siehe module.md) — Backend + Vue + Kotlin App jeweils end-to-end mit Task-CRUD, Status-Handling und Datum.

Tech-Stack

Schicht Technologie
Backend Symfony 7.4, PHP 8.3, Doctrine ORM
Frontend Web Vue 3 (Composition API), Vite, Pinia, Vue Router 4
Frontend Mobile Kotlin + Jetpack Compose (Material 3), Retrofit + kotlinx.serialization
Datenbank MariaDB 10.11 (utf8mb4)
CORS Nelmio CORS Bundle
Umgebung DDEV

Struktur

backend/
  src/
    Collection/TaskCollection.php   — IteratorAggregate, filterInactive/sortByDueDate*
    Controller/Api/TaskController.php — REST-Routen unter /api/tasks
    DTO/TaskRequest.php             — readonly promoted constructor, Validator + Context(!Y-m-d)
    Entity/Task.php                 — Doctrine entity, getStatus() derived-past
    Enum/TaskStatus.php             — active, done, inactive, past (past nicht user-selectable)
    Repository/TaskRepository.php   — currentTasks(), allTasks() → TaskCollection
    Service/TaskManager.php         — create/update/delete/toggle Business-Logik
    Kernel.php
  config/                           — nelmio_cors, doctrine, framework, ...
  migrations/Version20260411141650.php — tasks table
  public/index.php
frontend/
  src/
    components/Icon.vue             — zentrales Icon-Component
    router/index.js                 — /, /tasks, /tasks/all, /tasks/create, /tasks/:id mit breadcrumb meta
    services/api.js                 — fetch wrapper, tasks() + statuses() Endpoints
    stores/tasks.js                 — Pinia store: fetchCurrent, fetchAll, get, create, update, remove, toggle, fetchStatuses
    views/
      Startpage.vue                 — Nav-Kacheln
      Task.vue                      — /tasks (aktuelle Tasks), Card-pro-Datum mit Legend-Titel
      TaskAll.vue                   — /tasks/all (alle Tasks, flache Liste mit Edit/Delete)
      TaskCreate.vue                — /tasks/create
      TaskEdit.vue                  — /tasks/:id
    App.vue                         — Breadcrumb-Layout + RouterView
    main.js                         — Vue-Init (Pinia + Router)
app/app/src/main/java/de/haushalt/app/
  MainActivity.kt                   — Compose entry
  MainScreen.kt                     — NavHost (start, tasks, tasks/all, tasks/create, tasks/{id})
  StartScreen.kt                    — Nav-Kacheln
  data/
    ApiClient.kt                    — Retrofit + kotlinx.serialization Setup
    TaskApi.kt                      — Retrofit interface (list, get, create, update, delete, toggle, statuses)
    Task.kt                         — Task + TaskStatus enum
  ui/task/
    TaskScreen.kt                   — /tasks, gleiches Card-Gruppierungs-Muster wie Vue
    TaskAllScreen.kt                — /tasks/all flache Liste, Edit/Delete
    TaskCreateScreen.kt / TaskCreateViewModel.kt
    TaskEditScreen.kt / TaskEditViewModel.kt
    TaskListViewModel.kt            — visibleTasks, groupedTasks, showDone, refresh, toggle
    TaskAllViewModel.kt
    DatePickerField.kt              — Material 3 DatePickerDialog Wrapper
    StatusDropdown.kt               — ExposedDropdownMenuBox, Status-Labels vom Backend
    DateFormat.kt                   — formatDate() mit dd.MM.yyyy

Domänenmodell

Task

  • id, name, date (nullable, ISO), status
  • Status-Enum (TaskStatus): active, done, inactive, past
  • past ist derived — wenn date < today, liefert Task::getStatus() automatisch past; der rohe gespeicherte Wert bleibt erhalten (getRawStatus())
  • past ist nicht user-selectable (siehe TaskStatus::userSelectableValues())
  • Filter /api/tasks?filter=current → Tasks ohne inactive, sortiert nach date aufsteigend (null-first)
  • Default (/api/tasks) → alle Tasks, sortiert nach date absteigend

REST-API

Methode Route Zweck
GET /api/tasks?filter=current aktuelle Tasks (für /tasks)
GET /api/tasks alle Tasks (für /tasks/all)
GET /api/tasks/statuses user-selectable Statuswerte als string[]
GET /api/tasks/{id} einzelner Task
POST /api/tasks Task anlegen
PUT /api/tasks/{id} Task aktualisieren
DELETE /api/tasks/{id} Task löschen
PATCH /api/tasks/{id}/toggle Status zwischen active/done togglen

Request-DTO: TaskRequest (name, date !Y-m-d, status). Deserialisiert + validiert via #[MapRequestPayload]. Response-Serialisierung: Symfony Serializer mit groups: ['task:read'], Datum als ISO Y-m-d String.

UI-Muster

  • /tasks (Vue + Kotlin): Tasks nach Datum gruppiert in Cards. Datum sitzt als Pill auf dem Top-Border der Card (fieldset/legend-Look). No-Date-Tasks oben in titelloser Card. showDone default false.
  • /tasks/all (Vue + Kotlin): Flache Liste mit Edit- und Delete-Icons. past-Tasks mit Opacity 0.5, inactive kursiv, done durchgestrichen.
  • Icon-Reihenfolge /tasks Header: plus, list, eye, refresh.
  • Kotlin-Screens refreshen auf Lifecycle.Event.ON_RESUME via DisposableEffect (gegen stale Daten nach Navigation).
  • Status-Labels in Create/Edit kommen aus dem Backend (/api/tasks/statuses) — nicht clientseitig hardcoded.

Dokumentation

  • base.md — Vision: was gebaut wird (3 Apps, Systeme, Datenbank-Skizze)
  • module.md — Implementierungs-Schritte als Feature-Module (Backend + Frontend end-to-end pro Modul)
  • CLAUDE.md (diese Datei) — Ist-Zustand des Codes

Code-Konventionen

  • Sprache Code: Englisch (Klassen, Methoden, Variablen)
  • Sprache UI: Deutsch
  • Enum-Werte: Englisch in DB und Code
  • Datum im Backend: ISO Y-m-d (als DTO-Input und in Response-JSON)
  • Datum im UI: dd.MM.yyyy — Formatierung in Vue (formatDate in Task.vue) und Kotlin (DateFormat.kt)
  • Frontend: Vue 3 Composition API mit <script setup>

Development

# DDEV starten
ddev start

# Backend
ddev exec "cd backend && php bin/console cache:clear"
ddev exec "cd backend && php bin/console doctrine:migrations:migrate"

# Frontend
ddev exec "cd frontend && npm install"
ddev exec "cd frontend && npm run dev -- --host 0.0.0.0"
ddev exec "cd frontend && npm run build"

# Android App (Java 17 für Gradle)
cd app && JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ./gradlew :app:installDebug

# URLs
Frontend: https://haushalt.ddev.site:5173
API:      https://haushalt.ddev.site/api