Funktionen: Zustimmung in Textform auch per WhatsApp

Der Aktivieren-Dialog von Terminplaner, Webshop und Buchungskalender bietet als Weg zusätzlich WhatsApp an (Portal nimmt whatsapp an). Die Website-Analyse bleibt bei Chat oder E-Mail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Opus 5.5 committed 2026-10-11 15:03:37 +00:00
1 parent dc4df16cab
commit 0112c77afc
5 files changed
+16 -6

No files matched your search

@@ -8,7 +8,7 @@ import {
hindernisText, panelModell, anleitungOffen, textformNoetig, textformAnsicht, textformBereit, speicherStatus,
anfrageZeilen, anfrageStatus, stripeText, stripeTon, shopHatEintrag, begruendungOk, BEGRUENDUNG_MAX, entscheidungStatus,
} from '../../lib/funktionenView'
import { CHANNELS, channelLabel } from '../../lib/analyseView'
import { FUNKTION_CHANNELS, channelLabel } from '../../lib/analyseView'
import { berlinYmd, fmtDateTime } from '../../lib/format'
import { ticketPath } from '../../lib/ticketRoutes'
import { zeitenStatusText, mergeTeam, abschaltMeldung } from '../../lib/zeitenView'
@@ -139,7 +139,7 @@ function TextformPanel({ funktion, feld, value, onChange, projectId, today, disa
</label>
<span role="radiogroup" aria-label="Weg der Zustimmung" className="flex items-center gap-2 wrap">
<span>Weg:</span>
{CHANNELS.map((c) => (
{FUNKTION_CHANNELS.map((c) => (
<label key={c} className="check">
<input type="radio" name={`textform-weg-${funktion}-${projectId}`} value={c} checked={value.channel === c} disabled={disabled} onChange={() => onChange({ ...value, channel: c })} />
{channelLabel(c)}
+5 -2
View File
@@ -22,10 +22,13 @@ function formatIsoDate(value) {
}
export const CHANNELS = ['chat', 'email']
// Funktionen (Terminplaner, Webshop, Buchungskalender) nehmen zusaetzlich WhatsApp an (Portal: FUNKTION_CHANNELS)
export const FUNKTION_CHANNELS = ['chat', 'email', 'whatsapp']
export function channelLabel(channel) {
if (channel === 'chat') return 'Chat im Kundenportal'
if (channel === 'email') return 'E-Mail'
if (channel === 'whatsapp') return 'WhatsApp'
return ''
}
@@ -60,10 +63,10 @@ export const textformLabel = (version) => ({
})
// Alle drei Pflichtangaben; Datum als JJJJ-MM-TT zwischen Fassungsdatum und heute
export function canSubmitTextform({ confirmed, date, channel, today, minDate }) {
export function canSubmitTextform({ confirmed, date, channel, today, minDate, channels = CHANNELS }) {
if (confirmed !== true) return false
if (!/^\d{4}-\d{2}-\d{2}$/.test(String(date || ''))) return false
if (!CHANNELS.includes(channel)) return false
if (!channels.includes(channel)) return false
if (minDate && date < minDate) return false
if (today && date > today) return false
return true
+2 -2
View File
@@ -2,7 +2,7 @@
// Einarbeiten der Portal-Antwort. Rein, unter Node testbar.
import { fmtYmd, fmtBerlin } from './format'
import { canSubmitTextform } from './analyseView'
import { canSubmitTextform, FUNKTION_CHANNELS } from './analyseView'
/** Funktionen in Anzeigereihenfolge; key = Schluessel im Portal (features[key], POST /funktionen/:customerId/:key). */
export const FUNKTIONEN = [
@@ -288,7 +288,7 @@ export function textformAnsicht(feld, key = 'termine') {
export function textformBereit({ confirmed, date, channel, today }, feld) {
const minDate = typeof feld?.avvVersion === 'string' ? feld.avvVersion : ''
if (!minDate) return false
return canSubmitTextform({ confirmed, date, channel, today, minDate })
return canSubmitTextform({ confirmed, date, channel, today, minDate, channels: FUNKTION_CHANNELS })
}
/** Rumpf fuer POST /funktionen/:customerId/:key; Datum und Weg der Textform nur beim Aktivieren und nur, wenn beide da sind. */
+5
View File
@@ -56,6 +56,10 @@ test('textformLabel nennt die Fassung und die Zielgruppen-Bestaetigung', () => {
})
const ok = { confirmed: true, date: '2026-10-02', channel: 'email', today: '2026-10-03', minDate: '2026-10-02' }
test('channelLabel: WhatsApp fuer Funktionen', () => {
assert.equal(channelLabel('whatsapp'), 'WhatsApp')
})
test('canSubmitTextform: alles gueltig => true (Grenzen eingeschlossen)', () => {
assert.equal(canSubmitTextform(ok), true)
assert.equal(canSubmitTextform({ ...ok, channel: 'chat', date: '2026-10-03' }), true)
@@ -65,6 +69,7 @@ test('canSubmitTextform: fehlende oder ungueltige Angaben => false', () => {
assert.equal(canSubmitTextform({ ...ok, date: '' }), false)
assert.equal(canSubmitTextform({ ...ok, channel: '' }), false)
assert.equal(canSubmitTextform({ ...ok, channel: 'telefon' }), false)
assert.equal(canSubmitTextform({ ...ok, channel: 'whatsapp' }), false, 'Analyse: nur Chat oder E-Mail')
assert.equal(canSubmitTextform({ ...ok, date: '2026-10-01' }), false)
assert.equal(canSubmitTextform({ ...ok, date: '2026-10-04' }), false)
assert.equal(canSubmitTextform({ ...ok, date: 'morgen' }), false)
+2
View File
@@ -536,6 +536,8 @@ test('textformBereit mit dem Feld shop: Datum zwischen Fassung und heute, ohne F
assert.equal(textformBereit({ ...ok, date: '2026-10-04' }, shopFeld()), false, 'vor der Fassung')
assert.equal(textformBereit(ok, shopFeld({ avvVersion: '' })), false)
assert.equal(textformBereit(ok, undefined), false)
assert.equal(textformBereit({ ...ok, channel: 'whatsapp' }, shopFeld()), true, 'WhatsApp bei Funktionen erlaubt')
assert.equal(textformBereit({ ...ok, channel: 'telefon' }, shopFeld()), false)
})
test('termineChatTemplate: wörtlich, mit Fassung und den beiden versionierten Adressen', () => {