/**
* =========================================================
* Logica Lightbox + Commenti + AI per NETVET (WordPress)
* =========================================================
* * Istruzioni di Installazione:
* 1. Carica questo file JS nel tuo footer di WordPress (enqueue script).
* 2. Assicurati che le variabili globali (__app_id, __firebase_config,
* __initial_auth_token) siano disponibili nel contesto del tuo ambiente,
* o usa i valori di fallback se stai testando localmente.
* 3. Assicurati che netvet-lightbox.css sia caricato.
*/

(function() {
// — 1. CONFIGURAZIONE E INIZIALIZZAZIONE —

// Variabili Globali fornite dall’ambiente Canvas/WordPress (modifica i fallback se necessario)
const appId = typeof __app_id !== ‘undefined’ ? __app_id : ‘netvet-default-app’;
const firebaseConfig = typeof __firebase_config !== ‘undefined’ ? JSON.parse(__firebase_config) : {};
const initialAuthToken = typeof __initial_auth_token !== ‘undefined’ ? __initial_auth_token : null;
const GEMINI_MODEL = ‘gemini-2.5-flash-preview-09-2025’;

let db, auth, userId = null;
let isAuthReady = false;
let currentPostId = null;
let commentListenerUnsubscribe = null;
let lightbox;
let lightboxImage;
let postTitleElement;
let postIdDisplay;
let commentsList;
let authorInput;
let commentTextarea;
let submitBtn;
let commentErrorMessage;
let aiStatusMessage;

// — 2. HTML LIGHTBOX (INIETTAZIONE) —
// Inietteremo il markup Lightbox nel DOM all’avvio
const lightboxHTML = `

`;

// — 3. FUNZIONI DI UTILITÀ E API —

// Wrapper per l’importazione dinamica di Firebase
const loadFirebase = () => {
return Promise.all([
import(“https://www.gstatic.com/firebasejs/11.6.1/firebase-app.js”).then(m => m.initializeApp),
import(“https://www.gstatic.com/firebasejs/11.6.1/firebase-auth.js”).then(m => ({ getAuth: m.getAuth, signInAnonymously: m.signInAnonymously, signInWithCustomToken: m.signInWithCustomToken, onAuthStateChanged: m.onAuthStateChanged })),
import(“https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js”).then(m => ({ getFirestore: m.getFirestore, collection: m.collection, query: m.query, where: m.where, orderBy: m.orderBy, onSnapshot: m.onSnapshot, addDoc: m.addDoc, serverTimestamp: m.serverTimestamp }))
]);
};

const initFirebase = async () => {
try {
// Importa i moduli necessari
const [initializeApp, authModules, firestoreModules] = await loadFirebase();

const app = initializeApp(firebaseConfig);
db = firestoreModules.getFirestore(app);
auth = authModules.getAuth(app);

// Gestione dell’autenticazione
authModules.onAuthStateChanged(auth, async (user) => {
if (user) {
userId = user.uid;
isAuthReady = true;
} else {
if (initialAuthToken) {
await authModules.signInWithCustomToken(auth, initialAuthToken);
} else {
await authModules.signInAnonymously(auth);
}
}
if (!userId) {
userId = auth.currentUser?.uid || crypto.randomUUID();
}
isAuthReady = true;
});

} catch (error) {
console.error(“Errore nell’inizializzazione di Firebase:”, error);
}
};

const callGeminiAPI = async (systemPrompt, userQuery) => {
const apiKey = “”;
const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${apiKey}`;

const payload = {
contents: [{ parts: [{ text: userQuery }] }],
systemInstruction: {
parts: [{ text: systemPrompt }]
},
};

const maxRetries = 5;
for (let i = 0; i < maxRetries; i++) { try { const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { if (response.status === 429 && i < maxRetries - 1) { const delay = Math.pow(2, i) * 1000 + Math.random() * 1000; await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw new Error(`API call failed with status: ${response.status}`);
}

const result = await response.json();
const text = result.candidates?.[0]?.content?.parts?.[0]?.text;

if (text) {
return text;
} else {
throw new Error(“API response was valid but contained no text content.”);
}

} catch (error) {
console.error(“Errore durante la chiamata a Gemini API:”, error);
if (i === maxRetries – 1) {
throw new Error(“Fallito il tentativo di comunicazione con l’AI dopo diversi tentativi.”);
}
}
}
};

// — 4. FUNZIONI DI INTERAZIONE DEL LIGHTBOX —

const checkFormValidity = () => {
const author = authorInput.value;
const content = commentTextarea.value;

submitBtn.disabled = !(author.trim() && content.trim());
};

window.handleCommentSubmission = async () => {
const author = authorInput.value;
const content = commentTextarea.value;

if (!isAuthReady) {
commentErrorMessage.textContent = “Attendi la connessione al database. Riprova tra un attimo.”;
return;
}

if (!content.trim() || !author.trim()) {
commentErrorMessage.textContent = “Per favor, compila tutti i campi.”;
return;
}
commentErrorMessage.textContent = “”;

// Usiamo i moduli Firebase importati
const firestoreModules = await import(“https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js”);

const commentsCollectionPath = `/artifacts/${appId}/public/data/post_comments`;

try {
await firestoreModules.addDoc(firestoreModules.collection(db, commentsCollectionPath), {
postId: currentPostId,
authorId: userId,
authorName: author.trim(),
content: content.trim(),
timestamp: firestoreModules.serverTimestamp(),
});

authorInput.value = ”;
commentTextarea.value = ”;
submitBtn.disabled = true;

} catch (e) {
console.error(“Errore nell’aggiungere il commento: “, e);
commentErrorMessage.textContent = “Si è verificato un errore durante l’invio. Riprova.”;
}
};

window.loadComments = async (postId) => {
commentsList.innerHTML = ‘

‘;

if (!db || !isAuthReady) {
setTimeout(() => window.loadComments(postId), 300);
return;
}

const firestoreModules = await import(“https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js”);
const { collection, query, where, orderBy, onSnapshot } = firestoreModules;

const commentsCollectionPath = `/artifacts/${appId}/public/data/post_comments`;

const q = query(
collection(db, commentsCollectionPath),
where(“postId”, “==”, postId),
orderBy(“timestamp”, “desc”)
);

const unsubscribe = onSnapshot(q, (querySnapshot) => {
let html = ”;
if (querySnapshot.empty) {
html = ‘

Ancora nessun commento. Scrivine uno!

‘;
} else {
querySnapshot.forEach((doc) => {
const data = doc.data();
const content = data.content.trim();
const date = data.timestamp ? new Date(data.timestamp.toDate()).toLocaleDateString(‘it-IT’) : ‘In attesa…’;

let aiButton = ”;
if (content.length > 200) {
// Usa la classe gemini-purple definita nel CSS se Tailwind non è globale
aiButton = ``;
}

html += `

${data.authorName}
${date}
${aiButton}

${content}

`;
});
}
commentsList.innerHTML = html;
}, (error) => {
console.error(“Errore in onSnapshot: “, error);
commentsList.innerHTML = `

Errore nel caricamento dei commenti.

`;
});

return unsubscribe;
};

window.summarizeComment = async (encodedContent, commentId) => {
const content = decodeURIComponent(encodedContent);
const summaryDiv = document.getElementById(`summary-${commentId}`);

summaryDiv.classList.remove(‘hidden’);
summaryDiv.innerHTML = ` Riassunto in corso…`;

try {
const systemPrompt = “Sei un assistente AI per un blog. Il tuo compito è riassumere i commenti degli utenti in una singola frase concisa in italiano, mantenendo un tono neutrale.”;
const userQuery = `Riassumi il seguente commento: “${content}”`;

const summary = await callGeminiAPI(systemPrompt, userQuery);

summaryDiv.innerHTML = `Riassunto AI: ${summary}`;

} catch (error) {
summaryDiv.innerHTML = `Errore AI: Impossibile generare il riassunto.`;
}
};

window.generateReplySuggestion = async () => {
const btn = document.getElementById(‘generate-reply-btn’);
const textarea = commentTextarea;
const statusDiv = aiStatusMessage;

const commentsContainer = commentsList;
const lastComment = commentsContainer.querySelector(‘.comment-item p.text-gray-700:first-child’)?.textContent || “Nessun commento disponibile.”;
const postTitle = postTitleElement.textContent;

btn.disabled = true;
statusDiv.innerHTML = ` Generazione suggerimento…`;
statusDiv.classList.remove(‘hidden’, ‘text-red-500’, ‘text-green-500’);
statusDiv.classList.add(‘text-gray-600’, ‘flex’, ‘items-center’, ‘mb-2’);

try {
const systemPrompt = `Sei un moderatore di un blog. Devi scrivere un breve suggerimento di risposta (massimo due frasi in italiano) all’ultimo commento. Il tuo tono deve essere amichevole e incoraggiante. Rispondi solo con il testo del suggerimento.`;
const userQuery = `Titolo del post: ${postTitle}. Ultimo commento: “${lastComment}”. Genera una risposta.`;

const replySuggestion = await callGeminiAPI(systemPrompt, userQuery);

textarea.value = replySuggestion.trim();
statusDiv.innerHTML = `Suggerimento AI caricato! Modifica pure prima di inviare.`;
statusDiv.classList.remove(‘text-gray-600’);
statusDiv.classList.add(‘text-green-600’);
checkFormValidity();

} catch (error) {
statusDiv.innerHTML = `Errore AI: Impossibile generare la risposta.`;
statusDiv.classList.remove(‘text-gray-600’);
statusDiv.classList.add(‘text-red-500’);
} finally {
btn.disabled = false;
}
};

window.openLightbox = (imageUrl, postId, postTitle) => {

currentPostId = postId;

lightboxImage.src = imageUrl;
postTitleElement.textContent = postTitle;
postIdDisplay.textContent = postId;

lightbox.classList.add(‘active’);
document.body.style.overflow = ‘hidden’;

if (window.loadComments) {
if (commentListenerUnsubscribe) {
commentListenerUnsubscribe();
}
commentListenerUnsubscribe = window.loadComments(postId);
}

// Reset form e stato AI
authorInput.value = ”;
commentTextarea.value = ”;
commentErrorMessage.textContent = “”;
aiStatusMessage.classList.add(‘hidden’);

// Assicurati che non sia in modalità fullscreen quando si apre
if (document.fullscreenElement) {
document.exitFullscreen();
}
updateFullscreenIcon(false);
checkFormValidity();
}

window.closeLightbox = (event) => {
if (event && event.target.closest(‘.lightbox-content-wrapper’)) {
return;
}

if (commentListenerUnsubscribe) {
commentListenerUnsubscribe();
commentListenerUnsubscribe = null;
}

if (document.fullscreenElement) {
document.exitFullscreen();
}

lightbox.classList.remove(‘active’);
document.body.style.overflow = ‘auto’;
currentPostId = null;
}

const updateFullscreenIcon = (isEntering) => {
const iconElement = document.getElementById(‘fullscreen-icon’);
if (!iconElement) return;

// Icone SVG per uscire/entrare da fullscreen
const exitPath = “M5 13H1v4m0 0h4m-4 0l5-5m7 5h4v-4m0 0h-4m4 0l-5 5m5-18h-4v4m0 0h4m-4 0l5 5m-9-9H5v4m0 0H1m4 0l5 5”;
const enterPath = “M4 8V4m0 0h4M4 4l5 5m11-5h-4m4 0v4m0-4l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4”;

if (isEntering) {
iconElement.querySelector(‘path’).setAttribute(‘d’, exitPath);
} else {
iconElement.querySelector(‘path’).setAttribute(‘d’, enterPath);
}
};

window.toggleFullscreen = () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
if (lightbox.requestFullscreen) {
lightbox.requestFullscreen();
} else if (lightbox.webkitRequestFullscreen) {
lightbox.webkitRequestFullscreen();
} else if (lightbox.msRequestFullscreen) {
lightbox.msRequestFullscreen();
}
}
};

// — 5. INITIALIZZAZIONE DOM E ASCOLTATORI —

document.addEventListener(‘DOMContentLoaded’, () => {
// Inietta il Lightbox nel body
document.body.insertAdjacentHTML(‘beforeend’, lightboxHTML);

// Cattura gli elementi una volta iniettati
lightbox = document.getElementById(‘lightbox’);
lightboxImage = document.getElementById(‘lightbox-image’);
postTitleElement = document.getElementById(‘post-title’);
postIdDisplay = document.getElementById(‘post-id-display’);
commentsList = document.getElementById(‘comments-list’);
authorInput = document.getElementById(‘author-input’);
commentTextarea = document.getElementById(‘comment-textarea’);
submitBtn = document.getElementById(‘submit-btn’);
commentErrorMessage = document.getElementById(‘comment-error-message’);
aiStatusMessage = document.getElementById(‘ai-status-message’);

// Ascoltatori per l’attivazione del Lightbox (Cattura l’evento su qualsiasi trigger)
document.addEventListener(‘click’, (event) => {
const target = event.target;
if (target.classList.contains(‘lightbox-trigger’)) {
event.preventDefault();

const imageUrl = target.src;
const postId = target.getAttribute(‘data-post-id’);
const postTitle = target.getAttribute(‘data-post-title’) || document.title; // Usa il titolo della pagina come fallback

if (postId && imageUrl) {
window.openLightbox(imageUrl, postId, postTitle);
} else {
console.error(“Attributi lightbox-trigger mancanti (data-post-id e src).”);
}
}
});

// Ascoltatori per la validazione del form
authorInput.addEventListener(‘input’, checkFormValidity);
commentTextarea.addEventListener(‘input’, checkFormValidity);

// Ascoltatore per tasto ESC
document.addEventListener(‘keydown’, function(e) {
if (e.key === ‘Escape’ && lightbox.classList.contains(‘active’)) {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
window.closeLightbox();
}
}
});

// Ascoltatore per i cambiamenti di fullscreen
document.addEventListener(‘fullscreenchange’, () => {
if (!document.fullscreenElement) {
lightbox.classList.remove(‘fullscreen-active’);
updateFullscreenIcon(false);
} else {
lightbox.classList.add(‘fullscreen-active’);
updateFullscreenIcon(true);
}
});

// Inizializza Firebase
initFirebase();
});

})();

// Nota: Le funzioni globali (window.openLightbox, window.closeLightbox, etc.) sono
// necessarie per l’onclick inline del markup HTML e per l’interazione tra i moduli.

×

🏙️ Seleziona Vetrina

Chiudi Finestra

⚡ Azioni Rapide

⭐ I MIEI PREFERITI SALVATI

Chiudi Finestra

⚙️ I Miei Gestionali

Chiudi Finestra

📂 Archivi Clienti e Cloud

Chiudi Finestra
Torna in alto