Kundendaten-Modal: E-Mail-Wahl Stammdaten vs. Absender

In der "Anrede & Name"-Section neue Radio-Wahl, sobald die
Section aktiv ist:
- Stammdaten-E-Mail (customer.email) – default wenn vorhanden
- Absender-Adresse (Postfach von dem gesendet wird)
- Keine E-Mail einfügen

Wird in den Customer-Block-Builder durchgereicht und ersetzt die
fix verdrahtete customer.email-Zeile. Wenn die Stammdaten-Mail
fehlt, ist der Radio "Stammdaten" disabled und der Default
springt auf "Absender".

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 16:04:54 +02:00
parent 5293af18a5
commit f1b05c56e5
2 changed files with 82 additions and 3 deletions
@@ -420,6 +420,7 @@ export default function ComposeEmailModal({
isOpen={showInsertDataModal}
onClose={() => setShowInsertDataModal(false)}
contractId={contractId}
senderEmail={account.email}
currentBody={body}
currentAttachments={attachments}
onResult={(newBody, addedAtt) => {
@@ -18,11 +18,21 @@ interface Props {
isOpen: boolean;
onClose: () => void;
contractId: number;
/**
* E-Mail-Adresse des Postfachs, von dem die Mail abgeschickt wird.
* Wird in der "Anrede & Name"-Section als Alternative zur Stammdaten-
* E-Mail angeboten User-Wunsch 2026-06-21: bei Kundendaten wählen,
* ob die Customer-Email oder die Stressfrei-Wechseln-Absender-Adresse
* eingefügt wird.
*/
senderEmail: string;
currentBody: string;
currentAttachments: EmailAttachment[];
onResult: (newBody: string, addedAttachments: EmailAttachment[]) => void;
}
type EmailChoice = 'master' | 'sender' | 'none';
const MAX_TOTAL_SIZE = 25 * 1024 * 1024;
type SectionKey =
@@ -37,6 +47,7 @@ export default function InsertCustomerDataModal({
isOpen,
onClose,
contractId,
senderEmail,
currentBody,
currentAttachments,
onResult,
@@ -73,6 +84,11 @@ export default function InsertCustomerDataModal({
});
const [attachBankCard, setAttachBankCard] = useState(false);
const [attachIdentity, setAttachIdentity] = useState(false);
// Welche E-Mail-Adresse in der Customer-Section steht:
// - 'master' = Stammdaten-E-Mail (customer.email)
// - 'sender' = Postfach-Adresse, von der die Mail abgeht (Stressfrei)
// - 'none' = E-Mail-Zeile weglassen
const [emailChoice, setEmailChoice] = useState<EmailChoice>('master');
const [busy, setBusy] = useState(false);
// Bei jedem Öffnen sinnvoll vorbelegen (sonst bleiben "checked" stale
@@ -89,6 +105,8 @@ export default function InsertCustomerDataModal({
});
setAttachBankCard(false);
setAttachIdentity(false);
// Default: Stammdaten-E-Mail wenn vorhanden, sonst Absender-Adresse.
setEmailChoice(customer?.email ? 'master' : 'sender');
}
}, [isOpen, contract, customer, deliveryAddress]);
@@ -108,7 +126,13 @@ export default function InsertCustomerDataModal({
const blocks: string[] = [];
if (checked.customer && customer) {
blocks.push(formatCustomerBlock(customer, contract));
const chosenEmail =
emailChoice === 'master'
? customer.email || ''
: emailChoice === 'sender'
? senderEmail
: '';
blocks.push(formatCustomerBlock(customer, contract, chosenEmail));
}
if (checked.deliveryAddress && deliveryAddress) {
blocks.push(formatAddressBlock('Lieferadresse', deliveryAddress));
@@ -214,6 +238,56 @@ export default function InsertCustomerDataModal({
checked={checked.customer}
onToggle={() => toggle('customer')}
preview={previewCustomer(customer, contract)}
extra={
checked.customer && (
<div className="mt-2 ml-6 space-y-1">
<div className="text-xs font-medium text-gray-600">
E-Mail im Text:
</div>
<label className="flex items-center gap-2 text-xs text-gray-700 cursor-pointer">
<input
type="radio"
name="emailChoice"
checked={emailChoice === 'master'}
onChange={() => setEmailChoice('master')}
disabled={!customer.email}
className="text-blue-600"
/>
<span>
Stammdaten-E-Mail
{customer.email ? (
<span className="text-gray-400"> ({customer.email})</span>
) : (
<span className="text-gray-400"> (nicht hinterlegt)</span>
)}
</span>
</label>
<label className="flex items-center gap-2 text-xs text-gray-700 cursor-pointer">
<input
type="radio"
name="emailChoice"
checked={emailChoice === 'sender'}
onChange={() => setEmailChoice('sender')}
className="text-blue-600"
/>
<span>
Absender-Adresse
<span className="text-gray-400"> ({senderEmail})</span>
</span>
</label>
<label className="flex items-center gap-2 text-xs text-gray-700 cursor-pointer">
<input
type="radio"
name="emailChoice"
checked={emailChoice === 'none'}
onChange={() => setEmailChoice('none')}
className="text-blue-600"
/>
<span>Keine E-Mail einfügen</span>
</label>
</div>
)
}
/>
)}
{deliveryAddress && (
@@ -368,12 +442,16 @@ function fullName(
return parts.filter(Boolean).join(' ');
}
function formatCustomerBlock(customer: NonNullable<Contract['customer']>, contract: Contract): string {
function formatCustomerBlock(
customer: NonNullable<Contract['customer']>,
contract: Contract,
email: string,
): string {
const lines: string[] = ['Kundendaten:'];
lines.push(fullName(customer, contract.type));
if (customer.customerNumber) lines.push(`Kundennummer: ${customer.customerNumber}`);
if (customer.birthDate) lines.push(`Geburtsdatum: ${formatDate(customer.birthDate)}`);
if (customer.email) lines.push(`E-Mail: ${customer.email}`);
if (email) lines.push(`E-Mail: ${email}`);
if (customer.phone) lines.push(`Telefon: ${customer.phone}`);
if (customer.mobile) lines.push(`Mobil: ${customer.mobile}`);
return lines.join('\n');