Anrede-Verhältnis Du/Sie pro Kunde + Geburtstagsgruß respektiert Anrede

Schema:
- Customer.useInformalAddress: Boolean (Default: false = Sie)
- Auch bei Firmenkunden verfügbar (Chef kann man auch duzen)

Frontend:
- Neues Pflichtfeld "Anrede per" (Du/Sie) im Kunden-Formular
- Anzeige als Badge in CustomerDetail-Stammdaten

Geburtstagsgruß im Portal:
- Bei Du: "Herzlichen Glückwunsch, Max! Alles Gute zu deinem 42. Geburtstag!"
- Bei Sie: "Herzlichen Glückwunsch, Herr Müller! Alles Gute zu Ihrem 42. Geburtstag!"
- Konsistent auch bei nachträglichen Glückwünschen (hattest/hatten, bist/sind etc.)
- Backend liefert firstName, lastName, salutation und useInformalAddress

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 12:27:23 +02:00
parent ba29711ee7
commit 2a3928d0e7
8 changed files with 65 additions and 10 deletions
+17 -7
View File
@@ -27,6 +27,16 @@ export default function BirthdayModal() {
const handleClose = () => ackMutation.mutate();
// Anrede abhängig vom Du/Sie-Verhältnis zusammenstellen
const greetingName = info.useInformalAddress
? info.firstName
: [info.salutation, info.lastName].filter(Boolean).join(' ') || info.firstName;
const greetingPronoun = info.useInformalAddress ? 'dir' : 'Ihnen';
const greetingPossessive = info.useInformalAddress ? 'deinem' : 'Ihrem';
const greetingYour = info.useInformalAddress ? 'Dein' : 'Ihr';
const hadBirthday = info.useInformalAddress ? 'hattest' : 'hatten';
const becameOld = info.useInformalAddress ? 'bist' : 'sind';
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4">
<div className="bg-white rounded-2xl shadow-2xl max-w-md w-full overflow-hidden">
@@ -50,26 +60,26 @@ export default function BirthdayModal() {
{info.isToday ? (
<>
<h2 className="text-2xl font-bold text-gray-900 mb-2">
Herzlichen Glückwunsch, {info.firstName}!
Herzlichen Glückwunsch, {greetingName}!
</h2>
<p className="text-gray-600 mb-1">
Alles Gute zu Ihrem {info.age}. Geburtstag!
Alles Gute zu {greetingPossessive} {info.age}. Geburtstag!
</p>
<p className="text-gray-500 text-sm mb-6">
Wir wünschen Ihnen einen wunderschönen Tag und alles Gute für das neue Lebensjahr. 🌟
Wir wünschen {greetingPronoun} einen wunderschönen Tag und alles Gute für {greetingYour.toLowerCase()} neues Lebensjahr. 🌟
</p>
</>
) : (
<>
<h2 className="text-2xl font-bold text-gray-900 mb-2">
Nachträglich alles Gute, {info.firstName}!
Nachträglich alles Gute, {greetingName}!
</h2>
<p className="text-gray-600 mb-1">
Sie hatten vor {info.daysAgo} Tag{info.daysAgo === 1 ? '' : 'en'} Geburtstag
{info.age > 0 && ` und sind ${info.age} Jahre alt geworden`}.
{greetingYour === 'Ihr' ? 'Sie' : 'Du'} {hadBirthday} vor {info.daysAgo} Tag{info.daysAgo === 1 ? '' : 'en'} Geburtstag
{info.age > 0 && ` und ${becameOld} ${info.age} Jahre alt geworden`}.
</p>
<p className="text-gray-500 text-sm mb-6">
Wir wünschen Ihnen alles Gute nachträglich und eine tolle Zeit im neuen Lebensjahr. 🌟
Wir wünschen {greetingPronoun} alles Gute nachträglich und eine tolle Zeit im neuen Lebensjahr. 🌟
</p>
</>
)}
@@ -267,6 +267,14 @@ export default function CustomerDetail({ portalCustomerId }: { portalCustomerId?
</dd>
</div>
)}
<div>
<dt className="text-sm text-gray-500">Anrede per</dt>
<dd>
<Badge variant={c.useInformalAddress ? 'info' : 'default'}>
{c.useInformalAddress ? 'Du (informell)' : 'Sie (formell)'}
</Badge>
</dd>
</div>
<div>
<dt className="text-sm text-gray-500">Vorname</dt>
<dd className="flex items-center gap-1">
@@ -135,6 +135,17 @@ export default function CustomerForm() {
]}
/>
<Select
label="Anrede per *"
{...register('useInformalAddress', {
setValueAs: (v) => v === 'true' || v === true,
})}
options={[
{ value: 'false', label: 'Sie (formell)' },
{ value: 'true', label: 'Du (informell)' },
]}
/>
<Input
label="Vorname"
{...register('firstName', { required: 'Vorname erforderlich' })}
+3
View File
@@ -1599,6 +1599,9 @@ export interface MyBirthdayCheck {
isToday: boolean;
daysAgo: number;
firstName: string;
lastName: string;
salutation: string | null;
useInformalAddress: boolean;
age: number;
}
+1
View File
@@ -62,6 +62,7 @@ export interface Customer {
customerNumber: string;
type: 'PRIVATE' | 'BUSINESS';
salutation?: string;
useInformalAddress?: boolean;
firstName: string;
lastName: string;
companyName?: string;