# Feature: Preview-Bilder für Galerie

**Branch:** `feature/preview-images`  
**Datum:** 29. Oktober 2025

## 🎯 Ziel

Generierung und Verwendung von optimierten Preview-Bildern (Thumbnails) für Galerie-Ansichten, um:
- Ladezeiten drastisch zu reduzieren
- Bandbreite zu sparen
- User Experience zu verbessern
- Mobile Performance zu optimieren

---

## 📐 Architektur-Überblick

### Aktuelle Situation
- Bilder werden in voller Auflösung in Galerien geladen
- Path: `backend/src/data/images/` (Original-Bilder)
- Keine Thumbnails oder Preview-Varianten

### Ziel-Architektur
```
backend/src/data/
├── images/          # Original-Bilder (unverändert)
│   └── X_JeZj0TsQ.JPG
└── previews/        # NEU: Preview-Bilder (optimiert)
    └── X_JeZj0TsQ.JPG  (oder .webp)
```

### Thumbnail-Spezifikationen
- **Größe:** Max. 800px Breite (beibehält Aspect Ratio)
- **Format:** JPEG (85% Qualität) oder WebP (falls unterstützt)
- **Verwendung:** Galerie-Views (GroupsOverviewPage, ModerationGroupsPage)
- **Original:** Slideshow-View und Download behalten Original-Bilder

---

## 🔧 Technische Implementierung

### Backend: Sharp Library
**Warum Sharp?**
- Schnell (nutzt libvips)
- Unterstützt JPEG, PNG, WebP
- Läuft in Node.js ohne externe Binaries
- Unterstützt Resize, Optimize, Format-Konvertierung

**Installation:**
```bash
npm install sharp --save
```

### Datenbankschema-Erweiterung
```sql
-- Erweitere images Tabelle um preview_path
ALTER TABLE images ADD COLUMN preview_path TEXT;

-- Index für schnelle Abfragen
CREATE INDEX IF NOT EXISTS idx_images_preview_path ON images(preview_path);
```

---

## 📋 Implementierungs-Phasen

### Phase 1: Backend - Preview-Generierung (6-10h)

#### 1.1 Service-Layer erstellen
**Datei:** `backend/src/services/ImagePreviewService.js`

**Funktionen:**
- `generatePreview(originalPath, outputPath, options)` - Generiert einzelnes Preview
- `generatePreviewsForGroup(groupId)` - Batch-Generierung für Upload-Gruppe
- `cleanupOrphanedPreviews()` - Entfernt nicht mehr verwendete Previews
- `getPreviewPath(originalFileName)` - Gibt Preview-Pfad zurück

**Optionen:**
```javascript
{
  width: 800,           // Max-Breite in px
  quality: 85,          // JPEG-Qualität
  format: 'jpeg',       // 'jpeg' oder 'webp'
  withoutEnlargement: true  // Keine Vergrößerung kleiner Bilder
}
```

#### 1.2 Upload-Route erweitern
**Datei:** `backend/src/routes/upload.js` & `backend/src/routes/batchUpload.js`

- Nach erfolgreichem Upload: Preview-Generierung triggern
- Preview-Pfad in DB speichern
- Fehlerbehandlung: Bei Preview-Fehler Upload trotzdem erfolgreich

#### 1.3 DB-Schema Migration
**Datei:** `backend/src/database/migrations/003_add_preview_path.sql` (NEU)

```sql
-- Migration 003: Add preview_path column
ALTER TABLE images ADD COLUMN preview_path TEXT;
CREATE INDEX IF NOT EXISTS idx_images_preview_path ON images(preview_path);
```

**Datei:** `backend/src/database/DatabaseManager.js`
- Erweitere `initDatabase()` um Migration-Support
- Auto-run Migrations beim Start

#### 1.4 API-Endpunkte erweitern
**Bestehende Endpoints anpassen:**
- `GET /groups` - Rückgabe mit `previewPath` für jedes Bild
- `GET /groups/:groupId` - Rückgabe mit `previewPath`
- `GET /moderation/groups` - Rückgabe mit `previewPath`

**Neue Endpoints (optional):**
- `POST /groups/:groupId/regenerate-previews` - Regeneriert Previews für Gruppe
- `GET /previews/:fileName` - Serve Preview-Bilder (analog zu `/upload/:fileName`)

#### 1.5 Constants & Config
**Datei:** `backend/src/constants.js`

```javascript
const PREVIEW_FS_DIR = 'data/previews';
const PREVIEW_CONFIG = {
  width: 800,
  quality: 85,
  format: 'jpeg'
};
```

---

### Phase 2: Backend - Batch-Migration bestehender Bilder (2-4h)

#### 2.1 Migration-Script
**Datei:** `backend/src/scripts/generatePreviewsForExisting.js`

- Liest alle Bilder aus DB ohne `preview_path`
- Generiert Previews für alle bestehenden Bilder
- Aktualisiert DB mit Preview-Pfaden
- Progress-Logging

**Ausführung:**
```bash
node backend/src/scripts/generatePreviewsForExisting.js
```

Oder als Express-Endpoint für Admin:
- `POST /admin/migrate-previews` (mit Basic Auth)

---

### Phase 3: Frontend - Preview-Nutzung (3-6h)

#### 3.1 API-Response erweitern
**Typ-Definitionen (optional):**
```typescript
interface Image {
  id: number;
  fileName: string;
  originalName: string;
  filePath: string;        // Original-Bild
  previewPath?: string;    // NEU: Preview-Bild
  uploadOrder: number;
  fileSize: number;
  mimeType: string;
}
```

