Date: ${date}
Attendees: ${attendees}
Agenda (Total Time: ${totalTime} mins)
${itemsHtml}
`;
},
renderTemplateSelect() {
const select = this.elements.templateSelect;
if (!select) return;
select.innerHTML = '
';
this.state.templates.forEach(t => {
select.innerHTML += `
`;
});
},
renderTemplatesTable() {
const tableBody = this.elements.templatesTableBody;
if (!tableBody) return;
tableBody.innerHTML = '';
this.state.templates.forEach(t => {
tableBody.innerHTML += `
| ${t.name} |
|
`;
});
},
// --- EVENT HANDLERS & ACTIONS ---
changeTab(tabIndex) {
if (tabIndex < 0 || tabIndex >= this.elements.tabButtons.length) return;
this.state.currentTab = tabIndex;
this.elements.tabButtons.forEach((btn, i) => btn.classList.toggle('active', i === tabIndex));
this.elements.tabContents.forEach((content, i) => content.classList.toggle('active', i === tabIndex));
this.updateNavButtons();
},
updateNavButtons() {
if (!this.elements.prevTabBtn || !this.elements.nextTabBtn) return;
this.elements.prevTabBtn.style.visibility = this.state.currentTab === 0 ? 'hidden' : 'visible';
this.elements.nextTabBtn.style.visibility = this.state.currentTab === this.elements.tabButtons.length - 1 ? 'hidden' : 'visible';
},
addAgendaItem(item = { title: '', presenter: '', time: '' }) {
this.state.agendaItems.push(item);
this.renderAll();
},
handleItemChange(e) {
const target = e.target;
const itemEl = target.closest('.agenda-item');
if (!itemEl) return;
const index = parseInt(itemEl.dataset.index);
const prop = target.dataset.prop;
this.state.agendaItems[index][prop] = target.value;
this.renderPreview();
},
handleItemActions(e) {
const target = e.target.closest('button');
if (!target) return;
const itemEl = target.closest('.agenda-item');
if (!itemEl) return;
const index = parseInt(itemEl.dataset.index);
if (target.dataset.action === 'delete') {
this.state.agendaItems.splice(index, 1);
this.renderAll();
}
},
handleTemplateLoad(e) {
const templateId = parseInt(e.target.value);
if (!templateId) {
this.state.agendaItems = [];
} else {
const template = this.state.templates.find(t => t.id === templateId);
if (template) {
this.state.agendaItems = JSON.parse(JSON.stringify(template.items)); // Deep copy
}
}
this.renderAll();
},
handleTemplateSubmit(e) {
e.preventDefault();
const form = this.elements.templateForm;
const id = parseInt(form.querySelector('#template-edit-id').value);
const name = form.querySelector('#template-name').value;
const itemsText = form.querySelector('#template-items').value;
const items = itemsText.split('\n').map(line => {
const [title, presenter, time] = line.split(',');
return { title: title || '', presenter: presenter || '', time: parseInt(time) || 0 };
}).filter(item => item.title);
if (items.length === 0) {
this.showNotification('Template must have at least one valid item line.', 'error');
return;
}
if (id) {
const template = this.state.templates.find(t => t.id === id);
if (template) { template.name = name; template.items = items; }
} else {
this.state.templates.push({ id: this.getNextId(this.state.templates), name, items });
}
form.reset();
form.querySelector('#template-edit-id').value = '';
this.renderAll();
this.showNotification('Template saved!', 'success');
},
handleTemplateTableActions(e) {
const target = e.target.closest('button');
if (!target) return;
const id = parseInt(target.dataset.id);
if (target.dataset.action === 'edit') {
const template = this.state.templates.find(t => t.id === id);
if (template) {
const form = this.elements.templateForm;
form.querySelector('#template-edit-id').value = template.id;
form.querySelector('#template-name').value = template.name;
form.querySelector('#template-items').value = template.items.map(i => `${i.title},${i.presenter},${i.time}`).join('\n');
}
} else if (target.dataset.action === 'delete') {
if (confirm('Are you sure?')) {
this.state.templates = this.state.templates.filter(t => t.id !== id);
this.renderAll();
}
}
},
// --- Drag and Drop Handlers ---
handleDragStart(e) {
this.state.draggedItem = e.target;
setTimeout(() => e.target.classList.add('dragging'), 0);
},
handleDragOver(e) {
e.preventDefault();
const container = this.elements.agendaItemsContainer;
const afterElement = this.getDragAfterElement(container, e.clientY);
const dragging = container.querySelector('.dragging');
if (afterElement == null) {
container.appendChild(dragging);
} else {
container.insertBefore(dragging, afterElement);
}
},
handleDrop(e) {
e.preventDefault();
const newOrder = Array.from(this.elements.agendaItemsContainer.children).map(el => {
return this.state.agendaItems[parseInt(el.dataset.index)];
});
this.state.agendaItems = newOrder;
this.renderAll();
},
handleDragEnd(e) {
e.target.classList.remove('dragging');
},
getDragAfterElement(container, y) {
const draggableElements = [...container.querySelectorAll('.agenda-item:not(.dragging)')];
return draggableElements.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) {
return { offset: offset, element: child };
} else {
return closest;
}
}, { offset: Number.NEGATIVE_INFINITY }).element;
},
// --- PDF Generation ---
downloadAgendaPDF() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const title = document.getElementById('meeting-title').value;
const date = new Date(document.getElementById('meeting-date').value).toLocaleString();
const attendees = document.getElementById('meeting-attendees').value;
doc.setFontSize(18);
doc.text(title, 105, 22, { align: 'center' });
doc.setFontSize(11);
doc.text(`Date: ${date}`, 14, 35);
doc.text(`Attendees: ${attendees}`, 14, 42);
const tableData = this.state.agendaItems.map(item => [item.title, item.presenter, `${item.time} mins`]);
const totalTime = this.state.agendaItems.reduce((sum, i) => sum + (parseInt(i.time) || 0), 0);
tableData.push(['Total', '', `${totalTime} mins`]);
doc.autoTable({
startY: 55,
head: [['Topic', 'Presenter', 'Duration']],
body: tableData,
theme: 'striped',
headStyles: { fillColor: [5, 150, 105] },
didDrawCell: (data) => {
if (data.row.index === tableData.length - 1) {
doc.setFont(undefined, 'bold');
}
}
});
doc.save(`Agenda_${title.replace(/\s/g, '_')}.pdf`);
},
// --- UTILITY FUNCTIONS ---
loadDefaultTemplate() {
const now = new Date();
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
now.setSeconds(0);
now.setMilliseconds(0);
document.getElementById('meeting-date').value = now.toISOString().slice(0,16);
this.state.agendaItems = JSON.parse(JSON.stringify(this.state.templates[0].items));
},
getNextId(array) {
return array.length > 0 ? Math.max(...array.map(item => item.id)) + 1 : 1;
},
showNotification(message, type = 'success') {
const box = this.elements.notificationBox;
if (!box) return;
box.textContent = message;
box.className = `mag-notification ${type}`;
box.classList.add('show');
setTimeout(() => { box.classList.remove('show'); }, 3000);
}
};
// Make MAG object globally accessible
window.MAG = MAG;
// Start the application
MAG.init();
});