add component_inventory.md with legal pages, MietanfragePage, extended AdminPage

This commit is contained in:
2026-07-08 06:58:28 +00:00
parent 15e90041b9
commit 88aa4a9413
+210
View File
@@ -0,0 +1,210 @@
# 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)`