@@ -44,8 +44,10 @@ const PRODUKT_TEXT: Record<string, string> = {
follow_ups : 'Automatisierte handschriftliche Nachfass-Mailings für mehr Rücklauf.' ,
follow_ups : 'Automatisierte handschriftliche Nachfass-Mailings für mehr Rücklauf.' ,
} ;
} ;
/** Standard-Platzhalter der strukturierten Adresse (werden automatisch befüllt). */
/** Standard-Platzhalter der strukturierten Adresse (werden automatisch befüllt).
const STANDARD_STRUKTUR = [ 'Anrede' , 'Vorname' , 'Nachname' , 'Strasse' , 'PLZ' , 'Ort' , 'Land' ] ;
* Ohne „Anrede" – dafür gibt es kein Empfängerfeld; als [[Anrede]] ist es ein
* frei befüllbarer eigener Platzhalter. */
const STANDARD_STRUKTUR = [ 'Vorname' , 'Nachname' , 'Strasse' , 'PLZ' , 'Ort' , 'Land' ] ;
/** Standard-Platzhalter der Freitext-Adresse. */
/** Standard-Platzhalter der Freitext-Adresse. */
const STANDARD_FREITEXT = [ 'Zeile1' , 'Zeile2' , 'Zeile3' , 'Zeile4' , 'Zeile5' ] ;
const STANDARD_FREITEXT = [ 'Zeile1' , 'Zeile2' , 'Zeile3' , 'Zeile4' , 'Zeile5' ] ;
@@ -792,6 +794,28 @@ export default function Configurator({ vorwahlProdukt }: { vorwahlProdukt?: stri
const eigeneImText = genutztePlatzhalter . filter ( ( p ) = > ! standardSet . has ( p . toLowerCase ( ) ) ) ;
const eigeneImText = genutztePlatzhalter . filter ( ( p ) = > ! standardSet . has ( p . toLowerCase ( ) ) ) ;
/** Platzhalter im individuellen Umschlagtext – analog zur Text-Tabelle. */
/** Platzhalter im individuellen Umschlagtext – analog zur Text-Tabelle. */
const genutztePlatzhalterUmschlag = useMemo ( ( ) = > textPlatzhalter ( umschlagText ) , [ umschlagText ] ) ;
const genutztePlatzhalterUmschlag = useMemo ( ( ) = > textPlatzhalter ( umschlagText ) , [ umschlagText ] ) ;
/**
* Entry für den Versand ans Backend: löst ALLE im Text/Umschlag genutzten
* Platzhalter explizit auf (Standard-Platzhalter aus der Adresse via standardWert,
* eigene aus e.placeholders). So wird je Empfänger sicher ersetzt – unabhängig
* davon, wie das Backend die Adressfelder interpretiert.
*
* Zusätzlich wird der Freitext nur bei Adressmodus „freitext" mitgeschickt.
* Bei strukturierter Adresse muss free_text leer sein, sonst bevorzugt das
* Backend (addressText) den Freitext und beschriftet den Umschlag falsch –
* auch wenn im Freitextfeld nur Reste von einem früheren Moduswechsel stehen.
*/
const mitPlatzhaltern = ( e : Entry ) : Entry = > {
const used = [ . . . new Set ( [ . . . genutztePlatzhalter , . . . genutztePlatzhalterUmschlag ] ) ] ;
return {
. . . e ,
free_text : adressModus === 'freitext' ? e . free_text : '' ,
placeholders : {
. . . Object . fromEntries ( used . map ( ( p ) = > [ p , standardWert ( e , p ) ] ) ) ,
. . . e . placeholders ,
} ,
} ;
} ;
/**
/**
* Werden Platzhalterwerte NICHT bereits in einem Empfänger-Schritt erfasst
* Werden Platzhalterwerte NICHT bereits in einem Empfänger-Schritt erfasst
* (kein Adress-Schritt, kein Umschlag-Freitext)? Dann muss der Text-Schritt
* (kein Adress-Schritt, kein Umschlag-Freitext)? Dann muss der Text-Schritt
@@ -932,7 +956,7 @@ export default function Configurator({ vorwahlProdukt }: { vorwahlProdukt?: stri
realistic : realistisch ,
realistic : realistisch ,
envelope_labeling : needsEnvelope ? labeling : 'keine' ,
envelope_labeling : needsEnvelope ? labeling : 'keine' ,
envelope_text : umschlagText ,
envelope_text : umschlagText ,
entries : entries.slice ( 0 , 3 ) ,
entries : entries.slice ( 0 , 3 ) . map ( mitPlatzhaltern ) ,
} ) ;
} ) ;
if ( r . has_overflow ) {
if ( r . has_overflow ) {
setTextUeberlauf ( true ) ;
setTextUeberlauf ( true ) ;
@@ -981,7 +1005,7 @@ export default function Configurator({ vorwahlProdukt }: { vorwahlProdukt?: stri
realistic : realistisch ,
realistic : realistisch ,
envelope_labeling : needsEnvelope ? labeling : 'keine' ,
envelope_labeling : needsEnvelope ? labeling : 'keine' ,
envelope_text : umschlagText ,
envelope_text : umschlagText ,
entries : entries.slice ( 0 , 3 ) ,
entries : entries.slice ( 0 , 3 ) . map ( mitPlatzhaltern ) ,
} ) ;
} ) ;
setPreviewDocs ( ergebnis . docs ) ;
setPreviewDocs ( ergebnis . docs ) ;
setPreviewVerbleibend ( ergebnis . remaining ) ;
setPreviewVerbleibend ( ergebnis . remaining ) ;
@@ -1080,7 +1104,9 @@ export default function Configurator({ vorwahlProdukt }: { vorwahlProdukt?: stri
street : lieferung.street , zip : lieferung.zip , city : lieferung.city , country : lieferung.country ,
street : lieferung.street , zip : lieferung.zip , city : lieferung.city , country : lieferung.country ,
}
}
: null ,
: null ,
entries : entries.map ( ( e ) = > ( {
entries : entries.map ( ( e ) = > {
const n = mitPlatzhaltern ( e ) ; // free_text-Normalisierung + Platzhalter
return {
salutation : e.salutation ,
salutation : e.salutation ,
first_name : e.first_name ,
first_name : e.first_name ,
last_name : e.last_name ,
last_name : e.last_name ,
@@ -1089,11 +1115,12 @@ export default function Configurator({ vorwahlProdukt }: { vorwahlProdukt?: stri
zip : e.zip ,
zip : e.zip ,
city : e.city ,
city : e.city ,
country : e.country ,
country : e.country ,
free_text : adressModus === 'freitext' ? e . free_text : '' ,
free_text : n.free_text ,
placeholders : e .placeholders,
placeholders : n .placeholders,
// Abweichender Text nur, wenn wirklich gesetzt (sonst greift der Standardtext).
// Abweichender Text nur, wenn wirklich gesetzt (sonst greift der Standardtext).
text : ( e . text && e . text . trim ( ) ) ? e.text : undefined ,
text : ( e . text && e . text . trim ( ) ) ? e.text : undefined ,
} ) ) ,
} ;
} ) ,
} ) ;
} ) ;
// Auftrag ist abgesendet – der zwischengespeicherte Entwurf wird verworfen.
// Auftrag ist abgesendet – der zwischengespeicherte Entwurf wird verworfen.
try { localStorage . removeItem ( ENTWURF_KEY ) ; } catch { /* egal */ }
try { localStorage . removeItem ( ENTWURF_KEY ) ; } catch { /* egal */ }