thats-me/frontend/dev/19-02-2026/umsetzungskonzept.md
2026-03-06 13:56:20 +01:00

372 lines
14 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.

# Umsetzungskonzept — "That's Me" Wow-Prototyp
Dieses Dokument beschreibt die schrittweise Umsetzung des Prototyps. Jeder Schritt baut auf dem vorherigen auf und ist einzeln testbar.
---
## Phase 1: Viewport & Grundgerüst
### 1.1 — Neues App-Layout (`LifeWaveLayout.vue`)
**Ziel:** Minimalistisches Fullscreen-Layout als "Bühne" — ersetzt das bestehende MainLayout für die LifeWave-Ansicht.
**Umsetzung:**
- Neues Layout `src/layouts/LifeWaveLayout.vue` erstellen
- Fullscreen-Viewport (`100dvh`) ohne Quasar-Header/Footer/Drawer
- Neutraler Hintergrund: Hell-Modus `#FAFAFA`, Dunkel-Modus `#0A0A0A`
- CSS Custom Properties für Theme-Switching (`--bg-primary`, `--bg-glass`, `--text-primary`)
- Slot-basiert: `<router-view />` füllt den gesamten Viewport
- Kein Scrolling auf der Hauptebene — alles innerhalb des Viewports
**Struktur:**
```
┌──────────────────────────────┐
│ [User-Icon] top │ ← fixed, z-30
│ │
│ │
│ LifeWave Canvas │ ← absolute, z-0, fullscreen
│ + Glow-Punkte │
│ │
│ │
│ [+] bot │ ← fixed, z-30
└──────────────────────────────┘
```
### 1.2 — Glassmorphism CSS-System
**Ziel:** Wiederverwendbare Glass-Styles als CSS-Klassen (Referenz: die beiden Glassmorphism-Bilder).
**Umsetzung:**
- In `src/css/app.scss` definieren:
- `.glass` — Basis-Glaseffekt (`backdrop-filter: blur(20px)`, halbtransparenter Hintergrund, subtiler Border)
- `.glass--panel` — Variante für das Slide-Up-Panel (stärkerer Blur, ~40px)
- `.glass--button` — Variante für den schwebenden +-Button
- Light/Dark-Mode Varianten über CSS Custom Properties
- Subtiler `box-shadow` für Tiefe
- 1px Border mit `rgba(255,255,255,0.15)` für den "Glas-Rand"
---
## Phase 2: Header & Navigation
### 2.1 — Header-Leiste
**Ziel:** Minimalistischer Header mit Logo links und User-Icon rechts.
**Umsetzung:**
- Direkt im `LifeWaveLayout.vue` als `<header>` Element (fixed, z-20)
- **Links:** "ThatsMe" als Text-Logo (wird später durch echtes Logo ersetzt). Klick = Dark/Light Mode Toggle (temporär).
- **Rechts:** Runder User-Button (40px), `person_outline` Icon, `.glass--button` Styling
- Klick öffnet Off-Canvas-Drawer (rechte Seite)
- Später: Eingeloggt = Avatar/Initialen mit Glow-Ring
### 2.2 — Floating Action Button "+" (Bottom-Center)
**Ziel:** Einzelner schwebender Button zum Erstellen eines neuen Events.
**Umsetzung:**
- Komponente `src/components/AddEventButton.vue`
- Runder Button (56px), positioniert `bottom: 32px; left: 50%; transform: translateX(-50%); position: fixed`
- `.glass--button` Styling mit leichtem Glow-Effekt
- Material Icon `add` (weiß/grau je nach Theme)
- Klick-Animation: leichter Scale-Pulse
- Klick öffnet das Event-Panel (Phase 4)
---
## Phase 3: Timeline & Event-Dots
### 3.1 — FloatingLines als optionaler Hintergrund
**Ziel:** FloatingLines bleibt als optionales Feature erhalten, ist aber standardmäßig deaktiviert.
**Umsetzung:**
- FloatingLines im Layout eingebunden mit `v-if="showFloatingLines"` (default: `false`)
- Zuschaltbar über Toggle im Off-Canvas-Drawer
- Konfiguration: `enabledWaves: ['middle']`, `linesGradient: ['#E94FF5', '#2F4BA2']`, `lineCount: [12]`, `animationSpeed: 0.6`
- Dient als Inspiration für die spätere Verbindungslinie (Phase 3.3)
### 3.2 — Scrollbare Timeline mit Glow-Dots
**Ziel:** Events als leuchtende Kreise auf einer horizontal scrollbaren Zeitachse darstellen — wie ein visuelles Tagebuch.
Referenz: `Bildschirmfoto 2026-02-20 um 10.29.01.png`
**Konzept:**
- Der Viewport zeigt immer nur einen **Ausschnitt** der Timeline
- Die Timeline-Breite berechnet sich aus der Zeitspanne aller Events
- Horizontal scrollen (Touch-Swipe / Maus) navigiert durch die Zeit
- Unten werden **Monat und Jahr** eingeblendet (aktuell sichtbarer Bereich hervorgehoben)
**Umsetzung:**
- Neue Komponente `src/components/TimelineView.vue` — der scrollbare Container
- Timeline-Container: `overflow-x: auto; overflow-y: hidden; height: 100%`
- Innerer Container: Breite berechnet aus Datumsbereich (z.B. 120px pro Monat)
- **X-Achse (horizontal):** Datum-basierte Position — jedes Event wird auf seinen exakten Zeitpunkt positioniert
- **Y-Achse (vertikal):** Emotionswert (-1 bis +1 → unten bis oben, Mitte = unsichtbare Nulllinie = neutral)
- **Monats-Labels:** Am unteren Rand der Timeline, der aktuelle Monat groß/fett, Nachbarmonate kleiner
- **Jahres-Label:** Unter den Monaten, wechselt beim Scrollen
**GlowDot-Komponente** (`src/components/GlowDot.vue`):
- Jeder Punkt ist ein `<div>` mit radialem CSS-Gradient als "Glow"
- Größe: 20-28px Kern
- Glow-Farbe durch Emotion ODER Custom-Farbe
- Glow-Farblogik:
- **Positiv** (> 0): `#FF6B35` (Orange) → `#FFD700` (Gold) → `#4CAF50` (Grün)
- **Negativ** (< 0): `#2196F3` (Blau) `#9C27B0` (Violett) `#E91E63` (Pink)
- **Custom:** User-Farbe überschreibt den Glow, Y-Position bleibt
- Klick auf Punkt öffnet Event-Detail (Phase 5)
### 3.4 — Timeline-Zoom
**Ziel:** Der User kann in die Timeline rein- und rauszoomen. Events und Abstände skalieren, Monats-/Jahres-Schriftgrößen bleiben konstant.
**Umsetzung:**
- `zoomLevel` (0.43.0, Default 1.0) multipliziert das `EVENT_SPACING`
- GlowDots skalieren via CSS `transform: scale(var(--dot-scale))` über das `zoom`-Prop
- **Desktop:** Ctrl+Mausrad oder Trackpad-Pinch (beides feuert `wheel` mit `ctrlKey`)
- **Touch:** Zwei-Finger-Pinch-Geste
- Scroll-Position bleibt stabil: Der Punkt unter dem Cursor/Pinch-Zentrum bleibt fixiert
- Monats- und Jahres-Labels behalten ihre feste Schriftgröße
### 3.3 — Verbindungslinien zwischen Dots
**Ziel:** Eine farbverlaufende Linie verbindet die Glow-Punkte und bildet die "LifeWave". Visuell inspiriert durch die FloatingLines-Ästhetik.
**Umsetzung:**
- SVG-Overlay innerhalb des scrollbaren Timeline-Containers
- Cubic Bezier Pfade (`<path>`) zwischen den Dots
- Gradient entlang des Pfades: Start-Farbe = Glow des linken Dots, End-Farbe = Glow des rechten Dots
- Strichbreite: 2-3px, mit `filter: blur(2px)` für weichen Glow
- Organisches Feeling: Bezier-Kontrollpunkte leicht versetzt
---
## Phase 4: Neues Event anlegen (Slide-Up Panel)
### 4.1 — Event-Panel Komponente
**Ziel:** Glassmorphes Panel fährt von unten hoch. LifeWave bleibt sichtbar und wird durch das "Glas" diffus.
**Umsetzung:**
- Neue Komponente `src/components/EventPanel.vue`
- Positionierung: `position: fixed; bottom: 0; left: 0; right: 0; z-index: 20`
- Höhe: ~65% des Viewports (variabel, Drag-Handle zum Resizen optional)
- `.glass--panel` Styling (starker Backdrop-Blur ~40px)
- Abgerundete obere Ecken (`border-radius: 24px 24px 0 0`)
- Slide-Up Animation: `transform: translateY(100%)` `translateY(0)` mit `transition` oder Vue `<Transition>`
- Kleiner Drag-Handle-Balken oben (visueller Indikator, 40px breit, 4px hoch, zentriert)
- **Wichtig:** Hintergrund-LifeWave wird NICHT ausgeblendet der Glaseffekt erzeugt die Unschärfe
### 4.2 — Event-Formular (Felder im Panel)
**Ziel:** Minimalistisches Formular mit Live-Feedback.
**Felder:**
1. **Titel** Textfeld, Placeholder "Was ist passiert?"
2. **Datum** Date-Picker, Default = heute
3. **Emotions-Regler** Custom Slider von -1.0 (negativ) bis +1.0 (positiv)
- Visuelles Feedback: Slider-Track ändert Farbe (Blau/Kühl Warm/Grün)
- Thumb-Farbe passt sich an
4. **Farbe anpassen** (optional) Toggle + Color-Picker
- Default: aus (Emotion bestimmt Farbe)
- Es gibt vorgefertigte Farbverläufe für den emotions Leiter hier zum Beispiel Farbkombinationen
Verläufe
Nagativ -> neutral -> Positiv
#FD1D1D -> #FCB045 -> #833AB4
#ED8153 -> #ED8153 -> #217B9E
#00D4FF -> #164173 -> #440559
#FDBB2D -> #96BE74 -> #22C1C3
#FC466B -> #9A52B6 -> #3F5EFB
#EEAECA -> #C2B4D9 -> #94BBE9
5. **Notiz** — Textarea, optional, 3 Zeilen
6. **Speichern-Button** — Glass-Style, auffällig
### 4.3 — Live-Feedback (Der Wow-Moment)
**Ziel:** Während der User das Formular ausfüllt, erscheint in Echtzeit ein neuer Glow-Punkt im Hintergrund.
**Umsetzung:**
- Sobald das Panel geöffnet wird: ein "Ghost-Dot" (halbtransparent, pulsierend) erscheint auf der Wave
- **Emotions-Regler bewegen:** Ghost-Dot wandert auf der Y-Achse nach oben/unten, Glow-Farbe ändert sich live
- **Custom-Farbe wählen:** Glow-Farbe ändert sich sofort
- **Speichern:** Ghost-Dot wird zum festen Dot (Opacity 1.0, Puls-Animation → statisch), Verbindungslinie animiert sich zum neuen Punkt
- Ghost-Dot hat stärkere Puls-Animation als reguläre Dots
---
## Phase 5: Event bearbeiten & Detail-Ansicht
### 5.1 — Event-Detail (Tap auf Glow-Dot)
**Ziel:** Tap auf einen Glow-Dot öffnet eine kompakte Detail-Ansicht.
**Umsetzung:**
- Wiederverwendung des `EventPanel.vue` im "Edit-Modus"
- Panel fährt hoch, vorbelegt mit den Event-Daten
- Gleiche Felder wie beim Anlegen
- Zusätzlich: "Löschen"-Button (dezent, unten im Panel)
- Live-Feedback: Änderungen am Emotions-Regler / Farbe ändern den existierenden Dot in Echtzeit
### 5.2 — Dot-Selection-State
**Ziel:** Visuelles Feedback welcher Dot ausgewählt ist.
**Umsetzung:**
- Ausgewählter Dot bekommt:
- Vergrößerter Glow (Scale 1.3 mit Transition)
- Pulsierender Ring-Effekt (CSS Animation)
- Alle anderen Dots werden leicht gedimmt (Opacity 0.5)
---
## Phase 6: Smart-Panel & Einstellungen
### 6.1 — LifeWave-Einstellungen (User-Personalisierung)
**Ziel:** Der User kann seine Wave anpassen — das macht die App persönlich.
**Umsetzung:**
- Im User-Menü (Off-Canvas rechts) unter "Life Wave":
- **Wellen-Farben:** Gradient-Picker (2-4 Farben auswählen)
- **Wellen-Intensität:** Slider (lineCount: 4-20)
- **Wellen-Geschwindigkeit:** Slider (animationSpeed: 0.2-2.0)
- **Wellen-Stil:** Auswahl welche Waves aktiv sind (top/middle/bottom)
- Änderungen werden live auf die FloatingLines-Props angewendet
- Einstellungen im Pinia Store + localStorage persistiert
### 6.2 — Dark/Light Mode Toggle
**Ziel:** Nahtloser Wechsel zwischen Hell- und Dunkel-Modus.
**Umsetzung:**
- Toggle im User-Menü oder als kleines Icon neben dem User-Button
- Quasar Dark-Mode Plugin aktivieren (`$q.dark.toggle()`)
- CSS Custom Properties wechseln alle Farben
- FloatingLines `mixBlendMode` wechselt automatisch
- Hintergrundfarbe animiert den Übergang (300ms Transition)
---
## Datenmodell (Pinia Store)
### `src/stores/events.js`
```js
{
events: [
{
id: 'uuid',
title: 'Hochzeit von Lisa',
date: '2024-06-15',
emotion: 0.8, // -1.0 bis +1.0
customColor: null, // null = auto, '#FF00FF' = custom
note: 'Wunderschöner Tag im Garten...',
createdAt: timestamp,
updatedAt: timestamp,
},
]
}
```
### `src/stores/settings.js`
```js
{
theme: 'light', // 'light' | 'dark'
wave: {
gradient: ['#E94FF5', '#2F4BA2'],
lineCount: 12,
speed: 0.6,
enabledWaves: ['middle']
}
}
```
---
## Umsetzungsreihenfolge (Arbeitspakete)
| # | Paket | Abhängigkeit | Geschätzt |
| --- | --------------------------------------- | ------------ | ---------- |
| 1 | Phase 1.1 — LifeWaveLayout + Routing | — | Grundlage |
| 2 | Phase 1.2 — Glassmorphism CSS | — | Grundlage |
| 3 | Phase 3.1 — FloatingLines Fullscreen | #1 | Wow-Basis |
| 4 | Phase 2.1 — UserMenuButton | #1, #2 | Navigation |
| 5 | Phase 2.2 — AddEventButton | #1, #2 | Navigation |
| 6 | Phase 4.1 — EventPanel (Slide-Up, leer) | #2 | Panel |
| 7 | Datenmodell — Pinia Stores | — | Daten |
| 8 | Phase 3.2 — GlowDots | #3, #7 | Events |
| 9 | Phase 3.3 — LifeWavePath (Verbindungen) | #8 | Wave |
| 10 | Phase 4.2 — Event-Formular | #6, #7 | Eingabe |
| 11 | Phase 4.3 — Live-Feedback (Ghost-Dot) | #8, #10 | Wow! |
| 12 | Phase 5 — Event bearbeiten & Detail | #10, #8 | Edit |
| 13 | Phase 6.1 — LifeWave-Einstellungen | #3, #7 | Settings |
| 14 | Phase 6.2 — Dark/Light Mode | #1 | Theme |
---
## Demo-Daten für den Prototyp
8 Events vorbelegt — 4 mit Bildern, 4 ohne. Bilder liegen in `public/demo/`.
```js
;[
{ title: 'Erster Schultag', date: '1995-09-01', emotion: 0.6, image: null },
{
title: 'Abiball',
date: '2004-06-25',
emotion: 0.85,
image: 'demo/photo-1530103862676-de8c9debad1d.jpeg',
},
{ title: 'Trennung', date: '2010-03-15', emotion: -0.7, image: null },
{
title: 'Bergwanderung',
date: '2014-08-12',
emotion: 0.75,
image: 'demo/photo-1534067783941-51c9c23ecefd.jpeg',
},
{ title: 'Jobverlust', date: '2016-11-03', emotion: -0.6, image: null },
{
title: 'Hochzeit',
date: '2018-07-20',
emotion: 0.95,
customColor: '#E94FF5',
image: 'demo/photo-1506905925346-21bda4d32df4.jpeg',
},
{ title: 'Umzug', date: '2021-04-01', emotion: -0.3, image: null },
{
title: 'Neuer Job',
date: '2023-01-10',
emotion: 0.5,
image: 'demo/photo-1530103862676-de8c9debad1d.jpeg',
},
]
```
---
## Technische Hinweise
- **Three.js** ist bereits als Dependency vorhanden (über FloatingLines.vue)
- **Keine neuen Dependencies** nötig für Phase 1-5 (alles mit Quasar + CSS + SVG + Three.js machbar)
- **Performance:** GlowDots und LifeWavePath als separate Schicht ÜBER dem WebGL-Canvas (DOM, nicht WebGL) — einfacher zu implementieren, gute Performance bei <50 Events
- **Mobile-First:** Alle Maße in `dvh`/`dvw`, Touch-Events für Slider, Panel-Swipe