From f38ad1b6e7bb2275d27b64e89938bc5b62c40cdc Mon Sep 17 00:00:00 2001 From: fcarraUniSa Date: Tue, 23 Dec 2025 12:23:30 +0100 Subject: [PATCH] Update TemplateEditor.tsx --- components/TemplateEditor.tsx | 167 ++++++++-------------------------- 1 file changed, 40 insertions(+), 127 deletions(-) diff --git a/components/TemplateEditor.tsx b/components/TemplateEditor.tsx index 2f57e27..c967d18 100644 --- a/components/TemplateEditor.tsx +++ b/components/TemplateEditor.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { EmailTemplate } from '../types'; -import { saveTemplate, generateSQL, generateSelectSQL, getTemplates, generateTemplateKey, generateN8nCode } from '../services/storage'; +import { saveTemplate, generateSQL, generateSelectSQL, getTemplates, generateTemplateKey, generateN8nCode, generateUUID } from '../services/storage'; import { generateEmailContent } from '../services/geminiService'; import RichTextEditor from './RichTextEditor'; import { @@ -15,18 +15,6 @@ interface Props { onSave: () => void; } -// Fallback for crypto.randomUUID in non-secure (HTTP) contexts -const generateUUID = () => { - if (typeof crypto !== 'undefined' && crypto.randomUUID) { - return crypto.randomUUID(); - } - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - const r = Math.random() * 16 | 0; - const v = c === 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -}; - const DEFAULT_HEADER = `

La Mia Azienda

`; @@ -78,21 +66,20 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { const newKey = generateTemplateKey(name); if (!newKey) { - setNameError('Il nome del template non può essere vuoto o contenere solo simboli.'); + setNameError('Il nome del template non può essere vuoto.'); return; } setIsSaving(true); + console.log("Saving process started for:", name); + try { - console.log("Inizio processo di salvataggio per:", name); - - // Check for duplicates + // 1. Get current templates to check duplicates let allTemplates: EmailTemplate[] = []; try { allTemplates = await getTemplates(); } catch (err) { - console.error("Errore durante il recupero dei template esistenti:", err); - // Non blocchiamo necessariamente, ma avvisiamo + console.warn("Could not fetch templates for duplicate check, proceeding anyway...", err); } const isDuplicate = allTemplates.some(t => { @@ -118,13 +105,13 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { updatedAt: new Date().toISOString() }; - console.log("Invio dati al server...", newTemplate); + console.log("Sending POST to server with data:", newTemplate); await saveTemplate(newTemplate); - console.log("Salvataggio completato con successo"); + console.log("Save successful!"); onSave(); } catch (e: any) { - console.error("ERRORE SALVATAGGIO:", e); - alert(`Errore: ${e.message || 'Impossibile salvare il template'}`); + console.error("SAVE ERROR DETAILS:", e); + alert(`Errore di salvataggio: ${e.message}`); } finally { setIsSaving(false); } @@ -231,7 +218,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { placeholder="es. Email di Benvenuto" /> {nameError &&

{nameError}

} -

Deve essere univoco. Usato per generare la chiave DB: {generateTemplateKey(name) || '...'}

+

Deve essere univoco. Chiave DB: {generateTemplateKey(name) || '...'}

@@ -240,7 +227,7 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { value={description} onChange={e => setDescription(e.target.value)} className="w-full px-3 py-2 border border-slate-300 rounded-md focus:ring-2 focus:ring-brand-500 focus:border-brand-500 outline-none bg-white resize-none text-sm" - placeholder="Note interne (es. Usato per i nuovi iscritti)" + placeholder="Note interne..." rows={2} />
@@ -252,18 +239,17 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { value={subject} onChange={e => setSubject(e.target.value)} className="w-full px-3 py-2 border border-slate-300 rounded-md focus:ring-2 focus:ring-brand-500 focus:border-brand-500 outline-none bg-white" - placeholder="Oggetto... (supporta {{placeholder}})" + placeholder="Oggetto..." />
- Variabili Attive - Rilevate automaticamente dal testo + Variabili
- {detectedVars.length === 0 && Nessuna variabile rilevata. Scrivi {'{{nome}}'} per aggiungerne una.} + {detectedVars.length === 0 && Nessuna variabile. Usa {'{{nome}}'}.} {detectedVars.map(v => ( {`{{${v}}}`} @@ -290,16 +276,14 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {
- -
- -
+ +
@@ -307,34 +291,26 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { key={activeTab} value={getActiveContent()} onChange={setActiveContent} - placeholder={`Crea qui la sezione ${tabNames[activeTab]}...`} + placeholder={`Scrivi qui...`} className="h-full shadow-sm" />
- -

- Usa il pulsante "Variabile" nella toolbar per inserire placeholder come {'{{nome}}'}. -

-
+
- Anteprima Live + Anteprima -
- Renderizzato come HTML standard -
Oggetto: -

{subject.replace(/\{\{([\w\d_-]+)\}\}/g, (match, p1) => `${match}`)}

+

{subject}

-
@@ -349,68 +325,18 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => {

- Dettagli Integrazione + Integrazione

- +
- -
-
-
- -
-
-                        {currentInsertSql}
-                      
- -
-
- -
- -
-
-                        {currentSelectSql}
-                      
- -
-
-
- +
- -
-
-                      {currentN8nCode}
-                    
- -
-

- Incolla questo codice in un Nodo Code collegato dopo il tuo nodo SQL. Sostituisci REPLACE_WITH_VALUE con le variabili reali (es. $('NodeName').item.json.name). -

+ +
{currentInsertSql}
+
+
+ +
{currentN8nCode}
@@ -420,34 +346,21 @@ const Editor: React.FC = ({ initialTemplate, onBack, onSave }) => { {showAiModal && (
-

- - Generatore Contenuti IA -

-

- Descrivi cosa vuoi per la sezione {tabNames[activeTab]}. - L'IA genererà il codice HTML con i placeholder necessari. -

+

Generatore IA