Frontend: Preisoptionen in Formular-Entscheidungsoptionen (Radio/Checkbox) #135

Closed
opened 2026-06-28 14:43:35 +02:00 by niboer · 1 comment
Owner

Beschreibung

Nach dem Backend-Issue #134 (openapi.yaml-Schema) muessen die UI-Komponenten um radio- und checkbox-Felder mit bepreisten Optionen erweitert werden.

Preis-Format: Integer-Cents (15000 = EUR 150,00). Umrechnung in UI via formatEuro(cents / 100).

Aenderungen

1. Orval-Typen regenerieren

  • npm run generate:api ausfuehren (nach #134)

2. FormEditor (form-editor.svelte)

  • Neue Feld-Typen radio und checkbox im Type-Dropdown
  • Options-Editor: pro Option ein label-Input + price-Input (Euro, Umrechnung cents ↔ Euro)
  • Add/Remove-Buttons fuer Optionen innerhalb eines Felds
  • Serialisierung: options als Array<{ label, price: number }> (price in cents)
  • Bestehende select-Optionen bleiben comma-separated strings

3. Gaeste-Formular (persons/[personId]/+page.svelte)

  • Render radio als Radio-Button-Gruppe mit Preisangabe
  • Render checkbox als Checkbox-Gruppe mit Preisangabe
  • Preisberechnung (Summe der ausgewaehlten Optionen in Cent)
  • Gesamtsummen-Anzeige (formatiert via formatEuro)
  • Antwort-Format: radio → String (Label), checkbox → String[] (Labels)

4. Gaeste-Server (persons/[personId]/+page.server.ts)

  • saveDraft/submitFinal: Checkbox-Arrays aus mehreren FormData-Eintraegen mit gleichem Namen verarbeiten

5. Organisator-Ansicht (events/[eventId]/+page.svelte)

  • formatFormAnswers(): Preise pro Option und Gesamtsumme anzeigen
  • Override-Dialog: radio/checkbox mit Price-Display rendern

6. Organisator-Server (events/[eventId]/+page.server.ts)

  • overrideForm: Checkbox-Arrays aus FormData verarbeiten

7. Tests

  • FormEditor erzeugt korrekte Cent-Preise
  • Gaeste-Formular berechnet Gesamtsumme korrekt
  • formatFormAnswers zeigt Preise und Summe
  • Override mit Radio/Checkbox

Referenzen

  • Backend-Issue #134 (Schema-Definition)
  • Gehoert zu MS-FE-4 (#104)
## Beschreibung Nach dem Backend-Issue #134 (openapi.yaml-Schema) muessen die UI-Komponenten um `radio`- und `checkbox`-Felder mit bepreisten Optionen erweitert werden. **Preis-Format:** Integer-Cents (15000 = EUR 150,00). Umrechnung in UI via `formatEuro(cents / 100)`. ### Aenderungen #### 1. Orval-Typen regenerieren - `npm run generate:api` ausfuehren (nach #134) #### 2. FormEditor (`form-editor.svelte`) - Neue Feld-Typen `radio` und `checkbox` im Type-Dropdown - Options-Editor: pro Option ein `label`-Input + `price`-Input (Euro, Umrechnung cents ↔ Euro) - Add/Remove-Buttons fuer Optionen innerhalb eines Felds - Serialisierung: `options` als `Array<{ label, price: number }>` (price in cents) - Bestehende `select`-Optionen bleiben comma-separated strings #### 3. Gaeste-Formular (`persons/[personId]/+page.svelte`) - Render `radio` als Radio-Button-Gruppe mit Preisangabe - Render `checkbox` als Checkbox-Gruppe mit Preisangabe - Preisberechnung (Summe der ausgewaehlten Optionen in Cent) - Gesamtsummen-Anzeige (formatiert via `formatEuro`) - Antwort-Format: `radio` → String (Label), `checkbox` → String[] (Labels) #### 4. Gaeste-Server (`persons/[personId]/+page.server.ts`) - `saveDraft`/`submitFinal`: Checkbox-Arrays aus mehreren FormData-Eintraegen mit gleichem Namen verarbeiten #### 5. Organisator-Ansicht (`events/[eventId]/+page.svelte`) - `formatFormAnswers()`: Preise pro Option und Gesamtsumme anzeigen - Override-Dialog: `radio`/`checkbox` mit Price-Display rendern #### 6. Organisator-Server (`events/[eventId]/+page.server.ts`) - `overrideForm`: Checkbox-Arrays aus FormData verarbeiten #### 7. Tests - FormEditor erzeugt korrekte Cent-Preise - Gaeste-Formular berechnet Gesamtsumme korrekt - formatFormAnswers zeigt Preise und Summe - Override mit Radio/Checkbox ### Referenzen - Backend-Issue #134 (Schema-Definition) - Gehoert zu MS-FE-4 (#104)
Author
Owner

Detailplan (aus Code-Analyse)

1. Orval-Typen regenerieren

  • cd frontend && npm run generate:api (nach #134 openapi.yaml-Aenderung)
  • Pruefen: neue generierte Typen in frontend/src/lib/api/generated.ts

2. FormEditor (frontend/src/lib/components/form-editor.svelte)

  • Lokales Interface FormFieldOption mit label: string, price: number (Cent)
  • FormField.options-Typ aendern: string | FormFieldOption[] (select=string, radio/checkbox=Array)
  • Type-Dropdown um radio und checkbox erweitern
  • Bepreister Options-Editor: pro Option label-Input + price-Input (Euro, Umrechnung cents ↔ Euro)
    • Eingabe als Euro (12.50), Speicherung in Cent (1250)
    • Anzeige aus Cent-Daten: (price / 100).toFixed(2)
  • Add/Remove-Buttons fuer Optionen innerhalb eines Felds
  • Serialisierung in handleSave():
    • select bleibt options: string[]
    • radio/checkboxoptions: [{ label, price }] (price in integer Cent)

3. Gaeste-Formular (frontend/src/routes/app/persons/[personId]/+page.svelte)

  • formValues-Typ von Record<string, string> auf Record<string, string | string[]> aendern
  • radio-Feld rendern: <input type="radio">-Gruppe mit formatEuro(price / 100) pro Option
  • checkbox-Feld rendern: <input type="checkbox">-Gruppe mit Preisangabe, Gesamtsumme dynamisch berechnen
  • formatEuro(cents)-Hilfsfunktion lokal definieren: (cents / 100).toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })
  • Hidden-Inputs in saveDraft/submitFinal: checkbox → mehrere <input type="hidden"> mit gleichem name

4. Gaeste-Server (frontend/src/routes/app/persons/[personId]/+page.server.ts)

  • saveDraft: FormData-Eintraege sammeln — wenn Key mehrfach vorkommt → string[], sonst string
  • submitFinal: Gleiche Logik wie saveDraft fuer Checkbox-Arrays

5. Organisator-Ansicht (frontend/src/routes/app/events/[eventId]/+page.svelte)

  • formatFormAnswers(): Bei radio/checkbox Preise pro Option und Gesamtsumme anzeigen
    • Format: "Frühstueck: 15,00 €, Parkplatz: 10,00 € (Gesamt: 25,00 €)"
  • overrideValues-Typ: Record<string, string | string[]>
  • openOverride(): Checkbox-Werte als string[] laden
  • Override-Dialog: radio als Radio-Gruppe, checkbox als Checkbox-Gruppe mit Price-Display

6. Organisator-Server (frontend/src/routes/app/events/[eventId]/+page.server.ts)

  • overrideForm-Action: FormData-Eintraege mit Mehrfachwerten als string[] sammeln

7. Tests (frontend/src/tests/)

  • FormEditor erzeugt korrekte Cent-Preise (neue Testdatei oder in events.test.ts)
  • Guest-Formular berechnet Gesamtsumme korrekt
  • Server-Actions verarbeiten Checkbox-Arrays
  • formatFormAnswers zeigt Preise und Summe
  • Override mit Radio/Checkbox

Hinweise

  • Preis-Format: Integer-Cents (15000 = EUR 150,00). Umrechnung in UI via formatEuro(cents / 100)
  • Antwort-Format: radio → String (Label), checkbox → String[] (Labels)
  • Keine Backend-Aenderung noetig: formDefinition ist JSONB, Backend speichert/laedt ohne Interpretation
  • Abhaengig von #133 (openapi.yaml-Aktualisierung)
## Detailplan (aus Code-Analyse) ### 1. Orval-Typen regenerieren - `cd frontend && npm run generate:api` (nach #134 openapi.yaml-Aenderung) - Pruefen: neue generierte Typen in `frontend/src/lib/api/generated.ts` ### 2. FormEditor (`frontend/src/lib/components/form-editor.svelte`) - [ ] Lokales Interface `FormFieldOption` mit `label: string, price: number` (Cent) - [ ] `FormField.options`-Typ aendern: `string | FormFieldOption[]` (select=string, radio/checkbox=Array) - [ ] Type-Dropdown um `radio` und `checkbox` erweitern - [ ] Bepreister Options-Editor: pro Option `label`-Input + `price`-Input (Euro, Umrechnung cents ↔ Euro) - Eingabe als Euro (`12.50`), Speicherung in Cent (`1250`) - Anzeige aus Cent-Daten: `(price / 100).toFixed(2)` - [ ] Add/Remove-Buttons fuer Optionen innerhalb eines Felds - [ ] Serialisierung in `handleSave()`: - `select` bleibt `options: string[]` - `radio`/`checkbox` → `options: [{ label, price }]` (price in integer Cent) ### 3. Gaeste-Formular (`frontend/src/routes/app/persons/[personId]/+page.svelte`) - [ ] `formValues`-Typ von `Record<string, string>` auf `Record<string, string | string[]>` aendern - [ ] `radio`-Feld rendern: `<input type="radio">`-Gruppe mit `formatEuro(price / 100)` pro Option - [ ] `checkbox`-Feld rendern: `<input type="checkbox">`-Gruppe mit Preisangabe, Gesamtsumme dynamisch berechnen - [ ] `formatEuro(cents)`-Hilfsfunktion lokal definieren: `(cents / 100).toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })` - [ ] Hidden-Inputs in saveDraft/submitFinal: checkbox → mehrere `<input type="hidden">` mit gleichem `name` ### 4. Gaeste-Server (`frontend/src/routes/app/persons/[personId]/+page.server.ts`) - [ ] `saveDraft`: FormData-Eintraege sammeln — wenn Key mehrfach vorkommt → `string[]`, sonst `string` - [ ] `submitFinal`: Gleiche Logik wie saveDraft fuer Checkbox-Arrays ### 5. Organisator-Ansicht (`frontend/src/routes/app/events/[eventId]/+page.svelte`) - [ ] `formatFormAnswers()`: Bei radio/checkbox Preise pro Option und Gesamtsumme anzeigen - Format: `"Frühstueck: 15,00 €, Parkplatz: 10,00 € (Gesamt: 25,00 €)"` - [ ] `overrideValues`-Typ: `Record<string, string | string[]>` - [ ] `openOverride()`: Checkbox-Werte als `string[]` laden - [ ] Override-Dialog: `radio` als Radio-Gruppe, `checkbox` als Checkbox-Gruppe mit Price-Display ### 6. Organisator-Server (`frontend/src/routes/app/events/[eventId]/+page.server.ts`) - [ ] `overrideForm`-Action: FormData-Eintraege mit Mehrfachwerten als `string[]` sammeln ### 7. Tests (`frontend/src/tests/`) - [ ] FormEditor erzeugt korrekte Cent-Preise (neue Testdatei oder in events.test.ts) - [ ] Guest-Formular berechnet Gesamtsumme korrekt - [ ] Server-Actions verarbeiten Checkbox-Arrays - [ ] formatFormAnswers zeigt Preise und Summe - [ ] Override mit Radio/Checkbox ### Hinweise - **Preis-Format:** Integer-Cents (15000 = EUR 150,00). Umrechnung in UI via `formatEuro(cents / 100)` - **Antwort-Format:** `radio` → String (Label), `checkbox` → String[] (Labels) - **Keine Backend-Aenderung noetig:** formDefinition ist JSONB, Backend speichert/laedt ohne Interpretation - **Abhaengig von #133 (openapi.yaml-Aktualisierung)**
Sign in to join this conversation.
No description provided.