157 lines
8.1 KiB
Markdown
157 lines
8.1 KiB
Markdown
# Beraterkontakt (Simulation)
|
|
|
|
## Testseite starten
|
|
|
|
Wie bei der Buchung in drei Terminals starten:
|
|
|
|
```sh
|
|
npm run dev:mail
|
|
npm run dev:server
|
|
npm run dev
|
|
```
|
|
|
|
Öffne <http://localhost:5173/contact-test.html?berater-id=anna-mueller>.
|
|
Der Button öffnet ein modales Fenster. Gib eine E-Mail aus einer vorhandenen
|
|
Buchung in `src/server/data/bookings.csv` ein, wähle einen Kontaktgrund und
|
|
bestätige den Simulationshinweis. Beim Klick auf „Anfrage senden & Termin wählen“
|
|
prüft der Server die E-Mail und versendet nur bei vorhandener Buchung. Bei Bedarf zuerst
|
|
über die bestehende Angebotsseite eine Testbuchung anlegen.
|
|
|
|
Nach dem Absenden müssen zwei getrennte Nachrichten in
|
|
<http://localhost:8025> erscheinen: an die Kundenadresse und beispielsweise
|
|
`anna.mueller@tri-hub.de`. Der Browser wechselt anschließend zur vom Auftrag
|
|
vorgegebenen Microsoft-Bookings-Adresse. Es wird dort kein Termin automatisch
|
|
gebucht. Die Checkliste spricht von Microsoft Forms; umgesetzt ist der konkret
|
|
angegebene Bookings-Link.
|
|
|
|
## Checkliste
|
|
|
|
- [x] Kontaktgrund auswählbar: Coaching, Ernährungsplan, Wettkampfverpflegung,
|
|
Regeneration, Paketfragen, Termin und Sonstiges.
|
|
- [x] Getrennte Eingangsbestätigungen an Kunde und Berater, ausschließlich
|
|
simuliert über Mailpit, mit Kontaktgrund und Simulationshinweis.
|
|
- [x] Weiterleitung zur vorhandenen Microsoft-Bookings-Adresse nach Annahme
|
|
beider Nachrichten durch Mailpit; zusätzlicher Link als Rückfalloption.
|
|
- [x] Kontakt nur nach erfolgreichem E-Mail-Abgleich mit `bookings.csv`;
|
|
der Server prüft beim tatsächlichen Absenden erneut.
|
|
|
|
## Einbindung in Beraterprofile
|
|
|
|
Die Profilseite importiert `openContactDialog` aus
|
|
`src/features/contact/contact-dialog.js` und übergibt ausschließlich die ID:
|
|
|
|
```js
|
|
import { openContactDialog } from "./src/features/contact/contact-dialog.js";
|
|
|
|
button.addEventListener("click", () => {
|
|
openContactDialog({ advisorId: profile.id });
|
|
});
|
|
```
|
|
|
|
Den Importpfad relativ zur einbindenden Datei anpassen. Das Modul bringt die
|
|
Popup-Styles und die lokalen DM-Sans-Schriftdateien mit. Die vollständige
|
|
Einbauanleitung für die Profilseite steht in [contact-integration.md](contact-integration.md).
|
|
|
|
Die gemeinsame Datenquelle `src/shared/berater-daten.json` enthält ein Array
|
|
mit eindeutigen String-IDs und den Feldern `id`, `name`, `email`. Die beiden
|
|
vorhandenen Einträge sind Demo-Daten und können durch die tatsächlichen
|
|
Profildaten ersetzt werden. Zusätzliche Profilfelder sind möglich. Die Datei
|
|
wird im Frontend eingebunden: ausschließlich öffentliche Profildaten eintragen.
|
|
|
|
`src/shared/berater.js` stellt `findAdvisor(advisorId)` bereit. Popup und Server
|
|
verwenden dieselbe Zuordnung. Der Server holt die Empfängeradresse ausschließlich
|
|
aus dieser JSON; vom Browser gesendete Namen oder Empfängeradressen werden
|
|
nicht übernommen. E-Mail-Adressen müssen gültig sein und auf `@tri-hub.de`
|
|
enden. Eine unbekannte ID wird abgelehnt und sperrt das Absenden im Popup.
|
|
|
|
Die Testseite liest den URL-Parameter `berater-id`, zum Beispiel
|
|
`contact-test.html?berater-id=max-mustermann`. Ohne Parameter verwendet sie
|
|
`anna-mueller`. Nach Änderungen an der JSON den API-Server neu starten und für
|
|
das Deployment das Frontend neu bauen.
|
|
|
|
Das native `dialog` hält den Tastaturfokus im Popup. Escape und Schließen
|
|
bringen ihn zum auslösenden Button zurück. Während einer Anfrage ist Schließen
|
|
kurz gesperrt, damit der Versand nicht unbemerkt weiterläuft. Das Fenster ist
|
|
auf schmalen Bildschirmen scrollbar. Die E-Mail wird bei jedem Absenden geprüft;
|
|
ein separater Prüfbutton ist nicht erforderlich. Es gibt keine zusätzlichen
|
|
Laufzeitabhängigkeiten.
|
|
|
|
## API
|
|
|
|
Der vollständige OpenAPI-Vertrag steht in `src/server/swagger.json`.
|
|
Beide Endpunkte erwarten POST mit `Content-Type: application/json`, maximal
|
|
8 KiB. Fehler enthalten `error.code` und `error.message`.
|
|
|
|
| Endpunkt | Eingabe | Erfolg |
|
|
| ----------------------- | --------------------------------------------------- | ---------------------------------------------------------- |
|
|
| `/api/contact/validate` | `{ "email": "kunde@example.test" }` | 200: `{ "valid": true, "email": "kunde@example.test" }` |
|
|
| `/api/contact` | E-Mail, Berater-ID, Grund, Zustimmung (siehe unten) | 201: `simulated`, `emailStatus: "accepted"`, `redirectUrl` |
|
|
|
|
```json
|
|
{
|
|
"email": "kunde@example.test",
|
|
"advisorId": "anna-mueller",
|
|
"reason": "coaching",
|
|
"simulationAccepted": true
|
|
}
|
|
```
|
|
|
|
400 bedeutet ungültige Eingaben, 403 keine passende Buchung, 405 falsche Methode,
|
|
413 zu große Anfrage, 415 falscher Medientyp, 503 nicht lesbarer CSV-Speicher oder ungültige Beraterkontaktdaten.
|
|
502 bedeutet, dass mindestens eine Mailannahme fehlgeschlagen oder unklar ist;
|
|
der Browser leitet dann nicht weiter. 500 bezeichnet einen unerwarteten Fehler.
|
|
Die CSV wird ausschließlich gelesen und bleibt unverändert. Der separate
|
|
Validierungsendpunkt bleibt für API-Nutzer verfügbar; das Popup verwendet
|
|
ausschließlich `/api/contact` mit integrierter Kundenprüfung.
|
|
|
|
## Grenzen der Simulation
|
|
|
|
Der E-Mail-Abgleich ignoriert Groß-/Kleinschreibung und äußere Leerzeichen.
|
|
Er bestätigt einen Eintrag in der Buchungsdatei, nicht den Besitz des Postfachs.
|
|
Die Prüfantwort ist kein Anmeldetoken und gibt keine Buchungsdetails zurück.
|
|
Vor einem öffentlichen Produktiveinsatz wären eine Anmeldung oder Bestätigung
|
|
per E-Mail sowie ein Schutz vor automatisierten Adressabfragen erforderlich.
|
|
|
|
Kontaktmails verwenden fest `127.0.0.1:1025`, unabhängig von einer eventuell
|
|
externen SMTP-Konfiguration des Buchungsablaufs. Mailpit muss deshalb auf
|
|
demselben Host laufen. Kunden- und Berateradresse sind simulierte Empfänger;
|
|
es erfolgt kein externer Versand. SMTP-Annahme ist keine reale Zustellbestätigung.
|
|
|
|
Kontaktanfragen werden nicht dauerhaft gespeichert und haben keinen
|
|
Idempotenzschlüssel. Doppelklicks sind während des Versands gesperrt. Bei
|
|
Verbindungsabbrüchen oder Teilfehlern kann bereits eine Nachricht vorliegen:
|
|
vor manuellem Wiederholen Mailpit prüfen. Es gibt keinen automatischen Neuversand.
|
|
|
|
## Prüfungen
|
|
|
|
- `npm test`: API, CSV-Abgleich, erneute Validierung beim Absenden, ungültige
|
|
Eingaben, SMTP-Empfänger und Teilfehler; isolierte temporäre CSV-Dateien.
|
|
- `npm run test:browser`: vollständiger Ablauf einschließlich abgefangener
|
|
externer Weiterleitung, unbekannter Adresse, geänderter E-Mail, Versandfehler,
|
|
mobiler Darstellung, Fokus und Escape; zusätzlich bestehende Buchungstests.
|
|
- `npm run build` und `git diff --check`.
|
|
- Lokaler SMTP-Smoke-Test mit Mailpit: beide Empfänger und Simulationshinweis
|
|
in den empfangenen Nachrichten geprüft.
|
|
|
|
Chromium muss für Playwright installiert sein (`npx playwright install chromium`).
|
|
In dieser Arbeitsumgebung liegt der Testbrowser unter `/tmp/trihub-playwright`;
|
|
hier mit `PLAYWRIGHT_BROWSERS_PATH=/tmp/trihub-playwright npm run test:browser` starten.
|
|
Der globale Formatcheck hat bereits bestehende Abweichungen in `src/main.js`
|
|
und `src/components/navigationsbar/README.md`; die Kontaktdateien sind formatiert.
|
|
Der bestehende Gesamt-Build meldet außerdem fehlende ältere Schriftdateien aus
|
|
dem globalen Stylesheet. Das Kontakt-Popup verwendet eigene lokale Schriftdateien.
|
|
|
|
### Ergebnis dieser Umsetzung
|
|
|
|
31 API-/Servicetests und alle vier Kontakt-Browsertests bestanden.
|
|
Build, lokale Mailpit-Prüfung und Formatierung der geänderten Dateien bestanden.
|
|
Die bestehenden Buchungs-Browsertests sind teilweise nicht mehr an das schon
|
|
vorhandene Buchungs-Popup angepasst: Sie suchen Formularfelder, ohne vorher
|
|
„Jetzt buchen“ zu klicken. Weitere Bestandsfälle erwarten einen nicht mehr vorhandenen Startseiten-Link
|
|
oder eine Seitennavigation, wo bereits ein Popup geöffnet wird. Beim ursprünglichen Gesamtlauf bestanden 7 von 15 Browsertests; die 8 Fehler
|
|
betrafen ausschließlich die unveränderten Buchungstests. Die gezielten
|
|
Kontakttests werden nach Anpassungen separat ausgeführt.
|
|
`git diff --check` ist für die eigenen Änderungen sauber; die zuvor bereits
|
|
geänderte `bookings.csv` erzeugt separat CRLF-Whitespace-Hinweise und wurde
|
|
von dieser Umsetzung nicht verändert.
|