import React, { useState } from "react"; import { CompanyInfoElement } from "../../types/elements"; import { NumericPropertyInput } from "../ui/NumericPropertyInput"; import { ColorPropertyInput } from "../ui/ColorPropertyInput"; import { getEditorFeatureFlags, getPdfBuilderData } from "../../utils/editorFeatures"; interface CompanyInfoPropertiesProps { element: CompanyInfoElement; onChange: (elementId: string, property: string, value: unknown) => void; activeTab: { [key: string]: "fonctionnalites" | "personnalisation" | "positionnement"; }; setActiveTab: (tabs: { [key: string]: "fonctionnalites" | "personnalisation" | "positionnement"; }) => void; } // Composant Toggle personnalisé const Toggle = ({ checked, onChange, label, description, }: { checked: boolean; onChange: (checked: boolean) => void; label: string; description: string; }) => (
onChange(!checked)} style={{ position: "relative", width: "44px", height: "24px", backgroundColor: checked ? "#007bff" : "#ccc", borderRadius: "12px", cursor: "pointer", transition: "background-color 0.2s ease", border: "none", }} >
{description}
); export function CompanyInfoProperties({ element, onChange, activeTab, setActiveTab, }: CompanyInfoPropertiesProps) { const companyCurrentTab = activeTab[element.id] || "fonctionnalites"; const setCompanyCurrentTab = ( tab: "fonctionnalites" | "personnalisation" | "positionnement", ) => { setActiveTab({ ...activeTab, [element.id]: tab }); }; const pdfBuilderData = getPdfBuilderData(); const { canUseEditorThemes } = getEditorFeatureFlags(); // Helper pour normaliser le padding en nombre (gère les objets padding complexes) const _normalizePadding = ( value: | number | { top?: number; right?: number; bottom?: number; left?: number } | undefined, defaultValue: number = 12, ): number => { if (typeof value === "number") return value; if (typeof value === "object" && value !== null) { // Si c'est un objet, on prend la moyenne ou la première valeur disponible return ( value.top ?? value.left ?? value.right ?? value.bottom ?? defaultValue ); } return defaultValue; }; // Fonction pour générer le contenu des infos entreprise depuis les propriétés const generateCompanyContent = (props?: any) => { const config = props || element; const companyParts: string[] = []; // Récupérer les données d'entreprise depuis window const pluginCompany = pdfBuilderData.company || {}; // Helper pour valider une valeur const isValidValue = (value: any): boolean => { return value && value.toString().trim() !== "" && value !== "Non indiqué"; }; // Nom de l'entreprise (header) if (config.showCompanyName !== false) { const companyName = config.companyName || pluginCompany.name || ""; if (isValidValue(companyName)) { const _headerFontSize = config.headerFontSize || config.fontSize || 14; const _headerFontWeight = config.headerFontWeight || "bold"; const _headerColor = config.headerTextColor || config.textColor || "#000000"; companyParts.push(`Entreprise: ${companyName}`); } } // Adresse if (config.showAddress !== false) { const address = config.companyAddress || pluginCompany.address || ""; const city = config.companyCity || pluginCompany.city || ""; if (isValidValue(address)) { let fullAddress = address; if (isValidValue(city)) fullAddress += `, ${city}`; companyParts.push(fullAddress); } } // Téléphone if (config.showPhone !== false) { const phone = config.companyPhone || pluginCompany.phone || ""; if (isValidValue(phone)) { companyParts.push(`Tél: ${phone}`); } } // Email if (config.showEmail !== false) { const email = config.companyEmail || pluginCompany.email || ""; if (isValidValue(email)) { companyParts.push(`Email: ${email}`); } } // SIRET if (config.showSiret !== false) { const siret = config.companySiret || pluginCompany.siret || ""; if (isValidValue(siret)) { companyParts.push(`SIRET: ${siret}`); } } // TVA if (config.showVat !== false) { const tva = config.companyTva || pluginCompany.vat || ""; if (isValidValue(tva)) { companyParts.push(`TVA: ${tva}`); } } // RCS if (config.showRcs !== false) { const rcs = config.companyRcs || pluginCompany.rcs || ""; if (isValidValue(rcs)) { companyParts.push(`RCS: ${rcs}`); } } // Capital if (config.showCapital !== false) { const capital = config.companyCapital || pluginCompany.capital || ""; if (isValidValue(capital)) { companyParts.push(`Capital: ${capital} €`); } } // Assembler avec séparateur (newline pour vertical) return companyParts.join("\n"); }; // Helper pour toggler et régénérer le contenu const handlePropertyChangeWithContentUpdate = ( property: string, value: any, ) => { onChange(element.id, property, value); // Si c'est une propriété qui affecte le contenu, régénérer et sauvegarder if ( [ "showCompanyName", "showAddress", "showPhone", "showEmail", "showSiret", "showVat", "showRcs", "showCapital", ].includes(property) ) { const newConfig = { ...element, [property]: value }; const generatedContent = generateCompanyContent(newConfig); if (generatedContent && generatedContent.trim()) { onChange(element.id, "content", generatedContent); } } }; // État pour les accordéons de police const [fontAccordions, setFontAccordions] = useState({ headerFont: false, // Accordéon du nom de l'entreprise fermé par défaut bodyFont: false, // Accordéon des informations fermé par défaut layout: true, // Accordéon disposition ouvert par défaut themes: false, // Accordéon thèmes fermé par défaut colors: false, // Accordéon couleurs fermé par défaut }); const toggleAccordion = (accordion: "headerFont" | "bodyFont") => { setFontAccordions((prev) => ({ ...prev, [accordion]: !prev[accordion], })); }; const companyThemes = [ { id: "corporate", name: "Corporate", preview: (
), styles: { backgroundColor: "#ffffff", borderColor: "#1f2937", textColor: "#374151", headerTextColor: "#111827", }, }, { id: "modern", name: "Moderne", preview: (
), styles: { backgroundColor: "#ffffff", borderColor: "#3b82f6", textColor: "#1e40af", headerTextColor: "#1e3a8a", }, }, { id: "elegant", name: "Élégant", preview: (
), styles: { backgroundColor: "#ffffff", borderColor: "#8b5cf6", textColor: "#6d28d9", headerTextColor: "#581c87", }, }, { id: "minimal", name: "Minimal", preview: (
), styles: { backgroundColor: "#ffffff", borderColor: "#e5e7eb", textColor: "#374151", headerTextColor: "#111827", }, }, { id: "professional", name: "Professionnel", preview: (
), styles: { backgroundColor: "#ffffff", borderColor: "#059669", textColor: "#065f46", headerTextColor: "#064e3b", }, }, { id: "classic", name: "Classique", preview: (
), styles: { backgroundColor: "#ffffff", borderColor: "#92400e", textColor: "#78350f", headerTextColor: "#451a03", }, }, ]; return ( <> {/* Système d'onglets pour Company Info */}
{/* Onglet Fonctionnalités */} {companyCurrentTab === "fonctionnalites" && ( <> {/* Section Structure des informations */}
Structure des informations
onChange(element.id, "showBackground", checked) } label="Afficher le fond" description="Affiche un fond coloré derrière les informations" /> onChange(element.id, "showBorders", checked) } label="Afficher les bordures" description="Affiche les bordures autour des sections" />
{/* Section Informations générales */}
Informations générales
handlePropertyChangeWithContentUpdate( "showCompanyName", checked, ) } label="Afficher le nom de l'entreprise" description="Nom de l'entreprise" />
{/* Section Coordonnées */}
Coordonnées
handlePropertyChangeWithContentUpdate("showAddress", checked) } label="Afficher l'adresse" description="Adresse complète de l'entreprise" /> handlePropertyChangeWithContentUpdate("showPhone", checked) } label="Afficher le téléphone" description="Numéro de téléphone" /> handlePropertyChangeWithContentUpdate("showEmail", checked) } label="Afficher l'email" description="Adresse email de l'entreprise" />
{/* Section Informations légales */}
Informations légales
onChange(element.id, "showSiret", checked) } label="Afficher le numéro SIRET" description="Numéro SIRET de l'entreprise" /> onChange(element.id, "showVat", checked)} label="Afficher le numéro TVA" description="Numéro TVA de l'entreprise" /> onChange(element.id, "showRcs", checked)} label="Afficher le RCS" description="Registre du Commerce et des Sociétés" /> onChange(element.id, "showCapital", checked) } label="Afficher le capital social" description="Montant du capital social de l'entreprise" />
)} {/* Onglet Personnalisation */} {companyCurrentTab === "personnalisation" && ( <> {/* Accordéon Disposition */}
setFontAccordions((prev) => ({ ...prev, layout: !prev.layout })) } style={{ padding: "12px", backgroundColor: "#f8f9fa", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: fontAccordions.layout ? "1px solid #e9ecef" : "none", }} >

Disposition

{fontAccordions.layout && (
{/* Alignement vertical */}
{/* Padding top */}
onChange( element.id, "paddingTop", parseInt(e.target.value) || 0, ) } min="0" max="50" style={{ width: "100%", padding: "4px 8px", border: "1px solid #ccc", borderRadius: "3px", fontSize: "12px", }} />
{/* Padding horizontal */}
onChange( element.id, "paddingHorizontal", parseInt(e.target.value) || 0, ) } min="0" max="50" style={{ width: "100%", padding: "4px 8px", border: "1px solid #ccc", borderRadius: "3px", fontSize: "12px", }} />
{/* Padding bottom */}
onChange( element.id, "paddingBottom", parseInt(e.target.value) || 0, ) } min="0" max="50" style={{ width: "100%", padding: "4px 8px", border: "1px solid #ccc", borderRadius: "3px", fontSize: "12px", }} />
{/* Line spacing */}
onChange( element.id, "lineSpacing", parseInt(e.target.value) || 0, ) } min="0" max="20" style={{ width: "100%", padding: "4px 8px", border: "1px solid #ccc", borderRadius: "3px", fontSize: "12px", }} />
{/* Line-height (CSS) */}
onChange( element.id, "lineHeight", parseFloat(e.target.value) || 1, ) } min="0.5" max="3" step="0.1" style={{ width: "100%", padding: "4px 8px", border: "1px solid #ccc", borderRadius: "3px", fontSize: "12px", }} />
Actuel:{" "} {parseFloat(String(element.lineHeight || 1.4)).toFixed(1)}{" "} (Puppeteer uniquement)
)}
{canUseEditorThemes && ( <> {/* Accordéon Thèmes prédéfinis */}
setFontAccordions((prev) => ({ ...prev, themes: !prev.themes })) } style={{ padding: "12px", backgroundColor: "#f8f9fa", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: fontAccordions.themes ? "1px solid #e9ecef" : "none", }} >

Thèmes prédéfinis

{fontAccordions.themes && (
{companyThemes.map((theme) => (
{ // Appliquer le thème et toutes ses couleurs onChange(element.id, "theme", theme.id); onChange( element.id, "backgroundColor", theme.styles.backgroundColor, ); onChange( element.id, "borderColor", theme.styles.borderColor, ); onChange( element.id, "textColor", theme.styles.textColor, ); onChange( element.id, "headerTextColor", theme.styles.headerTextColor, ); }} style={{ cursor: "pointer", border: element.theme === theme.id ? "2px solid #007bff" : "2px solid transparent", borderRadius: "6px", padding: "6px", backgroundColor: "#ffffff", transition: "all 0.2s ease", }} title={theme.name} >
{theme.name}
{theme.preview}
))}
)}
)}
{/* Police du nom de l'entreprise - Accordéon */} {element.showCompanyName !== false && (
toggleAccordion("headerFont")} style={{ padding: "12px", backgroundColor: "#f8f9fa", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: fontAccordions.headerFont ? "1px solid #e9ecef" : "none", }} >

Police du nom de l'entreprise

{fontAccordions.headerFont && (
onChange(element.id, "headerFontSize", value) } />
)}
)} {/* Police du corps du texte - Accordéon */}
toggleAccordion("bodyFont")} style={{ padding: "12px", backgroundColor: "#f8f9fa", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: fontAccordions.bodyFont ? "1px solid #e9ecef" : "none", }} >

