Travel Blog Post Generator

Travel Blog Post Generator

Craft a beautiful story about your latest adventure.

Trip Details

Itinerary & Highlights

Your Narrative

Generated Blog Post

Copied to clipboard!

${item.description}

`; }); } preview.innerHTML = `

${data.title}

By ${data.author} | A ${data.tripType} to ${data.location}

Introduction

${data.introduction}

${highlightsHtml}

Final Thoughts

${data.conclusion}

`; } function showMessage() { messageBox.classList.remove('opacity-0', 'translate-y-10'); messageBox.classList.add('opacity-100', 'translate-y-0'); setTimeout(() => { messageBox.classList.remove('opacity-100', 'translate-y-0'); messageBox.classList.add('opacity-0', 'translate-y-10'); }, 2000); } async function generateBlogPostPdf() { const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const data = getFormData(); const pageW = pdf.internal.pageSize.getWidth(); const pageH = pdf.internal.pageSize.getHeight(); const margin = 20; const contentWidth = pageW - (margin * 2); let y = 0; const lineH = 7; const addHeaderFooter = () => { const pageCount = pdf.internal.getNumberOfPages(); for (let i = 1; i <= pageCount; i++) { pdf.setPage(i); pdf.setFontSize(9); pdf.setTextColor('#6b7280'); if (i > 1) { pdf.text(data.title, margin, 12); } pdf.text(`Page ${i}`, pageW - margin, pageH - 10, { align: 'right' }); } }; const checkBreak = (needed = 20) => { if (y + needed > pageH - margin) { pdf.addPage(); y = margin; } }; const addText = (text, options = {}) => { const { size=11, style='normal', color='#374151', indent=0, spacing=1 } = options; if (!text && text !== '') return; checkBreak(15); pdf.setFontSize(size); pdf.setFont('times', style); pdf.setTextColor(color); const splitText = pdf.splitTextToSize(text, contentWidth - indent); pdf.text(splitText, margin + indent, y); y += (splitText.length * lineH * 0.75) + (lineH * spacing); }; const addSectionHeader = (title) => { y += lineH * 1.5; checkBreak(20); pdf.setFontSize(16); pdf.setFont('helvetica', 'bold'); pdf.setTextColor('#b45309'); pdf.text(title, margin, y); y += lineH * 1.5; }; // --- Build PDF Document --- // Page 1: Title Page with image let imagePromise = null; if(data.heroImage) { imagePromise = new Promise((resolve, reject) => { const img = new Image(); img.crossOrigin = "Anonymous"; img.onload = () => { try { pdf.addImage(img, 'JPEG', 0, 0, pageW, 100); resolve(); } catch (e) { console.error("jsPDF image error:", e); resolve(); // Resolve anyway to not block PDF generation } }; img.onerror = () => { console.error("Could not load image for PDF."); resolve(); // Resolve so PDF generation can continue } img.src = data.heroImage; }); } else { imagePromise = Promise.resolve(); } await imagePromise; pdf.setFontSize(24); pdf.setFont('helvetica', 'bold'); pdf.setTextColor('#1f2937'); pdf.text(data.title, pageW / 2, 120, { align: 'center' }); pdf.setFontSize(12); pdf.setFont('helvetica', 'normal'); pdf.setTextColor('#4b5563'); pdf.text(`By ${data.author} | A ${data.tripType}`, pageW / 2, 130, { align: 'center' }); pdf.addPage(); y = margin; // Introduction addSectionHeader("Introduction"); addText(data.introduction); // Highlights if (data.highlights.length > 0) { addSectionHeader("Highlights"); data.highlights.forEach(item => { checkBreak(30); addText(item.title, { style: 'bold', size: 14, color: '#374151', spacing: 0.5 }); addText(item.day, { style: 'italic', size: 10, color: '#6b7280', spacing: 1.5}); addText(item.description, {spacing: 1.5}); }); } // Conclusion addSectionHeader("Final Thoughts"); addText(data.conclusion); addHeaderFooter(); pdf.save(`Blog_Post_${data.title.replace(/\s+/g, '_').substring(0,20)}.pdf`); } // --- Event Listeners & Init --- tabs.forEach(tab => tab.addEventListener('click', () => goToTab(parseInt(tab.dataset.tab)))); prevButton.addEventListener('click', () => goToTab(currentTab - 1)); nextButton.addEventListener('click', () => goToTab(currentTab + 1)); copyButton.addEventListener('click', () => { const preview = document.getElementById('report-preview-container'); if (preview) { navigator.clipboard.writeText(preview.innerText).then(() => { showMessage(); }).catch(err => console.error('Copy failed: ', err)); } }); pdfDownloadButton.addEventListener('click', generateBlogPostPdf); addHighlightButton.addEventListener('click', addHighlightItem); // Add one initial highlight item addHighlightItem(); updateTabUI(); });
Scroll to Top