let currentDate = new Date();
let selectedDate = null;
let selectedTime = null;
let occupiedSlots = {};
const demoData = {
fecha: null,
hora: null,
nombre: '',
apellido: '',
email: '',
telefono: '',
empresa: '',
cargo: '',
tamano: '',
industria: '',
notas: '',
codigoPromo: null
};
function parseOccupiedDates(fechasArray) {
occupiedSlots = {};
fechasArray.forEach(fechaISO => {
const [datePart, timePart] = fechaISO.split('T');
const [hours, minutes] = timePart.split(':');
const timeSlot = `${hours}:${minutes}`;
if (!occupiedSlots[datePart]) {
occupiedSlots[datePart] = [];
}
occupiedSlots[datePart].push(timeSlot);
});
}
// Horarios disponibles
const timeSlots = [
{ time: '09:00', label: '9:00 AM' },
{ time: '10:00', label: '10:00 AM' },
{ time: '11:00', label: '11:00 AM' },
{ time: '12:00', label: '12:00 PM' },
{ time: '13:00', label: '1:00 PM' },
{ time: '14:00', label: '2:00 PM' },
{ time: '15:00', label: '3:00 PM' },
{ time: '16:00', label: '4:00 PM' },
{ time: '17:00', label: '5:00 PM' }
];
function initCalendar() {
renderCalendar(currentDate);
}
function isBusinessDay(date) {
const day = date.getDay();
return day !== 0 && day !== 6;
}
function getMinimumDate() {
let minDate = new Date();
let businessDaysCount = 0;
while (businessDaysCount < 2) {
minDate.setDate(minDate.getDate() + 1);
if (isBusinessDay(minDate)) {
businessDaysCount++;
}
}
return minDate;
}
function isDateFullyOccupied(date) {
// Un día está "lleno" cuando todos los horarios definidos en timeSlots
// ya aparecen en occupiedSlots (suma de demos agendadas + bloqueos
// administrativos). Usar every() es más robusto que comparar longitudes
// porque tolera duplicados o entradas fuera del rango definido.
const d = new Date(date);
d.setHours(0, 0, 0, 0);
const dateKey = d.toISOString().split('T')[0];
const occupied = occupiedSlots[dateKey] || [];
if (occupied.length < timeSlots.length) return false;
return timeSlots.every(slot => occupied.includes(slot.time));
}
function isDateSelectable(date) {
const minDate = getMinimumDate();
minDate.setHours(0, 0, 0, 0);
const checkDate = new Date(date);
checkDate.setHours(0, 0, 0, 0);
return isBusinessDay(date)
&& checkDate >= minDate
&& !isDateFullyOccupied(date);
}
function renderCalendar(date) {
const year = date.getFullYear();
const month = date.getMonth();
const monthNames = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
$('#monthYear').text(`${monthNames[month]} ${year}`);
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const prevLastDay = new Date(year, month, 0);
const grid = $('#calendarGrid');
grid.find('.calendar-day').remove();
const firstDayOfWeek = firstDay.getDay();
for (let i = firstDayOfWeek - 1; i >= 0; i--) {
const day = prevLastDay.getDate() - i;
const dayDate = new Date(year, month - 1, day);
const dayDiv = $('
')
.addClass('calendar-day other-month disabled')
.text(day);
grid.append(dayDiv);
}
const today = new Date();
today.setHours(0, 0, 0, 0);
for (let day = 1; day <= lastDay.getDate(); day++) {
const dayDate = new Date(year, month, day);
const dayDiv = $('
')
.addClass('calendar-day')
.text(day);
if (dayDate.getTime() === today.getTime()) {
dayDiv.addClass('today');
}
if (!isDateSelectable(dayDate)) {
dayDiv.addClass('disabled');
} else {
dayDiv.click(function() {
selectDate(dayDate);
});
}
if (selectedDate && dayDate.getTime() === selectedDate.getTime()) {
dayDiv.addClass('selected');
}
grid.append(dayDiv);
}
const remainingDays = 42 - grid.find('.calendar-day').length;
for (let day = 1; day <= remainingDays; day++) {
const dayDiv = $('
')
.addClass('calendar-day other-month disabled')
.text(day);
grid.append(dayDiv);
}
const minDate = getMinimumDate();
const prevMonth = new Date(year, month - 1, 1);
if (prevMonth < new Date(minDate.getFullYear(), minDate.getMonth(), 1)) {
$('#prevMonth').prop('disabled', true);
} else {
$('#prevMonth').prop('disabled', false);
}
}
function selectDate(date) {
selectedDate = new Date(date);
selectedDate.setHours(0, 0, 0, 0);
demoData.fecha = selectedDate.toISOString().split('T')[0];
selectedTime = null;
demoData.hora = null;
$('#summaryTime, #summaryTime2, #confirmTime').text('-');
renderCalendar(currentDate);
updateSelectedDateDisplay();
renderTimeSlots();
changeStep(2);
}
function updateSelectedDateDisplay() {
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
const dateStr = selectedDate.toLocaleDateString('es-MX', options);
$('#selectedDateDisplay').text(dateStr);
$('#summaryDate, #summaryDate2, #confirmDate').text(dateStr);
}
function renderTimeSlots() {
const container = $('#timeSlotsContainer');
container.empty();
const selectedDateStr = demoData.fecha;
const occupiedTimes = occupiedSlots[selectedDateStr] || [];
timeSlots.forEach(slot => {
const isOccupied = occupiedTimes.includes(slot.time);
const slotDiv = $('
')
.addClass('time-slot')
.html(`
${slot.label}
${isOccupied ? 'No disponible' : ''}
`);
if (isOccupied) {
slotDiv.addClass('disabled');
slotDiv.css('cursor', 'not-allowed');
} else {
slotDiv.click(function() {
selectTimeSlot(slot);
});
}
if (selectedTime === slot.time) {
slotDiv.addClass('selected');
}
container.append(slotDiv);
});
}
function selectTimeSlot(slot) {
selectedTime = slot.time;
demoData.hora = slot.time;
$('#summaryTime, #summaryTime2, #confirmTime').text(slot.label);
renderTimeSlots();
setTimeout(() => {
changeStep(3);
}, 300);
}
function changeStep(step) {
$('.demo-content').removeClass('active');
$(`#demo-step-${step}`).addClass('active');
$('.step').removeClass('active completed');
for (let i = 1; i <= 4; i++) {
if (i < step) {
$(`#step-ind-${i}`).addClass('completed');
} else if (i === step) {
$(`#step-ind-${i}`).addClass('active');
}
}
}
function submitDemo() {
const form = document.getElementById('demoLeadForm');
if (!form.checkValidity()) {
form.classList.add('was-validated');
return;
}
demoData.nombre = $('#demoNombre').val();
demoData.apellido = $('#demoApellido').val();
demoData.email = $('#demoEmail').val();
demoData.telefono = $('#demoTelefono').val();
demoData.empresa = $('#demoEmpresa').val();
demoData.cargo = $('#demoCargo').val();
demoData.tamano = $('#demoTamano').val();
demoData.industria = $('#demoIndustria').val();
demoData.notas = $('#demoNotas').val();
const codigoPromoActivo = $('#demoCheckCodigoPromo').is(':checked');
demoData.codigoPromo = codigoPromoActivo
? ($('#demoInputCodigoPromo').val().trim() || null)
: null;
const fechaTexto = $('#summaryDate2').text() || demoData.fecha;
const horaTexto = $('#summaryTime2').text() || demoData.hora;
Swal.fire({
title: '¿Confirmar tu demo?',
html: `
Estás por agendar una demo con los siguientes datos:
📅 Fecha: ${fechaTexto}
🕐 Horario: ${horaTexto}
📧 Correo: ${demoData.email}
`,
icon: 'question',
showCancelButton: true,
confirmButtonText: '
Sí, agendar',
cancelButtonText: '
Cancelar',
confirmButtonColor: '#0d6efd',
cancelButtonColor: '#6c757d',
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
enviarDemo();
}
});
}
function enviarDemo() {
Swal.fire({
title: 'Procesando...',
text: 'Estamos agendando tu demo',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
$.ajax({
url: '/landing-page/agendar-demo',
type: 'POST',
headers: {
'X-CSRFToken': TokenFormData().get('csrf_token'),
},
contentType: 'application/json',
data: JSON.stringify(demoData),
success: function(response) {
Swal.close();
$('#confirmEmail').text(demoData.email);
$('#confirmEmailDetail').text(demoData.email);
confetti({
particleCount: 100,
spread: 70,
origin: { y: 0.6 }
});
changeStep(4);
},
error: function(xhr) {
Swal.close();
manejarError(xhr);
}
});
}
function initEventHandlers() {
$('#prevMonth').click(function() {
currentDate.setMonth(currentDate.getMonth() - 1);
renderCalendar(currentDate);
});
$('#nextMonth').click(function() {
currentDate.setMonth(currentDate.getMonth() + 1);
renderCalendar(currentDate);
});
}
function openTermsConditions() {
window.open("/terminoscondiciones", "Términos y Condiciones", 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,width=630,height=700');
}
function openAvisoPrivacidad() {
window.open("/avisoprivacidad", "Aviso de Privacidad", 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,width=630,height=700');
}