Files
hms-licht-ton/docs/component_inventory.md

211 lines
11 KiB
Markdown
Raw Permalink 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.
# HMS Licht & Ton Component Inventory
## Overview
All components are built as Vue 3 single-file components (template + setup). In production (Nuxt 3), these map to `.vue` files in `components/` and `pages/` directories.
## Shared Components
### HmsLogo
- **Purpose:** SVG logo with white HMS text + orange (#EC6925) rectangular border
- **Props:** `size` (Number, default: 40)
- **States:** Default only (static SVG)
- **Accessibility:** `aria-label`, `role="img"`
### SpeakerIcon
- **Purpose:** SVG loudspeaker/light icon for equipment grid
- **Props:** `type` (String: linearray, subwoofer, monitor, pointsource, column, movinghead)
- **States:** Default (gray), Hover (orange via parent CSS)
- **Accessibility:** `aria-hidden="true"`
### AppHeader
- **Purpose:** Sticky navigation header with logo, desktop nav, mobile hamburger menu
- **States:** Default, Active nav item (`aria-current="page"`), Mobile menu open/closed
- **Accessibility:** `role="banner"`, `aria-label`, `aria-expanded`, `aria-controls`
### AppFooter
- **Purpose:** 4-column footer with company info, navigation, contact, legal links
- **States:** Default only
- **Accessibility:** `role="contentinfo"`
### ServiceCard
- **Purpose:** Service offering card with icon, title, description
- **Props:** `icon`, `title`, `description`
- **States:** Default, Hover (border highlight)
### EquipmentCard
- **Purpose:** Equipment listing card with image, badge, name, description, add-to-cart button
- **Props:** `item` (Object: id, code, name, category, description, brand, image)
- **Emits:** `click`, `add-to-cart`
- **States:** Default, Hover (border + shadow + lift), Focus (keyboard), No image (placeholder)
- **Accessibility:** `role="article"`, `tabindex="0"`, `aria-label` on add button
### LoadingSkeleton
- **Purpose:** Shimmer animation skeleton cards for loading states
- **Props:** `count` (Number, default: 6)
- **States:** Shimmer animation (infinite)
- **Accessibility:** `aria-live="polite"`, `aria-busy="true"`
### EmptyState
- **Purpose:** Empty state with icon, title, message, optional CTA button
- **Props:** `icon`, `title`, `message`, `actionLabel`
- **Emits:** `action`
- **States:** Default
- **Accessibility:** `role="status"`
### ErrorState
- **Purpose:** Error state with alert icon, title, message, retry button
- **Props:** `title`, `message`
- **Emits:** `retry`
- **States:** Default
- **Accessibility:** `role="alert"`
### LegalContentPage
- **Purpose:** Reusable layout for static legal content pages (Impressum, Datenschutz, AGB)
- **Props:** `title` (String), `content` (String/HTML)
- **States:** loading (skeleton), content (rendered)
- **Accessibility:** `role="article"`, semantic heading structure h1 > h2 > h3
## Page Components
### HomePage (`#/`)
- **Sections:** Hero (bg image + overlay), Speaker Grid (6 types), Über uns (stats + image), 8 Service Cards, Mietkatalog CTA
- **States:** Default (all content static)
### ReferenzenPage (`#/referenzen`)
- **States:** Loading (skeleton), Loaded (gallery grid), Error (retry), Empty (no category results)
- **Features:** Category filter chips (Alle, Open-Air, Indoor, Rigging, Event), 9 real HMS photos
### KontaktPage (`#/kontakt`)
- **Sections:** Büro/Lager/Öffnungszeiten cards, 2 Ansprechpartner cards, Contact form
- **Form States:** Default, Validation errors (inline), Submitting (spinner), Submitted (success message)
- **Validation:** Name*, Email* (regex), Message*, Privacy checkbox*
### MietkatalogPage (`#/mietkatalog`)
- **States:** Loading (skeleton), Loaded (equipment grid), Error (retry), Empty (no search results)
- **Features:** Search input, Category filter chips (7 categories), Sort dropdown (name/brand/code), Result count
### EquipmentDetailPage (`#/mietkatalog/:id`)
- **States:** Loading (skeleton), Loaded (detail view), Error (not found)
- **Sections:** Image/placeholder, Specs table, Rental form (date range + quantity), Related items grid
- **Form:** Mietbeginn, Mietende, Anzahl (stepper), Add to cart button
### WarenkorbPage (`#/warenkorb`)
- **States:** Empty (no items), Cart with items
- **Features:** Item list with quantity steppers, remove buttons, rental dates display, CTA button → /mietanfrage
- **Note:** Warenkorb verwaltet nur Items (anzeigen, Mengen steuern, entfernen). Kein Formular für Kontaktdaten hier.
- **Accessibility:** Cart summary with live-updating totals, `aria-live="polite"`
### MietanfragePage (`#/mietanfrage`)
- **Purpose:** Mietanfrage-Formular mit Veranstaltungsdaten + Kontaktdaten + Nachricht. Submit sendet an Rentman via POST /projectrequests + POST /projectrequests/{id}/projectrequestequipment.
- **Sections:**
1. **Warenkorb-Übersicht:** Zeigt ausgewählte Artikel mit Mengen (read-only), Link zurück zum Warenkorb
2. **Veranstaltungsdaten:** Name*, Datum von*, Datum bis*, Ort*, Anzahl Personen
3. **Kontaktdaten:** Name*, Firma, E-Mail*, Telefon, Adresse (Straße, PLZ, Ort)
4. **Nachricht:** Freitext-Nachrichtfeld
5. **Submit:** "Mietanfrage absenden" Button
- **States:**
- `form` Default, Formular leer oder mit Validierungs-Hinweisen
- `validation-error` Inline-Validierungsfehler (Pflichtfelder markiert, Fehlermeldungen unter den Feldern)
- `submitting` Spinner im Submit-Button, Felder disabled
- `success` Erfolgsmeldung mit Referenz-Nummer, Weiter-Button ("Zurück zur Startseite")
- `error` Fehlermeldung mit Retry-Button ("Erneut versuchen")
- **Empty Cart Handling:** Wenn Warenkorb leer → Hinweis "Keine Artikel ausgewählt" + Link zum Mietkatalog
- **Validation:**
- Veranstaltungsname: Pflicht, min 3 Zeichen
- Datum von/bis: Pflicht, von ≤ bis
- Ort: Pflicht
- Name: Pflicht, min 2 Zeichen
- E-Mail: Pflicht, Regex-Validierung
- Telefon: Optional, Format-Validierung
- Adresse: Optional (aber wenn PLZ angegeben, auch Ort erforderlich)
- **Accessibility:** `role="form"`, `aria-invalid` on error fields, `aria-describedby` for error messages, fieldset/legend for grouped sections
### AdminPage (`#/admin`)
- **Purpose:** Admin-Login und post-login Dashboard mit Equipment-Sync-Trigger
- **States:**
- `login` Login-Form (Username + Password), Fehler bei falschen Daten
- `idle` Post-Login Dashboard, Sync-Status sichtbar, Sync-Button bereit
- `syncing` Sync läuft, Progress-Indicator, Sync-Log live aktualisiert
- `sync-complete` Sync abgeschlossen, Status aktualisiert (last sync date, article count), Erfolgsmeldung
- `sync-error` Sync fehlgeschlagen, Fehlermeldung + Retry-Button, Sync-Log zeigt Fehlerdetails
- **Elements:**
- **Sync-Trigger Button:** "Equipment-Sync starten" (Primary, disabled während syncing)
- **Sync-Status:** Last sync date, article count, Sync-Status-Badge (idle/syncing/complete/error)
- **Sync-Log Viewer:** Scrollbarer Log-Bereich mit Zeitstempeln, kollabierbar
- **Login-Form States:** Default, Validation error (invalid credentials), Loading (spinner)
- **Accessibility:** `role="main"`, `aria-live="polite"` für Sync-Status, `aria-busy` während syncing
### ImpressumPage (`#/impressum`)
- **Purpose:** Statische Impressum-Seite mit rechtlichen Angaben gemäß §5 TMG
- **Route:** `/impressum`
- **Content:** Firmenname, Vertretungsberechtigte, Anschrift, Kontakt, USt-IdNr., Verantwortlich für Inhalte
- **States:** loading (skeleton), content (rendered)
- **Component:** Verwendet `LegalContentPage` Layout
- **Accessibility:** Semantic heading structure h1 > h2
### DatenschutzPage (`#/datenschutz`)
- **Purpose:** Statische Datenschutz-Seite mit DSGVO-konformer Datenschutzerklärung
- **Route:** `/datenschutz`
- **Content:** Server-Logfiles, Cookies, Kontaktformular-Datenverarbeitung, Rentman-Datenverarbeitung, Nutzerrechte
- **States:** loading (skeleton), content (rendered)
- **Component:** Verwendet `LegalContentPage` Layout
- **Accessibility:** Semantic heading structure h1 > h2 > h3
### AGBVermietungPage (`#/agb-vermietung`)
- **Purpose:** Statische AGB-Seite für Vermietung
- **Route:** `/agb-vermietung`
- **Content:** Allgemeine Geschäftsbedingungen für Vermietung (vom User bereitgestellter Text)
- **States:** loading (skeleton), content (rendered)
- **Component:** Verwendet `LegalContentPage` Layout
- **Accessibility:** Semantic heading structure h1 > h2
### NotFoundPage (`#/404`)
- **States:** Default (404 message + home link)
## UX State Coverage Summary
| Page | Loading | Empty | Error | Partial | Success | Additional States |
|------|---------|-------|-------|---------|---------|------------------|
| Home | | | | | | |
| Referenzen | Skeleton | No category | Retry | Filtered | | |
| Kontakt | | | | | Form sent | validation-error |
| Mietkatalog | Skeleton | No results | Retry | Filtered | | |
| Detail | Skeleton | | Not found | | | |
| Warenkorb | | Empty cart | | | | |
| Mietanfrage | | Empty cart | Retry | | Request sent | form, submitting, validation-error |
| Admin | Spinner | | Login error | | Logged in | idle, syncing, sync-complete, sync-error |
| Impressum | Skeleton | | | | | content |
| Datenschutz | Skeleton | | | | | content |
| AGB Vermietung | Skeleton | | | | | content |
| 404 | | | | | | |
## Component States Documentation
### Button States
- **Default:** `background: var(--color-accent); color: white`
- **Hover:** `background: var(--color-accent-hover)`
- **Active:** `transform: translateY(0)`
- **Disabled:** `background: var(--secondary); cursor: not-allowed`
- **Focus-visible:** `outline: 2px solid var(--color-accent); outline-offset: 2px`
### Input States
- **Default:** `border: 1px solid var(--border-strong); background: var(--surface)`
- **Focus:** `border-color: var(--color-accent); box-shadow: 0 0 0 2px rgba(236,105,37,0.1)`
- **Error:** `border-color: var(--color-error)`
- **Disabled:** `background: var(--row); color: var(--secondary); cursor: not-allowed`
### Card States
- **Default:** `border: 1px solid var(--border); box-shadow: var(--shadow-sm)`
- **Hover:** `border-color: var(--secondary); box-shadow: var(--shadow-lg)`
### Chip States
- **Default:** `border: 1px solid var(--border-strong); background: var(--surface)`
- **Hover:** `border-color: var(--secondary)`
- **Active:** `background: var(--color-accent); color: white; border-color: var(--color-accent)`
### Sync-Status Badge States (AdminPage)
- **Idle:** `background: var(--surface); color: var(--text-muted)`
- **Syncing:** `background: rgba(96, 165, 250, 0.08); color: var(--color-info); animation: pulse`
- **Complete:** `background: var(--color-success-bg); color: var(--color-success)`
- **Error:** `background: var(--color-error-bg); color: var(--color-error)`