Police des informations

{fontAccordions.bodyFont && (
onChange(element.id, "bodyFontSize", value) } />
)}
{/* Accordéon Couleurs */}
setFontAccordions((prev) => ({ ...prev, colors: !prev.colors })) } style={{ padding: "12px", backgroundColor: "#f8f9fa", cursor: "pointer", display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: fontAccordions.colors ? "1px solid #e9ecef" : "none", }} >

Couleurs

{fontAccordions.colors && (
{element.showBackground !== false && (
onChange(element.id, "backgroundColor", value) } />
)} {element.showBorders !== false && (
onChange(element.id, "borderColor", value) } />
)} {element.showBorders !== false && ( onChange(element.id, "borderWidth", value) } description="Épaisseur de la bordure en pixels" /> )}
onChange(element.id, "headerTextColor", value) } />
onChange(element.id, "textColor", value) } />
onChange(element.id, "textColor", value) } />
)}
)} {/* Onglet Positionnement */} {companyCurrentTab === "positionnement" && ( <>
onChange(element.id, "x", parseInt(e.target.value)) } style={{ width: "100%", height: "6px", borderRadius: "3px", background: "#ddd", outline: "none", cursor: "pointer", }} />
onChange(element.id, "y", parseInt(e.target.value)) } style={{ width: "100%", height: "6px", borderRadius: "3px", background: "#ddd", outline: "none", cursor: "pointer", }} />
onChange(element.id, "width", parseInt(e.target.value)) } style={{ width: "100%", height: "6px", borderRadius: "3px", background: "#ddd", outline: "none", cursor: "pointer", }} />
onChange(element.id, "height", parseInt(e.target.value)) } style={{ width: "100%", height: "6px", borderRadius: "3px", background: "#ddd", outline: "none", cursor: "pointer", }} />
)} ); }