/** * Template email de relance — envoyé AU CLIENT FINAL pour réclamer le * paiement d'une facture impayée. Le subject + le body sont définis par * le user dans son plan de relance (avec variables {{numero}} etc.) ; on * injecte ce body brut dans une mise en page Rubis : * * - Header rubis-deep avec le NOM DE L'ORG (ce que connaît le client) * et le numéro de facture en sous-titre * - Body rendu (le texte que le user a rédigé, déjà interpolé) * - Card "récap facture" en pied de body : numéro, montant, échéance * * Pas de boutons CTA dans la relance — le client est censé payer hors * mail (virement, espèces, ...). Le mail rappelle juste le contexte. */ import * as React from 'react' import { Section, Text } from '@react-email/components' import { BRAND, sp } from './_brand.js' import { EmailLayout } from './_layout.js' export type RelanceEmailProps = { /** Nom commercial visible côté client (l'org du user). */ brandName: string invoice: { numero: string amountFormatted: string dueDateFormatted: string daysLate: number } /** Texte de la relance (déjà interpolé) que le user a posé dans son plan. */ bodyText: string /** URL landing publique (footer cliquable "Rubis sur l'ongle"). */ landingUrl?: string } export function RelanceEmail({ brandName, invoice, bodyText, landingUrl, }: RelanceEmailProps) { const isLate = invoice.daysLate > 0 return ( {/* Body texte en pre-line pour conserver les sauts de ligne tels que le user les a écrits. Le client lit le mot du patron, pas un template impersonnel. */} {bodyText} {/* Card récap en pied : tableau visuel court qui rappelle les chiffres. */}
Facture {invoice.numero} Montant TTC {invoice.amountFormatted} Échéance {invoice.dueDateFormatted} {isLate ? ( ({invoice.daysLate}j de retard) ) : null}
) } // --------------------------------------------------------------------------- // Styles inline // --------------------------------------------------------------------------- const bodyTextStyle: React.CSSProperties = { color: BRAND.ink, fontSize: '15px', lineHeight: '1.6', margin: `0 0 ${sp.xl} 0`, whiteSpace: 'pre-line', // préserve les \n du body sans nécessiter
} const summaryCardStyle: React.CSSProperties = { // Blanc sur fond crème pour détacher la card visuellement (le container // du layout est désormais crème, pas blanc). backgroundColor: BRAND.white, border: `1px solid ${BRAND.line}`, borderRadius: BRAND.radiusCard, padding: `${sp.md} ${sp.lg}`, margin: `${sp.lg} 0 0 0`, } const summaryRowStyle: React.CSSProperties = { display: 'block', margin: `${sp.sm} 0`, fontSize: '13px', lineHeight: '1.4', } const summaryLabelStyle: React.CSSProperties = { display: 'inline-block', width: '110px', color: BRAND.ink3, fontWeight: 500, } const summaryValueStyle: React.CSSProperties = { color: BRAND.ink, fontWeight: 600, }