#### 3.2 Component Updates
**Dateien zu ändern:**
- `frontend/src/Components/ComponentUtils/GroupCard.js`
- `frontend/src/Components/Pages/GroupsOverviewPage.js`
- `frontend/src/Components/Pages/ModerationGroupsPage.js`

**Logik:**
```javascript
const imageSrc = image.previewPath || image.filePath;
// Fallback auf Original, falls Preview fehlt
```

#### 3.3 Slideshow beibehält Original
**Datei:** `frontend/src/Components/Pages/SlideshowPage.js`
- **Keine Änderung** - Slideshow nutzt weiterhin `filePath` (Original)

---

### Phase 4: Testing & Optimierung (2-4h)

#### 4.1 Unit Tests
- `ImagePreviewService.test.js` - Service-Logik
- Test mit verschiedenen Bildformaten (JPEG, PNG)
- Error-Handling Tests

#### 4.2 Integration Tests
- Upload → Preview-Generierung → DB-Update
- API-Response enthält `previewPath`
- Frontend lädt Preview-Bilder

#### 4.3 Performance-Messung
- Vergleich Ladezeiten: Original vs. Preview
- Bundle-Size (Sharp Library Impact)
- Memory-Usage bei Batch-Generierung

#### 4.4 Cleanup & Docs
- `README.md` Update mit Preview-Feature
- `CHANGELOG.md` Eintrag
- Code-Kommentare & JSDoc

---

## ⏱️ Zeitschätzung

| Phase | Aufgabe | Geschätzt |
|-------|---------|-----------|
| 1.1 | ImagePreviewService | 2-3h |
| 1.2 | Upload-Route erweitern | 1-2h |
| 1.3 | DB-Migration | 1h |
| 1.4 | API-Endpoints | 1-2h |
| 1.5 | Config/Constants | 0.5h |
| 2.1 | Batch-Migration Script | 2-4h |
| 3.1-3.3 | Frontend Updates | 3-6h |
| 4.1-4.4 | Testing & Docs | 2-4h |
| **Gesamt** | | **12-22h** |

**Realistische Schätzung:** 2-3 Arbeitstage

---

## 🚀 Deployment-Strategie

### Schritt 1: Backend-Deploy mit Preview-Generierung
- Deploy neuer Backend-Code
- DB-Migration läuft automatisch beim Start
- Neue Uploads erhalten automatisch Previews

### Schritt 2: Batch-Migration (einmalig)
```bash
docker exec image-uploader-backend node src/scripts/generatePreviewsForExisting.js
```
oder via Admin-Endpoint

### Schritt 3: Frontend-Deploy
- Deploy Frontend mit Preview-Support
- Fallback auf Original-Bilder bleibt aktiv

### Rollback-Plan
- Preview-Feature ist opt-in (Fallback auf `filePath`)
- Bei Problemen: Frontend-Rollback ohne Backend-Änderung nötig

---

## 📊 Erwartete Verbesserungen

### Dateigrößen (Beispiel)
- **Original JPEG (3000x2000px):** ~2-3 MB
- **Preview JPEG (800x533px, 85%):** ~80-150 KB
- **Einsparung:** ~95%

### Ladezeiten (Galerie mit 20 Bildern)
- **Vorher:** 20 × 2.5 MB = 50 MB
- **Nachher:** 20 × 100 KB = 2 MB
- **Verbesserung:** ~96% schneller

---

## ⚠️ Risiken & Mitigation

### Risiko 1: Sharp Build-Fehler in Docker
**Mitigation:** 
- Alpine-kompatible Sharp-Version testen
- Falls nötig: `python3`, `make`, `g++` in Dockerfile hinzufügen

### Risiko 2: Disk-Space Verdopplung
**Mitigation:**
- Previews sind ~5% der Original-Größe
- Cleanup-Script für verwaiste Previews
- Optional: alte Previews nach X Tagen löschen

### Risiko 3: CPU-Last bei Batch-Migration
**Mitigation:**
- Batch-Processing mit Chunk-Size (z.B. 10 Bilder parallel)
- Progress-Logging
- Optional: Background-Job Queue (Bull, Agenda)

---

## 🔄 Zukünftige Erweiterungen

- **WebP-Support:** Kleinere Dateien, bessere Compression
- **Responsive Previews:** Mehrere Größen (400px, 800px, 1200px)
- **Lazy-Loading:** Intersection Observer für On-Demand-Loading
- **CDN-Integration:** Previews auf S3/CloudFront auslagern
- **Image-Optimization:** Auto-Rotation (EXIF), Strip Metadata

---

## 📝 Acceptance Criteria

- [ ] Neue Uploads generieren automatisch Previews
- [ ] Bestehende Bilder haben Previews nach Migration
- [ ] Galerie-Views laden Preview-Bilder (keine Originals)
- [ ] Slideshow lädt weiterhin Original-Bilder
- [ ] API liefert sowohl `filePath` als auch `previewPath`
- [ ] Fallback auf Original funktioniert, wenn Preview fehlt
- [ ] Ladezeit-Verbesserung messbar (>80%)
- [ ] Tests bestehen (Unit + Integration)
- [ ] Dokumentation aktualisiert

---

**Erstellt am:** 29. Oktober 2025  
**Zuletzt aktualisiert:** 29. Oktober 2025
