import { useState, useEffect } from "react"; import { useEditor, EditorContent } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import { TextStyle } from '@tiptap/extension-text-style'; import { Color } from '@tiptap/extension-color'; import { Link } from '@tiptap/extension-link'; import { trpc } from "@/lib/trpc"; import DashboardLayout from "@/components/DashboardLayout"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { toast } from "sonner"; import { Mail, Eye, Save, RotateCcw, Plus } from "lucide-react"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; export default function AdminEmailTemplates() { const [selectedType, setSelectedType] = useState("inscription"); const [showPreviewModal, setShowPreviewModal] = useState(false); const [formData, setFormData] = useState({ type: "inscription", name: "", logoUrl: "", primaryColor: "#2563eb", headerBgColor: "#2563eb", headerTextColor: "#ffffff", headerTitle: "Formation Manager Itinova", bodyContent: "", footerText: "", active: true, }); const { data: templates, refetch } = trpc.emailTemplates.list.useQuery(); const { data: currentTemplate } = trpc.emailTemplates.getByType.useQuery( { type: selectedType }, { enabled: !!selectedType } ); // Initialiser l'éditeur TipTap const editor = useEditor({ extensions: [ StarterKit, TextStyle, Color, Link.configure({ openOnClick: false, }), ], content: formData.bodyContent, onUpdate: ({ editor }) => { setFormData({ ...formData, bodyContent: editor.getHTML() }); }, }); const upsertMutation = trpc.emailTemplates.upsert.useMutation({ onSuccess: () => { toast.success("Template enregistré avec succès"); refetch(); }, onError: (error) => { toast.error(`Erreur: ${error.message}`); }, }); const initMutation = trpc.emailTemplates.initializeDefaults.useMutation({ onSuccess: () => { toast.success("Templates par défaut initialisés"); refetch(); }, onError: (error) => { toast.error(`Erreur: ${error.message}`); }, }); // Charger le template sélectionné useEffect(() => { if (currentTemplate) { const newData = { type: currentTemplate.type, name: currentTemplate.name, logoUrl: currentTemplate.logoUrl || "", primaryColor: currentTemplate.primaryColor, headerBgColor: currentTemplate.headerBgColor, headerTextColor: currentTemplate.headerTextColor, headerTitle: currentTemplate.headerTitle, bodyContent: currentTemplate.bodyContent || "", footerText: currentTemplate.footerText || "", active: currentTemplate.active, }; setFormData(newData); // Mettre à jour le contenu de l'éditeur if (editor) { editor.commands.setContent(newData.bodyContent); } } }, [currentTemplate, editor]); const handleSave = () => { upsertMutation.mutate({ ...formData, logoUrl: formData.logoUrl || null, bodyContent: formData.bodyContent || null, footerText: formData.footerText || null, }); }; const handleReset = () => { if (currentTemplate) { setFormData({ type: currentTemplate.type, name: currentTemplate.name, logoUrl: currentTemplate.logoUrl || "", primaryColor: currentTemplate.primaryColor, headerBgColor: currentTemplate.headerBgColor, headerTextColor: currentTemplate.headerTextColor, headerTitle: currentTemplate.headerTitle, bodyContent: currentTemplate.bodyContent || "", footerText: currentTemplate.footerText || "", active: currentTemplate.active, }); } }; const handleInitDefaults = () => { if (confirm("Initialiser les templates par défaut ? Cela ne modifiera pas les templates existants.")) { initMutation.mutate(); } }; // Générer la prévisualisation HTML avec variables remplacées const generatePreviewWithVariables = () => { // Remplacer les variables par des données d'exemple const replaceVariables = (text: string) => { return text .replace(/\{\{nomApprenant\}\}/g, 'Dupont') .replace(/\{\{prenomApprenant\}\}/g, 'Marie') .replace(/\{\{nomFormation\}\}/g, 'Formation Management') .replace(/\{\{nomSequence\}\}/g, 'Séquence 1 - Introduction') .replace(/\{\{dateDebut\}\}/g, '15/01/2025') .replace(/\{\{dateFin\}\}/g, '17/01/2025') .replace(/\{\{lieu\}\}/g, 'Salle de formation A - Bâtiment principal') .replace(/\{\{formateur\}\}/g, 'Jean Martin') .replace(/\{\{datesHTML\}\}/g, '
Date 1 : lundi 15 janvier 2025
Date 2 : mardi 16 janvier 2025
'); }; const bodyWithVars = formData.bodyContent ? replaceVariables(formData.bodyContent) : `

Saisissez le contenu de votre email dans le champ "Corps du message" pour voir la prévisualisation ici...

`; const headerWithVars = replaceVariables(formData.headerTitle); const footerWithVars = formData.footerText ? replaceVariables(formData.footerText) : 'Texte du pied de page'; return `
${formData.logoUrl ? `Logo` : ''}

${headerWithVars}

${bodyWithVars}
`.trim(); }; // Générer la prévisualisation HTML const generatePreview = () => { return `
${formData.logoUrl ? `Logo` : ''}

${formData.headerTitle}

${formData.bodyContent ? formData.bodyContent.replace(/\n/g, '
') : `

Saisissez le contenu de votre email dans le champ "Corps du message" pour voir la prévisualisation ici...

`}
`.trim(); }; const templateTypes = [ { value: "inscription", label: "Confirmation d'inscription" }, { value: "teaser", label: "Email teaser" }, { value: "rappel", label: "Rappel 1" }, { value: "rappelJ1", label: "Rappel 2" }, { value: "rappel3", label: "Rappel 3" }, { value: "rappel4", label: "Rappel 4" }, { value: "rappel5", label: "Rappel 5" }, { value: "rappel6", label: "Rappel 6" }, { value: "reset_password", label: "Réinitialisation de mot de passe" }, ]; return (

Templates d'emails

Personnalisez l'apparence de vos emails automatiques

{(!templates || templates.length === 0) && ( Initialisation requise Aucun template trouvé. Initialisez les templates par défaut pour commencer. )}
{/* Éditeur */} Éditeur de template Modifiez les paramètres du template sélectionné
setFormData({ ...formData, name: e.target.value })} placeholder="Ex: Confirmation d'inscription" />
setFormData({ ...formData, logoUrl: e.target.value })} placeholder="https://exemple.com/logo.png" />
setFormData({ ...formData, headerBgColor: e.target.value })} className="w-16 h-10 p-1" /> setFormData({ ...formData, headerBgColor: e.target.value })} placeholder="#2563eb" />
setFormData({ ...formData, headerTextColor: e.target.value })} className="w-16 h-10 p-1" /> setFormData({ ...formData, headerTextColor: e.target.value })} placeholder="#ffffff" />
setFormData({ ...formData, primaryColor: e.target.value })} className="w-16 h-10 p-1" /> setFormData({ ...formData, primaryColor: e.target.value })} placeholder="#2563eb" />

Utilisée pour les boutons et les accents

setFormData({ ...formData, headerTitle: e.target.value })} placeholder="Formation Manager Itinova" />
{/* Boutons de variables dynamiques */}
{/* Éditeur WYSIWYG TipTap */}
{/* Barre d'outils */} {editor && (
)} {/* Zone d'édition */}

Le contenu du corps du message. Utilisez les boutons ci-dessus pour insérer des variables dynamiques.