import React, { useState, useEffect, memo, useCallback } from "react"; import { Canvas } from "./canvas/Canvas"; import { Toolbar } from "./toolbar/Toolbar"; import { PropertiesPanel } from "./properties/PropertiesPanel"; import { Header } from "./header/Header"; import { ElementLibrary } from "./element-library/ElementLibrary"; import { useTemplate } from "../hooks/useTemplate"; import { useBuilder } from "../contexts/builder/BuilderContext"; import { useCanvasSettings, DEFAULT_SETTINGS, } from "../contexts/CanvasSettingsContext"; import { DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT, } from "../constants/canvas"; import { getEditorFeatureFlags } from "../utils/editorFeatures"; import { ClientNonceManager } from "../utils/ClientNonceManager"; import { injectResponsiveUtils } from "../utils/responsive"; import { useIsMobile, useIsTablet } from "../hooks/useResponsive"; import { debugLog, debugError } from "../utils/debug"; // Déclaration des types pour les fonctions de notification globales declare global { interface Window { showSuccessNotification?: (message: string, duration?: number) => void; showErrorNotification?: (message: string, duration?: number) => void; showWarningNotification?: (message: string, duration?: number) => void; showInfoNotification?: (message: string, duration?: number) => void; } } // ✅ Add spin animation const spinStyles = ` @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; // Inject CSS if (typeof document !== "undefined") { const style = document.createElement("style"); style.textContent = spinStyles; document.head.appendChild(style); } interface PDFBuilderContentProps { width?: number; height?: number; className?: string; } export const PDFBuilderContent = memo(function PDFBuilderContent({ width = DEFAULT_CANVAS_WIDTH, height = DEFAULT_CANVAS_HEIGHT, className, }: PDFBuilderContentProps) { debugLog("🏗️ PDFBuilderContent: Component initialized with props:", { width, height, className, }); const { state } = useBuilder(); const isPreviewMode = state.previewMode === "command"; const { isPremium } = getEditorFeatureFlags(); const [isHeaderFixed, setIsHeaderFixed] = useState(false); const [isPropertiesPanelOpen, setIsPropertiesPanelOpen] = useState(false); const [manualSaveSuccess, _setManualSaveSuccess] = useState(false); debugLog("📱 PDFBuilderContent: Initial state set:", { isHeaderFixed, isPropertiesPanelOpen, manualSaveSuccess, isPreviewMode, }); // Hooks responsives const isMobile = useIsMobile(); const isTablet = useIsTablet(); debugLog("📱 PDFBuilderContent: Responsive hooks:", { isMobile, isTablet }); const { templateName, templateDescription, canvasWidth, canvasHeight, marginTop, marginBottom, showGuides, snapToGrid, isNewTemplate, isModified, isSaving, isLoading, // ✅ NEW: Template is loading isEditingExistingTemplate, saveTemplate, previewTemplate, newTemplate, updateTemplateSettings, } = useTemplate(); debugLog("📋 PDFBuilderContent: useTemplate hook values:", { templateName, templateDescription, canvasWidth, canvasHeight, marginTop, marginBottom, showGuides, snapToGrid, isNewTemplate, isModified, isSaving, isLoading, isEditingExistingTemplate, }); // Hook pour les paramètres du canvas const canvasSettings = useCanvasSettings(); debugLog("🎨 PDFBuilderContent: Canvas settings:", canvasSettings); // Vérifier les erreurs de chargement des paramètres du canvas useEffect(() => { if (canvasSettings.error) { debugError( "❌ PDFBuilderContent: Canvas settings error:", canvasSettings.error, ); // Afficher une notification d'erreur if (typeof window !== "undefined" && window.showErrorNotification) { debugLog( "🔔 PDFBuilderContent: Showing canvas settings error notification", ); window.showErrorNotification( `Erreur lors du chargement des paramètres: ${canvasSettings.error}`, ); } } }, [canvasSettings.error]); // Injection des utilitaires responsives useEffect(() => { debugLog("🔧 PDFBuilderContent: Injecting responsive utils"); injectResponsiveUtils(); debugLog("✅ PDFBuilderContent: Responsive utils injected"); }, []); // Effet pour gérer le scroll et ajuster le padding useEffect(() => { debugLog("📜 PDFBuilderContent: Setting up scroll handler"); const handleScroll = () => { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; const newIsHeaderFixed = scrollTop > 100; debugLog( "📜 PDFBuilderContent: Scroll detected, scrollTop:", scrollTop, "isHeaderFixed:", newIsHeaderFixed, ); setIsHeaderFixed(newIsHeaderFixed); }; window.addEventListener("scroll", handleScroll, { passive: true }); debugLog("✅ PDFBuilderContent: Scroll handler added"); return () => { debugLog("🧹 PDFBuilderContent: Cleaning up scroll handler"); window.removeEventListener("scroll", handleScroll); }; }, []); // Wrapper pour sauvegarder const saveTemplateWithAutoSave = useCallback(async () => { debugLog("💾 PDFBuilderContent: Manual save initiated"); try { // Effectuer la sauvegarde manuelle debugLog("🔄 PDFBuilderContent: Calling saveTemplate..."); await saveTemplate(); debugLog("✅ PDFBuilderContent: Manual save successful"); debugLog("[PDF_BUILDER] Manual save successful"); // Afficher une notification de succès if (typeof window !== "undefined" && window.showSuccessNotification) { debugLog("🔔 PDFBuilderContent: Showing success notification"); window.showSuccessNotification("Template sauvegardé avec succès !"); } } catch (manualSaveError) { debugError("❌ PDFBuilderContent: Manual save failed:", manualSaveError); debugError("[PDF_BUILDER] Manual save failed:", manualSaveError); // Afficher une notification d'erreur if (typeof window !== "undefined" && window.showErrorNotification) { debugLog("🔔 PDFBuilderContent: Showing error notification"); window.showErrorNotification( "Erreur lors de la sauvegarde du template", ); } throw manualSaveError; // Re-throw pour que l'UI montre l'erreur } }, [saveTemplate]); return ( <>
{/* Header en haut - masqué en mode preview */} {!isPreviewMode && (
)} {/* Toolbar sous le header - masqué en mode preview */} {!isPreviewMode && (
)} {/* Contenu principal */}
{/* Sidebar des éléments WooCommerce - masqué en mode preview */} {!isPreviewMode && } {/* Zone centrale avec le canvas */}
{/* Indicateur de dimensions avec format et DPI */} {!isPreviewMode && (
{(() => { const format = (window as any).pdfBuilderCanvasSettings ?.default_canvas_format || "A4"; const dpi = (window as any).pdfBuilderCanvasSettings ?.default_canvas_dpi || 96; const orientation = (window as any).pdfBuilderCanvasSettings ?.default_canvas_orientation || "portrait"; const paperFormats = (window as any) .pdfBuilderPaperFormats || { A4: { width: 210, height: 297 }, A3: { width: 297, height: 420 }, A5: { width: 148, height: 210 }, Letter: { width: 215.9, height: 279.4 }, Legal: { width: 215.9, height: 355.6 }, Tabloid: { width: 279.4, height: 431.8 }, }; // Récupérer les dimensions en mm const dimsMM = paperFormats[format] || paperFormats["A4"]; // Calculer les dimensions en pixels avec le DPI actuel const pixelsPerMM = dpi / 25.4; let widthPx = Math.round(dimsMM.width * pixelsPerMM); let heightPx = Math.round(dimsMM.height * pixelsPerMM); // Inverser si orientation paysage if (orientation === "landscape") { [widthPx, heightPx] = [heightPx, widthPx]; } return `${format}: ${widthPx}×${heightPx}px (${dpi} DPI)`; })()}
)} {/* Bouton Générer PDF en mode preview */} {isPreviewMode && ( )} {/* ✅ Loading spinner overlay */} {isLoading && (

Chargement du template...

)} {/* ✅ ONLY render Canvas when template is loaded OR it's a new template */} {!isLoading && ( <> {debugLog( "🎨 PDFBuilderContent: Rendering Canvas component", { canvasWidth, canvasHeight }, )} )}
{/* Bouton toggle pour le panneau de propriétés - masqué en mode preview */} {!isPreviewMode && ( )}
{/* Panneau de propriétés à droite - masqué en mode preview */} {!isPreviewMode && isPropertiesPanelOpen && (
)}
); });