8.1 KiB
Beraterkontakt (Simulation)
Testseite starten
Wie bei der Buchung in drei Terminals starten:
npm run dev:mail
npm run dev:server
npm run dev
Öffne http://localhost:5173/contact-test.html?berater-id=relindis-agethen.
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
relindis.agethen@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
- Kontaktgrund auswählbar: Coaching, Ernährungsplan, Wettkampfverpflegung, Regeneration, Paketfragen, Termin und Sonstiges.
- Getrennte Eingangsbestätigungen an Kunde und Berater, ausschließlich simuliert über Mailpit, mit Kontaktgrund und Simulationshinweis.
- Weiterleitung zur vorhandenen Microsoft-Bookings-Adresse nach Annahme beider Nachrichten durch Mailpit; zusätzlicher Link als Rückfalloption.
- 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:
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.
Die gemeinsame Datenquelle src/shared/berater-daten.json enthält ein Array
mit eindeutigen String-IDs und den Feldern id, vorname, nachname, spitzname, email. Die vorhandenen Einträge enthalten die Beraterprofile. 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=maren-hoffmann. Ohne Parameter verwendet sie
relindis-agethen. 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 |
{
"email": "kunde@example.test",
"advisorId": "relindis-agethen",
"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 buildundgit 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.