Personalized Space Travel Itinerary Creator

Planned Activities:

${activitiesHTML}

Log Entry: ${leg.highlight}

`; detailsDiv.appendChild(legDiv); }); outputDiv.style.display = 'block'; outputDiv.scrollIntoView({ behavior: 'smooth', block: 'start' }); }; // --- Event Listeners --- generateBtn.addEventListener('click', () => { const name = nameInput.value.trim(); const duration = durationSelect.value; const interest = interestSelect.value; const shipClass = shipSelect.value; const selectedEnvironments = Array.from(environmentCheckboxes) .filter(cb => cb.checked) .map(cb => cb.value); if (!name) { alert("Please enter the Traveler's Name."); nameInput.focus(); return; } currentItinerary = generateItinerary(name, duration, interest, selectedEnvironments, shipClass); displayItinerary(currentItinerary); }); downloadBtn.addEventListener('click', () => { if (!currentItinerary.legs || currentItinerary.legs.length === 0) { alert("Please generate an itinerary first!"); return; } const { jsPDF } = window.jspdf; const { autoTable } = window.jspdfAutotable; const doc = new jsPDF(); // --- PDF Styling --- const primaryColor = '#0abde3'; const secondaryColor = '#f368e0'; const accentColor = '#1f2d40'; // Dark blue for headers on white PDF const textColor = '#333333'; const headingFontSize = 18; const subHeadingFontSize = 12; const normalFontSize = 9; // Smaller for fitting table data const tableHeaderColor = accentColor; // Dark blue header let yPos = 15; // --- PDF Content --- doc.setFontSize(headingFontSize); doc.setFont('helvetica', 'bold'); doc.setTextColor(primaryColor); // Use primary color for main title doc.text("Personalized Space Travel Itinerary", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 12; // Trip Summary Table doc.setFontSize(subHeadingFontSize); doc.setTextColor(textColor); doc.setFont('helvetica', 'bold'); doc.text("Trip Summary:", 14, yPos); yPos += 6; autoTable(doc, { startY: yPos, theme: 'grid', headStyles: { fillColor: tableHeaderColor, textColor: '#ffffff', fontStyle: 'bold' }, styles: { fontSize: normalFontSize, cellPadding: 2 }, body: [ ['Traveler Name', currentItinerary.travelerName], ['Trip Duration', currentItinerary.tripDuration], ['Primary Interest', currentItinerary.primaryInterest], ['Ship', currentItinerary.shipInfo], ['Preferred Environments', currentItinerary.preferredEnvironments.join(', ') || 'Any'], ], didDrawPage: (data) => { yPos = data.cursor.y; } }); yPos += 10; // Itinerary Details Table doc.setFontSize(subHeadingFontSize); doc.setFont('helvetica', 'bold'); doc.text("Itinerary Details:", 14, yPos); yPos += 8; const tableBody = currentItinerary.legs.map(leg => [ leg.leg, leg.destination, leg.travel, leg.activities ? leg.activities.join('\n') : '-', // Join activities with newline for multi-line cells leg.highlight ]); autoTable(doc, { startY: yPos, head: [['Leg', 'Destination', 'Travel Method', 'Activities', 'Log Entry/Highlight']], body: tableBody, theme: 'striped', // Use striped for better readability headStyles: { fillColor: tableHeaderColor, textColor: '#ffffff', fontStyle: 'bold' }, styles: { fontSize: normalFontSize - 1, cellPadding: 2, overflow: 'linebreak' }, // Smaller font, allow line breaks columnStyles: { // Adjust column widths if needed, e.g.: //0: { cellWidth: 15 }, // Leg //1: { cellWidth: 40 }, // Destination //2: { cellWidth: 30 }, // Travel //3: { cellWidth: 'auto' }, // Activities (let it take space) //4: { cellWidth: 40 } // Highlight }, didDrawPage: (data) => { yPos = data.cursor.y; } }); // Save PDF const safeName = currentItinerary.travelerName.replace(/[^a-z0-9]/gi, '_').toLowerCase(); doc.save(`space_itinerary_${safeName}.pdf`); }); }); // End DOMContentLoaded
Scroll to Top