trihub-ernaehrung-backseatDevs/docs/contact.md

8.2 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 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.