`;
// This is the full view with buttons
itineraryDetailView.innerHTML = `
${printableContent}
`;
itineraryListView.classList.add('hidden');
itineraryDetailView.classList.remove('hidden');
// Add event listeners to newly created buttons
document.getElementById('back-to-list-btn').addEventListener('click', () => {
itineraryDetailView.classList.add('hidden');
itineraryListView.classList.remove('hidden');
});
document.querySelector('.edit-itinerary-btn').addEventListener('click', (e) => populateFormForEdit(e.target.dataset.id));
document.querySelector('.delete-itinerary-btn').addEventListener('click', (e) => deleteItinerary(e.target.dataset.id));
document.getElementById('download-pdf-btn').addEventListener('click', () => downloadPDF(itinerary));
}
function deleteItinerary(itineraryId) {
// Using a simple confirmation as a placeholder for a custom modal
if (confirm('Are you sure you want to delete this itinerary? This action cannot be undone.')) {
state.itineraries = state.itineraries.filter(i => i.id !== itineraryId);
renderDashboard();
itineraryDetailView.classList.add('hidden');
itineraryListView.classList.remove('hidden');
}
}
// --- PDF DOWNLOAD LOGIC --- //
function downloadPDF(itinerary) {
const { jsPDF } = window.jspdf;
const pdfContent = document.getElementById('pdf-content');
if (!pdfContent) return;
// Use html2canvas to render the div to a canvas
html2canvas(pdfContent, { scale: 2 }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
// Calculate dimensions for the PDF
const pdf = new jsPDF({
orientation: 'portrait',
unit: 'px',
format: 'a4'
});
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
const ratio = canvasWidth / canvasHeight;
let imgWidth = pdfWidth - 20; // with margin
let imgHeight = imgWidth / ratio;
let heightLeft = imgHeight;
let position = 10; // top margin
pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
heightLeft -= pdfHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight + 10; // top margin for new page
pdf.addPage();
pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
heightLeft -= pdfHeight;
}
// Generate a filename
const fileName = `Itinerary-${itinerary.employeeName.replace(' ', '_')}-${itinerary.tripName.replace(' ', '_')}.pdf`;
pdf.save(fileName);
});
}
// --- CONFIGURATION LOGIC --- //
function renderConfigLists() {
// Render Employees
employeeList.innerHTML = state.config.employees.map(emp => `
${emp.name} - ${emp.title}
`).join('');
// Render Airlines
airlineList.innerHTML = state.config.airlines.map(airline => `
${airline}
`).join('');
// Render Hotels
hotelList.innerHTML = state.config.hotels.map(hotel => `
${hotel}
`).join('');
// Render Car Rentals
carRentalList.innerHTML = state.config.carRentals.map(car => `
${car}
`).join('');
// Update dropdowns
employeeNameSelect.innerHTML = state.config.employees.map(emp => `
`).join('');
}
function updateConfigFromDOM() {
state.config.employees = Array.from(employeeList.children).map(li => ({
id: li.dataset.id,
name: li.querySelector('span').childNodes[0].textContent.trim(),
title: li.querySelector('em').textContent.substring(2)
}));
state.config.airlines = Array.from(airlineList.children).map(li => li.querySelector('span').textContent);
state.config.hotels = Array.from(hotelList.children).map(li => li.querySelector('span').textContent);
state.config.carRentals = Array.from(carRentalList.children).map(li => li.querySelector('span').textContent);
renderConfigLists(); // Re-render to update dropdowns
}
// Event listeners for config buttons
addEmployeeBtn.addEventListener('click', () => {
const name = newEmployeeNameInput.value.trim();
const title = newEmployeeTitleInput.value.trim();
if (name && title) {
state.config.employees.push({ id: generateId(), name, title });
newEmployeeNameInput.value = '';
newEmployeeTitleInput.value = '';
renderConfigLists();
}
});
addAirlineBtn.addEventListener('click', () => {
const name = newAirlineNameInput.value.trim();
if (name && !state.config.airlines.includes(name)) {
state.config.airlines.push(name);
newAirlineNameInput.value = '';
renderConfigLists();
}
});
addHotelBtn.addEventListener('click', () => {
const name = newHotelNameInput.value.trim();
if (name && !state.config.hotels.includes(name)) {
state.config.hotels.push(name);
newHotelNameInput.value = '';
renderConfigLists();
}
});
addCarRentalBtn.addEventListener('click', () => {
const name = newCarRentalNameInput.value.trim();
if (name && !state.config.carRentals.includes(name)) {
state.config.carRentals.push(name);
newCarRentalNameInput.value = '';
renderConfigLists();
}
});
// Use MutationObserver to automatically update state when items are removed via inline onclick
const observer = new MutationObserver(updateConfigFromDOM);
observer.observe(employeeList, { childList: true });
observer.observe(airlineList, { childList: true });
observer.observe(hotelList, { childList: true });
observer.observe(carRentalList, { childList: true });
// --- INITIALIZATION --- //
function initializeApp() {
// Null checks for critical elements
if (!tabButtons.dashboard || !tabPanels.dashboard || !itineraryForm) {
console.error("Critical UI elements are missing. Tool cannot initialize.");
return;
}
addFlightBtn.addEventListener('click', () => addFlightSegment());
addAccommodationBtn.addEventListener('click', () => addAccommodationSegment());
addTransportBtn.addEventListener('click', () => addTransportSegment());
addMeetingBtn.addEventListener('click', () => addMeetingSegment());
clearFormBtn.addEventListener('click', clearForm);
renderConfigLists();
renderDashboard();
showTab('dashboard'); // Start on the dashboard
clearForm(); // Set up the form with one empty flight segment
}
initializeApp();
});