From 57002dc0221a03ca6d5db01fb6e9353466c9dc5f Mon Sep 17 00:00:00 2001 From: dschlueter Date: Thu, 25 Jun 2026 18:03:13 +0200 Subject: [PATCH] feat(admin): ein Speichern-Button auf Einstellungs-Ebene mit Format-Validierung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Speichern-Button aus dem einklappbaren „Notfall-Profil" auf die Karten-/ Einstellungs-Ebene verschoben (immer sichtbar) und in „Speichern" umbenannt. - Speichert jetzt ALLE Daten: alle Profilfelder + Standort-Freigabe + erlaubte Sprachen in einem PUT. - Vor JEDEM Speichern Format-Validierung pro Feld; bei Verstoß rotes Feld (border/ring-red) + Meckertext, Speichern wird abgebrochen. Rote Markierung verschwindet beim Nachbessern (input-Listener). - Regeln: PLZ = 5 Ziffern · Telefon = +/Ziffern/Leer/()/- (6–20) · Geburtsdatum = TT.MM.JJJJ (echtes Datum) · Kontakt-E-Mails/-Telefone = CSV gültiger Werte. Leere optionale Felder gelten als konform. Validierungslogik in node geprüft. Co-Authored-By: Claude Opus 4.8 --- app/web/app.js | 75 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/app/web/app.js b/app/web/app.js index 3393495..f8313f0 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -330,6 +330,27 @@ async function copyText(text, btn) { const ALL_LANGS = [["de","DE"],["en","EN"],["fr","FR"],["es","ES"],["it","IT"], ["pt","PT"],["pl","PL"],["ar","AR"],["ru","RU"],["zh","ZH"]]; +// --- Format-Validierung der Notfall-Profil-Felder ------------------------ +const _isEmail = (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v); +const _isPhone = (v) => /^\+?[\d\s/().\-]{6,20}$/.test(v); +function _isGermanDate(v) { + const m = /^(\d{2})\.(\d{2})\.(\d{4})$/.exec(v); + if (!m) return false; + const d = +m[1], mo = +m[2], y = +m[3]; + const dt = new Date(y, mo - 1, d); + return dt.getDate() === d && dt.getMonth() === mo - 1 && dt.getFullYear() === y && y >= 1900 && y <= 2100; +} +const _csvAll = (v, fn) => v.split(",").map((s) => s.trim()).filter(Boolean).every(fn); +// pro Feld: ok(wert) wird NUR bei nicht-leerem Wert geprüft + Meckertext. +const PROF_VALIDATORS = { + postal_code: { ok: (v) => /^\d{5}$/.test(v), msg: "PLZ: genau 5 Ziffern" }, + phone_mobile: { ok: _isPhone, msg: "Mobil: gültige Telefonnummer (z. B. +49 151 …)" }, + phone_landline: { ok: _isPhone, msg: "Festnetz: gültige Telefonnummer" }, + birth_date: { ok: _isGermanDate, msg: "Geburtsdatum: TT.MM.JJJJ" }, + emergency_contacts: { ok: (v) => _csvAll(v, _isEmail), msg: "Kontakt-E-Mail(s): gültige Adressen (Komma-getrennt)" }, + emergency_phones: { ok: (v) => _csvAll(v, _isPhone), msg: "Kontakt-Telefon(e): gültige Nummern (Komma-getrennt)" }, +}; + // Wendet die vom Admin erlaubten Sprachen auf das Sprachmenü an. Leer = alle erlaubt. // Genau eine erlaubte Sprache -> Menü ausblenden (kein Stress für den Nutzer). function applyAllowedLanguages(prefs) { @@ -1100,20 +1121,22 @@ function buildUserCard(u) { - + -
- - -
+ +
+ + +
+