372 lines
14 KiB
Markdown
372 lines
14 KiB
Markdown
# 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.4–3.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
|