update plan

This commit is contained in:
Marek Lenczewski
2026-04-12 16:00:26 +02:00
parent 3fd7bb661c
commit 168f6ba6b7
3 changed files with 54 additions and 94 deletions

129
CLAUDE.md
View File

@@ -2,13 +2,13 @@
Basis-Software mit 3 geplanten Apps: Task Manager, Shopping List, Meal Planner. 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. Aktueller Stand: **TaskSchema module** implementiert (siehe `module.md`).
## Tech-Stack ## Tech-Stack
| Schicht | Technologie | | Schicht | Technologie |
|---------|------------| |---------|------------|
| Backend | Symfony 7.4, PHP 8.3, Doctrine ORM | | Backend | Symfony 7.4, PHP 8.3, Doctrine ORM, Symfony Messenger + Scheduler |
| Frontend Web | Vue 3 (Composition API), Vite, Pinia, Vue Router 4 | | Frontend Web | Vue 3 (Composition API), Vite, Pinia, Vue Router 4 |
| Frontend Mobile | Kotlin + Jetpack Compose (Material 3), Retrofit + kotlinx.serialization | | Frontend Mobile | Kotlin + Jetpack Compose (Material 3), Retrofit + kotlinx.serialization |
| Datenbank | MariaDB 10.11 (utf8mb4) | | Datenbank | MariaDB 10.11 (utf8mb4) |
@@ -20,118 +20,93 @@ Aktueller Stand: **Task module** implementiert (siehe `module.md`) — Backend +
``` ```
backend/ backend/
src/ src/
Collection/TaskCollection.php — IteratorAggregate, filterInactive/sortByDueDate* Collection/TaskCollection.php, TaskSchemaCollection.php
Controller/Api/TaskController.php — REST-Routen unter /api/tasks Controller/Api/TaskController.php, TaskSchemaController.php
DTO/TaskRequest.php — readonly promoted constructor, Validator + Context(!Y-m-d) DTO/TaskRequest.php, TaskSchemaRequest.php
Entity/Task.php — Doctrine entity, getStatus() derived-past Entity/Task.php (+ schema FK), TaskSchema.php
Enum/TaskStatus.php — active, done, inactive, past (past nicht user-selectable) Enum/TaskStatus.php, TaskSchemaStatus.php
Repository/TaskRepository.php — currentTasks(), allTasks() → TaskCollection Message/GenerateTasksMessage.php
Service/TaskManager.php — create/update/delete/toggle Business-Logik MessageHandler/GenerateTasksMessageHandler.php
Kernel.php Repository/TaskRepository.php, TaskSchemaRepository.php
config/ — nelmio_cors, doctrine, framework, ... Service/TaskManager.php (update/delete/toggle), TaskSchemaManager.php (create/update/delete), TaskGenerator.php (generateTasks/removeTasks/generateNewTasks)
migrations/Version20260411141650.php — tasks table Schedule.php — Scheduler (cron 0 3 * * *)
public/index.php config/packages/messenger.yaml — scheduler_default transport
migrations/
public/app/version.json + haushalt.apk — App-Update
frontend/ frontend/
src/ src/
components/Icon.vue — zentrales Icon-Component components/Icon.vue
router/index.js — /, /tasks, /tasks/all, /tasks/create, /tasks/:id mit breadcrumb meta router/index.js — /, /tasks, /tasks/all, /tasks/:id, /schemas, /schemas/create, /schemas/:id
services/api.js — fetch wrapper, tasks() + statuses() Endpoints services/api.js taskApi + schemaApi
stores/tasks.js — Pinia store: fetchCurrent, fetchAll, get, create, update, remove, toggle, fetchStatuses stores/tasks.js, schemas.js
views/ views/ — Startpage, Task, TaskAll, TaskEdit, SchemaCreate, SchemaAll, SchemaEdit
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/ app/app/src/main/java/de/haushalt/app/
MainActivity.kt — Compose entry MainActivity.kt, MainScreen.kt, StartScreen.kt
MainScreen.kt — NavHost (start, tasks, tasks/all, tasks/create, tasks/{id}) data/ — ApiClient, TaskApi, Task, TaskSchemaApi, TaskSchema, AppUpdateApi, AppUpdater
StartScreen.kt — Nav-Kacheln ui/task/ — TaskScreen, TaskAllScreen, TaskEditScreen, ViewModels, DatePickerField, StatusDropdown, DateFormat
data/ ui/schema/ — SchemaCreateScreen, SchemaEditScreen, SchemaAllScreen, ViewModels, SchemaComponents
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 ## Domänenmodell
**Task** **Task**: id, name, date?, status (active/done/inactive/past), schema?
- `id`, `name`, `date` (nullable, ISO), `status` - `past` ist derived (date < today), nicht user-selectable
- 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()`) **TaskSchema**: id, name, status (active/inactive), taskStatus, date?, repeat (json)?, start?, end?
- `past` ist **nicht user-selectable** (siehe `TaskStatus::userSelectableValues()`) - repeat=null → single (Task direkt, kein Schema persistiert)
- Filter `/api/tasks?filter=current` → Tasks ohne `inactive`, sortiert nach `date` aufsteigend (null-first) - repeat={"daily":true} / {"weekly":[7 bools]} / {"monthly":[31 bools]}
- Default (`/api/tasks`) → alle Tasks, sortiert nach `date` absteigend - getRepeatType() → 'daily' | 'weekly' | 'monthly' | null
## REST-API ## REST-API
| Methode | Route | Zweck | | Methode | Route | Zweck |
|---|---|---| |---|---|---|
| GET | `/api/tasks?filter=current` | aktuelle Tasks (für `/tasks`) | | GET | `/api/tasks?filter=current` | aktuelle Tasks |
| GET | `/api/tasks` | alle Tasks (für `/tasks/all`) | | GET | `/api/tasks` | alle Tasks |
| GET | `/api/tasks/statuses` | user-selectable Statuswerte als `string[]` | | GET | `/api/tasks/statuses` | selectable Statuswerte |
| GET | `/api/tasks/{id}` | einzelner Task | | GET | `/api/tasks/{id}` | einzelner Task |
| POST | `/api/tasks` | Task anlegen |
| PUT | `/api/tasks/{id}` | Task aktualisieren | | PUT | `/api/tasks/{id}` | Task aktualisieren |
| DELETE | `/api/tasks/{id}` | Task löschen | | DELETE | `/api/tasks/{id}` | Task löschen |
| PATCH | `/api/tasks/{id}/toggle` | Status zwischen `active`/`done` togglen | | PATCH | `/api/tasks/{id}/toggle` | activedone togglen |
| GET | `/api/task-schemas` | alle Schemas |
Request-DTO: `TaskRequest` (name, date `!Y-m-d`, status). Deserialisiert + validiert via `#[MapRequestPayload]`. | GET | `/api/task-schemas/{id}` | einzelnes Schema |
Response-Serialisierung: Symfony Serializer mit `groups: ['task:read']`, Datum als ISO `Y-m-d` String. | POST | `/api/task-schemas` | Schema erstellen (+ Tasks generieren) |
| PUT | `/api/task-schemas/{id}` | Schema aktualisieren (remove + regenerate Tasks) |
| DELETE | `/api/task-schemas/{id}` | Schema + nicht-past Tasks löschen |
## UI-Muster ## 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`**: Tasks nach Datum gruppiert in Cards (Legend-Titel). Icons: calendar, +, list, eye, refresh.
- **`/tasks/all`** (Vue + Kotlin): Flache Liste mit Edit- und Delete-Icons. `past`-Tasks mit Opacity 0.5, `inactive` kursiv, `done` durchgestrichen. - **`/tasks/all`**: Flache Liste mit Edit/Delete. past=0.5 opacity, inactive=kursiv, done=durchgestrichen.
- **Icon-Reihenfolge `/tasks` Header**: plus, list, eye, refresh. - **`/schemas`**: Schema-Liste mit Name + Repeat nebeneinander, Edit/Delete Icons.
- Kotlin-Screens refreshen auf `Lifecycle.Event.ON_RESUME` via `DisposableEffect` (gegen stale Daten nach Navigation). - **Schema Create/Edit**: name, (status + taskStatus nebeneinander), repeat, weekday/monthday grid, (start + end nebeneinander).
- Status-Labels in Create/Edit kommen aus dem Backend (`/api/tasks/statuses`) — nicht clientseitig hardcoded. - Kotlin: Lifecycle-Refresh via DisposableEffect ON_RESUME.
- App-Update: "Update prüfen" Button auf StartScreen, APK von Server laden.
## Dokumentation ## Dokumentation
- **`base.md`** — Vision: was gebaut wird (3 Apps, Systeme, Datenbank-Skizze) - **`base.md`** — Vision: was gebaut wird
- **`module.md`** — Implementierungs-Schritte als Feature-Module (Backend + Frontend end-to-end pro Modul) - **`module.md`** — Implementierungs-Schritte als Feature-Module
- **`CLAUDE.md`** (diese Datei) — Ist-Zustand des Codes - **`CLAUDE.md`** (diese Datei) — Ist-Zustand des Codes
## Code-Konventionen ## Code-Konventionen
- **Sprache Code**: Englisch (Klassen, Methoden, Variablen) - **Sprache Code**: Englisch, **UI**: Deutsch, **Enum-Werte**: Englisch
- **Sprache UI**: Deutsch - **Datum**: Backend ISO `Y-m-d`, UI `dd.MM.yyyy`
- **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>` - **Frontend**: Vue 3 Composition API mit `<script setup>`
## Development ## Development
```bash ```bash
# DDEV starten
ddev start ddev start
# Backend
ddev exec "cd backend && php bin/console cache:clear" ddev exec "cd backend && php bin/console cache:clear"
ddev exec "cd backend && php bin/console doctrine:migrations:migrate" 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 dev -- --host 0.0.0.0"
ddev exec "cd frontend && npm run build" 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 cd app && JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ./gradlew :app:installDebug
# App-Update: APK nach backend/public/app/ kopieren, version.json versionCode hochzählen
# URLs # URLs
Frontend: https://haushalt.ddev.site:5173 Frontend: https://haushalt.ddev.site:5173
API: https://haushalt.ddev.site/api API: https://haushalt.ddev.site/api

View File

@@ -19,9 +19,8 @@ Fundament/Vision - WAS gebaut wird
- Jetpack Compose - Kotlin components - Jetpack Compose - Kotlin components
# Database # Database
- Task (id, name, date, status, category, schema) - Task (id, name, date, status, schema?)
- Category (id, name, color) - TaskSchema (id, name, status, taskStatus, date?, repeat?, start?, end?)
- TaskSchema (id, name, category, type, start, end)
- Item (id, name, unit) - Items - Item (id, name, unit) - Items
- ShoppingList (id) - Shopping list - ShoppingList (id) - Shopping list
- ItemList (id, list, item, quantity, status) - Items for shopping list - ItemList (id, list, item, quantity, status) - Items for shopping list

View File

@@ -113,17 +113,3 @@ Implementierungs-Schritte als Feature-Module - WIE es gebaut wird
- Repeat schema: tasks for period (max 14 days), scheduler fills daily - Repeat schema: tasks for period (max 14 days), scheduler fills daily
- Update: remove non-past tasks + regenerate - Update: remove non-past tasks + regenerate
- Delete: remove non-past tasks + schema - Delete: remove non-past tasks + schema
# Category module
## Backend
- Category - Category entity
- id, name, color
- Task - Task entity
- category
-
- CategoryController - Category routes
- index, show, create, update, delete
- TaskSchemaManager - TaskSchema CRUD
- TaskSchemaRepository - TaskSchema queries