Flo Eisenmenger, Geschäftsführer der spawntree GmbH (kleine Webagentur, Hamburg). DDEV-Entwicklungsumgebung, Symfony 7.x, PHP 8.2, MariaDB 10.11.
Ein internes Timetracking-Tool – zunächst nur für mich, später ggf. als SaaS. Technisch ähnlich wie mite.de – wir orientieren uns stark am UI/UX von mite.
Userid, email (unique), firstName, lastName, password (nullable), notef.eisenmenger@spawntree.de / Flo EisenmengerClient (Kunde)id, name, hourlyRate (decimal, nullable), noteProjectsProjectid, name, client (ManyToOne → Client), noteService (Leistung)id, name, billable (bool, default true), noteTimeEntryid, date (DATE_IMMUTABLE), duration (int, Minuten), user, project, service (nullable), note, createdAt, updatedAttoArray() Methode für JSON-ResponsesGET / → timetracking_weekGET /week/{date} → timetracking_week_dateGET /api/entries?date=Y-m-d → Einträge für einen Tag (JSON)POST /api/entries → Eintrag erstellenPATCH /api/entries/{id} → Eintrag bearbeitenDELETE /api/entries/{id} → Eintrag löschenGET /clients → client_indexPOST /api/clients, PATCH /api/clients/{id}, DELETE /api/clients/{id}GET /projects → project_indexPOST /api/projects, PATCH /api/projects/{id}, DELETE /api/projects/{id}GET /services → service_indexPOST /api/services, PATCH /api/services/{id}, DELETE /api/services/{id}templates/
├── base.html.twig ← Basistemplate mit Nav-Include
├── _nav.html.twig ← Dunkle Top-Navigation
├── timetracking/
│ ├── week.html.twig ← Hauptseite (Zeiterfassung)
│ └── _entry_row.html.twig ← Partial: einzelne Zeiteintrag-Zeile
├── client/
│ └── index.html.twig ← Kundenliste mit Inline-Edit
├── project/
│ └── index.html.twig ← Projektliste mit Inline-Edit
└── service/
└── index.html.twig ← Leistungsliste mit Inline-Edit
assets/styles/
├── main.scss ← Entry Point, importiert alles
├── atoms/
│ ├── _variables.scss ← Farben, Spacing, etc.
│ ├── _typography.scss
│ ├── _buttons.scss ← .btn, .btn-primary, .btn-secondary
│ └── _inputs.scss ← .input, .select, .textarea
└── components/
├── _week-nav.scss ← Wochennavigation im Header
├── _month-calendar.scss ← Monatskalender (Popup)
├── _entry-form.scss ← Zeiterfassungs-Formular
├── _entry-list.scss ← Eintrags-Liste inkl. Inline-Edit
├── _duration-help.scss ← "?"-Tooltip beim Dauerfeld
├── _main-nav.scss ← Dunkle Top-Nav
├── _greeting.scss ← Begrüßungszeile
└── _crud.scss ← CRUD-Seiten (Kunden/Projekte/Leistungen)
sections/
└── _timetracking.scss ← .tt-page, .tt-header, .tt-content
assets/
├── app.js ← Webpack Entry für Hauptseite
│ importiert: main.scss, calendar.js, entries.js
├── scripts/
│ ├── calendar.js ← WeekCalendar Klasse
│ │ - Wochennavigation mit Slide-Animation
│ │ - Monatsansicht (Popup)
│ │ - Ruft window.entryManager.loadEntriesForDate() auf
│ ├── entries.js ← EntryManager Klasse
│ │ - Event Delegation auf #entry-list
│ │ - CRUD via fetch()
│ │ - localStorage für letztes Projekt/Leistung
│ │ - Importiert aus duration.js
│ ├── duration.js ← Hilfsfunktionen (Export)
│ │ - parseDuration() (1:30, 8 12, 1,75)
│ │ - roundToQuarter() (konfigurierbar)
│ │ - DURATION_CONFIG.roundToQuarter = true
│ │ - initDurationBlurHandler()
│ └── crud.js ← Webpack Entry für CRUD-Seiten
│ Generic für Kunden/Projekte/Leistungen
Wichtig: entries.js nutzt ES Module import/export – funktioniert mit Webpack Encore.
Zwei Entries:
app → ./assets/app.js (Hauptseite)crud → ./assets/scripts/crud.js (CRUD-Seiten)CRUD-Seiten laden crud.js via {{ encore_entry_script_tags('crud') }} im Twig-Block.
1:30, 8 12 (von-bis), 1,75 (Dezimal), 0:00 (Reset)formatMinutes() → "1:30"translations/messages.de.yamlAppExtension.php als Twig-Functions: deMonths(), deMonthsShort(), deWeekdays(), deWeekdaysShort()window.TT.i18n (aus Twig gesetzt)function t(key) { return window.TT?.i18n?.[key] ?? key; }/api/...{ error: "..." } mit passendem HTTP-StatusAktuell hardcoded auf f.eisenmenger@spawntree.de.
Auth (Login/Session) ist noch nicht gebaut – kommt später.
bash reset-and-seed.sh
# → DB droppen, Migrations ausführen, app:seed aufrufen
app:seed legt an: 1 User, 5 Leistungen (4 verrechenbar, 1 intern), 10 Kunden mit je 1-3 Projekten.
testtimetrackinghttps://testtimetracking.ddev.site:8456https://testtimetracking.ddev.site:8037 (nach ddev get ddev/ddev-phpmyadmin)db, Passwort db, DB db.env: DATABASE_URL="mysql://db:db@db:3306/db?serverVersion=10.11.2-MariaDB&charset=utf8mb4"