| <H2>
Asistente de Ventas Zeta
(function() {
'use strict';
// Efecto ripple en el botón
document.addEventListener("DOMcontentLoaded", function() {
// PERMITIR ABRIR EL CHAT DESDE CUALQUIER ENLACE CON href="#zaragonjg-open-chat"
document.addEventListener('click', function(e) {
const link = e.target.closest('a[href="#zaragonjg-open-chat"]');
if (link) {
e.preventDefault();
const chatButton = document.getElementById('zaragonjg-open-chat');
if (chatButton) chatButton.click();
}
});
const button = document.getElementById("zaragonjg-open-chat");
if (button) {
button.addEventListener("click", function(e) {
const existingRipples = button.querySelectorAll(".ripple");
existingRipples.forEach(r => r.remove());
const ripple = document.createElement("span");
ripple.classList.add("ripple");
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = `${size}px`;
ripple.style.left = `${x}px`;
ripple.style.top = `${y}px`;
button.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
});
}
});
// =========================================================================
// LÓGICA PRINCIPAL DEL BOT
// =========================================================================
document.addEventListener('DOMcontentLoaded', () => {
const widgetContainer = document.getElementById('zaragonjg-service-widget');
if (!widgetContainer) return;
const openModalBtn = widgetContainer.querySelector('#zaragonjg-open-chat');
const closeModalBtn = widgetContainer.querySelector('#closeModalBtn');
const serviceModal = widgetContainer.querySelector('#serviceModal');
const messageContainer = widgetContainer.querySelector('#messageContainer');
const chatContainer = widgetContainer.querySelector('#chatContainer');
// Inicializar Stripe
const stripe = zaragonjg_stripe_public_key ? Stripe(zaragonjg_stripe_public_key) : null;
let formData = {};
let calculatedPrice = 0;
let priceBeforeTaxes = 0;
// Función para calcular precio final con impuestos españoles
// IRPF solo aplica a Comercio/Empresa, no a Persona
function calculateFinalPrice(basePrice) {
const iva = basePrice * 0.21;
const applyIrpf = formData.clientType === 'empresa';
const irpf = applyIrpf ? basePrice * -0.01 : 0;
return {
subtotal: basePrice,
iva: Math.round(iva * 100) / 100,
irpf: Math.round(irpf * 100) / 100,
total: Math.round((basePrice + iva + irpf) * 100) / 100,
hasIrpf: applyIrpf
};
}
// Contadores de muebles y cajas
let furnitureCount = {
camas: 0,
armarios: 0,
modulares: 0
};
let extraBoxes = 0;
const includedBoxes = 15;
// Base de datos de precios
const pricingData = {
porte: { min: 100, max: 300 },
local: {
estudio: { min: 300, max: 450, volume: '5-10' },
hab2: { min: 400, max: 650, volume: '10-15' },
hab3: { min: 600, max: 900, volume: '15-25' },
hab4: { min: 800, max: 1200, volume: '25-30' },
chalet: { min: 1000, max: 1500, volume: '30+' }
},
provincial: { min: 450, max: 850 },
valencia: { min: 500, max: 850 },
madrid: { min: 600, max: 1000 },
barcelona: { min: 600, max: 1100 },
nacional: { min: 1200, max: 2800 },
servicios: {
embalaje: { min: 150, max: 350 },
montaje: { min: 150, max: 450 },
guardamuebles: { min: 100, max: 250 }
}
};
// FAQ
const faqData = [
{
q: "¿Cómo se calcula una mudanza?",
a: "El precio se basa en: volumen de objetos (m³), distancia entre origen y destino, mano de obra necesaria, accesos del inmueble y servicios adicionales contratados."
},
{
q: "¿Qué incluye el servicio?",
a: "Incluye: transporte, carga y descarga, operarios profesionales, protección básica del mobiliario y seguro básico de transporte."
},
{
q: "¿Cuánto cuesta una mudanza local?",
a: "En Zaragoza capital: desde 300€ para estudios hasta 1.500€ para chalets. El precio varía según tamaño de vivienda y servicios adicionales."
},
{
q: "¿Ofrecen servicio de embalaje?",
a: "Sí, ofrecemos embalaje profesional con cajas reforzadas y protección de objetos frágiles. Precio: 50-350€ según volumen."
},
{
q: "¿Tienen guardamuebles?",
a: "Sí, contamos con almacenaje seguro y vigilado desde 100€/mes. Incluye seguimiento 24/7 y acceso cuando lo necesites."
},
{
q: "¿Cómo reservo el servicio?",
a: "Puedes solicitar presupuesto aquí mismo. Para mudanzas, realizamos un cargo de 50€ que confirma tu reserva. Contáctanos para más información."
}
];
// Funciones auxiliares
function resetForm() {
formData = {
serviceType: '',
clientType: '',
fullname: '',
phone: '',
serviceDate: '',
mudanzaType: '',
roomCount: '',
originAddress: '',
destinationAddress: '',
destination: '',
additionalServices: [],
observations: ''
};
calculatedPrice = 0;
furnitureCount = { camas: 0, armarios: 0, modulares: 0 };
extraBoxes = 0;
messageContainer.innerHTML = '';
}
function addMessage(text, sender) {
const messageDiv = document.createElement('div');
messageDiv.classList.add('message-widget', sender + '-widget');
if (sender === 'assistant') {
const avatar = document.createElement('img');
avatar.src = 'https://mudanzaszaragonjg.com/wp-content/uploads/2025/11/Zeta-Bot.svg';
avatar.alt = 'Zeta';
avatar.classname = 'assistant-avatar-widget';
messageDiv.appendChild(avatar);
}
const messageText = document.createElement('div');
messageText.innerHTML = text;
messageDiv.appendChild(messageText);
messageContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
function showTypingIndicator() {
const typingDiv = document.createElement('div');
typingDiv.classname = 'typing-indicator-widget';
typingDiv.id = 'typingIndicator';
for (let i = 0; i < 3; i++) {
const dot = document.createElement('div');
dot.classname = 'typing-dot-widget';
typingDiv.appendChild(dot);
}
messageContainer.appendChild(typingDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
function hideTypingIndicator() {
const indicator = document.getElementById('typingIndicator');
if (indicator) indicator.remove();
}
function simulateTyping(callback, delay = 1000) {
showTypingIndicator();
setTimeout(() => {
hideTypingIndicator();
callback();
}, delay);
}
function addOptions(options, callback, allowMultiple = false) {
const optionsDiv = document.createElement('div');
optionsDiv.classList.add('options-container-widget');
if (allowMultiple) {
const selected = [];
options.forEach(option => {
const btn = document.createElement('button');
btn.classList.add('option-btn-widget');
btn.textcontent = option.name;
btn.onclick = () => {
if (selected.includes(option.id)) {
selected.splice(selected.indexOf(option.id), 1);
btn.style.background = '#e8f5e9';
} else {
selected.push(option.id);
btn.style.background = '#c8e6c9';
}
};
optionsDiv.appendChild(btn);
});
const confirmBtn = document.createElement('button');
confirmBtn.classList.add('option-btn-widget');
confirmBtn.textcontent = 'Confirmar';
confirmBtn.style.cssText = 'background: #4caf50; color: white;';
confirmBtn.onclick = () => {
optionsDiv.remove();
callback(selected);
};
optionsDiv.appendChild(confirmBtn);
} else {
options.forEach(option => {
const btn = document.createElement('button');
btn.classList.add('option-btn-widget');
btn.textcontent = option.name;
btn.onclick = () => {
optionsDiv.remove();
callback(option.id);
};
optionsDiv.appendChild(btn);
});
}
messageContainer.appendChild(optionsDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
function addInput(placeholder, callback, type = 'text') {
const inputDiv = document.createElement('div');
inputDiv.classList.add('input-container-widget');
const input = document.createElement('input');
input.type = type;
input.placeholder = placeholder;
const btn = document.createElement('button');
btn.textcontent = 'Enviar';
const submit = () => {
if (input.value.trim() !== '') {
inputDiv.remove();
callback(input.value.trim());
}
};
btn.onclick = submit;
input.addEventListener('keypress', (e) => {
if (e.key === 'Enter') submit();
});
inputDiv.appendChild(input);
inputDiv.appendChild(btn);
messageContainer.appendChild(inputDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
input.focus();
}
function addDateSelector(callback) {
const container = document.createElement('div');
container.classList.add('date-selector-container');
const dateInput = document.createElement('input');
dateInput.type = 'date';
dateInput.min = new Date().toISOString().split('T')[0];
container.appendChild(dateInput);
const btn = document.createElement('button');
btn.textcontent = 'Confirmar';
container.appendChild(btn);
messageContainer.appendChild(container);
chatContainer.scrollTop = chatContainer.scrollHeight;
dateInput.focus();
btn.onclick = () => {
if (!dateInput.value) return;
container.remove();
const formattedDate = new Date(dateInput.value + 'T00:00:00')
.toLocaleDateString('es-ES', { day: 'numeric', month: 'long', year: 'numeric' });
callback(formattedDate);
};
}
// =========================================================================
// FLUJOS DEL BOT - MENÚ PRINCIPAL
// =========================================================================
function showMainMenu() {
simulateTyping(() => {
addMessage("¿Qué necesitas?", 'assistant');
setTimeout(() => {
addOptions([
{ id: 'porte', name: '1️⃣ Porte pequeño' },
{ id: 'local', name: '2️⃣ Mudanza local Zaragoza' },
{ id: 'provincial', name: '3️⃣ Mudanza provincial/nacional' },
{ id: 'guardamuebles', name: '4️⃣ Guardamuebles' },
{ id: 'faq', name: '❓ Preguntas Frecuentes' }
], (choice) => {
if (choice === 'faq') {
showFAQ();
} else if (choice === 'porte') {
addMessage('1️⃣ Porte pequeño', 'user');
setTimeout(() => startPorteFlow(), 800);
} else if (choice === 'local') {
addMessage('2️⃣ Mudanza local Zaragoza', 'user');
setTimeout(() => startLocalFlow(), 800);
} else if (choice === 'provincial') {
addMessage('3️⃣ Mudanza provincial/nacional', 'user');
setTimeout(() => startProvincialNacionalFlow(), 800);
} else if (choice === 'guardamuebles') {
addMessage('4️⃣ Guardamuebles', 'user');
setTimeout(() => startGuardamueblesFlow(), 800);
}
});
}, 500);
});
}
// FAQ
function showFAQ() {
addMessage('❓ Preguntas Frecuentes', 'user');
simulateTyping(() => {
addMessage("Estas son las preguntas más frecuentes:", 'assistant');
setTimeout(() => {
const faqOptions = faqData.map((item, idx) => ({ id: idx, name: item.q }));
faqOptions.push({ id: 'menu', name: '🏠 Volver al Menú' });
addOptions(faqOptions, (idx) => {
if (idx === 'menu') {
addMessage('🏠 Volver al Menú', 'user');
setTimeout(() => showMainMenu(), 800);
} else {
addMessage(faqData[idx].q, 'user');
simulateTyping(() => {
addMessage(faqData[idx].a, 'assistant');
setTimeout(() => {
simulateTyping(() => {
addMessage("¿Necesitas algo más?", 'assistant');
setTimeout(() => {
addOptions([
{ id: 'menu', name: '🏠 Menú Principal' },
{ id: 'mudanza', name: '🚚 Solicitar Mudanza' }
], (choice) => {
if (choice === 'menu') {
addMessage('🏠 Volver al Menú', 'user');
setTimeout(() => showMainMenu(), 800);
} else {
addMessage('🚚 Solicitar Mudanza', 'user');
setTimeout(() => startLocalFlow(), 800);
}
});
}, 500);
}, 1000);
}, 1500);
}, 1000);
}
});
}, 500);
});
}
// FLUJO 1: PORTE PEQUEÑO
function startPorteFlow() {
formData.serviceType = 'mudanza';
formData.mudanzaType = 'porte';
simulateTyping(() => {
addMessage("Para pequeños transportes trabajamos desde:", 'assistant');
setTimeout(() => {
const summaryDiv = document.createElement('div');
summaryDiv.classname = 'price-summary-widget';
summaryDiv.innerHTML = `
Hasta 5 m³ → 100 - 300 € </H2> |
Social
Social Data
Cost and overhead previously rendered this semi-public form of communication unfeasible.
But advances in social networking technology from 2004-2010 has made broader concepts of sharing possible.