document.addEventListener('DOMContentLoaded', () => { const initialEvents = [ { id: "ev1", title: "Seminario: Redes 6G", startDate: "2025-10-08", endDate: "2025-10-08", time: "10:00", description: "Charla sobre avances.", campus: "Campus San Joaquin", public: "Estudiantes", category: "Seminario", status: "Programado", duration: "1 hora", organizerUnit: "Departamento Académico", specificDepartment: "Departamento de Electronica" }, { id: "ev2", title: "Congreso de IA", startDate: "2025-10-15", endDate: "2025-10-17", time: "09:00", description: "Congreso internacional de tres días.", campus: "Campus Valparaiso", public: "Profesores", category: "Conferencia", status: "Programado", duration: "Día completo", organizerUnit: "Departamento Académico", specificDepartment: "Departamento de Informatica" }, { id: "ev3", title: "Ceremonia Bienvenida", startDate: "2025-11-05", endDate: "2025-11-05", time: "11:00", description: "Acto oficial.", campus: "Campus Viña del Mar", public: "Comunidad", category: "Ceremonia", status: "Programado", duration: "2 horas", organizerUnit: "Departamento Académico", specificDepartment: "Vicerrectoria" } ]; let events = JSON.parse(localStorage.getItem('events')) || initialEvents; let loggedIn = false; let currentDate = new Date(2025, 9, 1); let selectedDate = null; let modalMode = 'create'; let editingEventId = null; const DOMElements = { loginForm: document.getElementById('login-form'), adminOptions: document.getElementById('admin-options'), createEventBtn: document.getElementById('create-event-btn'), logoutBtn: document.getElementById('logout-btn'), eventList: document.getElementById('event-list'), upcomingList: document.getElementById('upcoming-events-list'), searchInput: document.getElementById('search-query'), categoryFilter: document.getElementById('filter-category'), publicFilter: document.getElementById('filter-public'), detailModal: document.getElementById('detail-modal'), detailTitle: document.getElementById('detail-title'), detailBody: document.getElementById('detail-body'), eventFormModal: document.getElementById('event-form-modal'), eventForm: document.getElementById('event-form'), formModalTitle: document.getElementById('form-modal-title'), monthYearDisplay: document.getElementById('month-year-display'), calendarGrid: document.getElementById('calendar-grid'), prevMonthBtn: document.getElementById('prev-month-btn'), nextMonthBtn: document.getElementById('next-month-btn'), eventListTitle: document.getElementById('event-list-title'), toastContainer: document.getElementById('toast-container') }; const saveEvents = () => localStorage.setItem('events', JSON.stringify(events)); const renderEvents = () => { const query = DOMElements.searchInput.value.toLowerCase(); const cat = DOMElements.categoryFilter.value; const pub = DOMElements.publicFilter.value; const calendarYear = currentDate.getFullYear(); const calendarMonth = currentDate.getMonth(); DOMElements.eventListTitle.textContent = selectedDate ? `Eventos para el ${formatDate(selectedDate, { day: 'numeric', month: 'long' })}` : `Eventos de ${currentDate.toLocaleString('es-ES', { month: 'long' })}`; const filtered = events.filter(e => { const matchesFilter = (e.title.toLowerCase().includes(query)) && (cat === 'Todos' || e.category === cat) && (pub === 'Todos' || e.public === pub); if (!matchesFilter) return false; const eventStart = new Date(e.startDate); const eventEnd = new Date(e.endDate); const eventStartsInOrBeforeMonth = eventStart.getFullYear() < calendarYear || (eventStart.getFullYear() === calendarYear && eventStart.getMonth() <= calendarMonth); const eventEndsInOrAfterMonth = eventEnd.getFullYear() > calendarYear || (eventEnd.getFullYear() === calendarYear && eventEnd.getMonth() >= calendarMonth); const isInMonth = eventStartsInOrBeforeMonth && eventEndsInOrAfterMonth; const matchesDate = !selectedDate || (selectedDate >= e.startDate && selectedDate <= e.endDate); return isInMonth && matchesDate; }); DOMElements.eventList.innerHTML = ''; if (filtered.length === 0) { DOMElements.eventList.innerHTML = `
No hay eventos para mostrar.
`; return; } filtered.forEach(event => { const card = document.createElement('article'); card.className = 'event-card border rounded-lg p-4 shadow-sm bg-white text-gray-800 cursor-pointer hover:shadow-lg transition-shadow group relative'; card.dataset.eventId = event.id; const adminControls = loggedIn ? `` : ''; const statusColor = event.status === 'En curso' ? 'bg-green-600' : 'bg-blue-600'; card.innerHTML = `${event.description}
${formatDate(event.startDate)} · ${event.time}
${event.campus}
${adminControls}`; DOMElements.eventList.appendChild(card); }); }; const renderUpcomingEvents = () => { DOMElements.upcomingList.innerHTML = ''; const upcoming = events.slice().sort((a, b) => new Date(a.startDate) - new Date(b.startDate)).slice(0, 3); upcoming.forEach(event => { const item = document.createElement('li'); item.className = 'py-3 cursor-pointer hover:bg-gray-50'; item.dataset.eventId = event.id; item.innerHTML = `Fechas: ${dateRange}
Hora: ${event.time}
Duración: ${event.duration}
Campus: ${event.campus}
Categoría: ${event.category}
${event.description}
Organiza: ${event.organizerUnit}
`; DOMElements.detailModal.classList.remove('hidden'); }; const hideAllModals = () => { DOMElements.detailModal.classList.add('hidden'); DOMElements.eventFormModal.classList.add('hidden'); }; const fullRender = () => { renderEvents(); renderUpcomingEvents(); renderCalendar(); }; DOMElements.loginForm.addEventListener('submit', (e) => { e.preventDefault(); if (document.getElementById('user-input').value === 'admin' && document.getElementById('pass-input').value === '1234') { loggedIn = true; updateLoginUI(); showToast('Inicio de sesión exitoso'); } else { showToast('Credenciales incorrectas', 'error'); } }); DOMElements.logoutBtn.addEventListener('click', () => { loggedIn = false; updateLoginUI(); showToast('Sesión cerrada correctamente', 'info'); }); DOMElements.createEventBtn.addEventListener('click', () => openEventFormModal('create')); DOMElements.eventForm.addEventListener('submit', (e) => { e.preventDefault(); if (!e.target.checkValidity()) { e.target.reportValidity(); return; } const formData = new FormData(DOMElements.eventForm); const eventData = Object.fromEntries(formData.entries()); eventData.time = `${eventData.startHour}:${eventData.startMinute}`; delete eventData.startHour; delete eventData.startMinute; if (modalMode === 'create') { const newEvent = { ...eventData, id: String(Date.now()), status: "Programado" }; events.unshift(newEvent); showToast('Evento creado con éxito'); } else { const eventIndex = events.findIndex(ev => ev.id === editingEventId); if (eventIndex > -1) events[eventIndex] = { ...events[eventIndex], ...eventData }; showToast('Evento actualizado con éxito'); } saveEvents(); hideAllModals(); DOMElements.eventForm.reset(); fullRender(); }); DOMElements.eventList.addEventListener('click', (e) => { const editBtn = e.target.closest('.edit-btn'); const deleteBtn = e.target.closest('.delete-btn'); const card = e.target.closest('.event-card'); if (editBtn) { openEventFormModal('edit', editBtn.dataset.eventId); } else if (deleteBtn) { if (confirm('¿Estás seguro?')) { events = events.filter(ev => ev.id !== deleteBtn.dataset.eventId); saveEvents(); fullRender(); showToast('Evento eliminado', 'info'); } } else if (card) { openDetailModal(card.dataset.eventId); } }); DOMElements.upcomingList.addEventListener('click', (e) => { const item = e.target.closest('li[data-event-id]'); if (item) openDetailModal(item.dataset.eventId); }); DOMElements.calendarGrid.addEventListener('click', (e) => { const eventEl = e.target.closest('div[data-event-id]'); const dayCell = e.target.closest('.calendar-day'); if (eventEl) { openDetailModal(eventEl.dataset.eventId); } else if (dayCell) { const date = dayCell.dataset.date; selectedDate = selectedDate === date ? null : date; fullRender(); } }); DOMElements.prevMonthBtn.addEventListener('click', () => { currentDate.setMonth(currentDate.getMonth() - 1); selectedDate = null; fullRender(); }); DOMElements.nextMonthBtn.addEventListener('click', () => { currentDate.setMonth(currentDate.getMonth() + 1); selectedDate = null; fullRender(); }); document.querySelectorAll('.close-modal-btn, .cancel-modal-btn').forEach(btn => btn.addEventListener('click', hideAllModals)); [DOMElements.searchInput, DOMElements.categoryFilter, DOMElements.publicFilter].forEach(el => el.addEventListener('input', ()=>{ selectedDate = null; fullRender(); })); function formatDate(d, options = { day: 'numeric', month: 'short', year: 'numeric' }) { const dd = new Date(d); dd.setMinutes(dd.getMinutes() + dd.getTimezoneOffset()); return dd.toLocaleDateString('es-ES', options); } const init = () => { populateFilters(); fullRender(); updateLoginUI(); }; init(); });