Fashion Lookbook Generator

Fashion Lookbook Generator

1. Collection Metadata
2. Look Breakdown Summary
Look # Title Garments Color Palette

Define Individual Looks and Items

Add New Look

Defined Looks

Look # Title Garments (Summary) Actions

Fill out the Builder and Manager tabs and click "Generate Lookbook Draft" to preview.

${look.garments.replace(/\n/g, '
') || '(Items not listed)'}

Styling Notes:

${look.accessories.replace(/\n/g, '
') || '(No styling notes)'}

`; }); reviewContent.innerHTML = html; pdfDownloadBtn.disabled = false; switchTab(2); // Switch to review tab }; /** * PDF Generation Function (Fully Functional) */ const downloadPDF = () => { const metaData = getMetadata(); const jsPDF = window.jspdf.jsPDF; const doc = new jsPDF('p', 'pt', 'a4'); let currentY = 40; const margin = 40; const pageWidth = doc.internal.pageSize.width; const maxWidth = pageWidth - (margin * 2); const checkPageBreak = (spaceNeeded) => { if (currentY + spaceNeeded > doc.internal.pageSize.height - margin) { doc.addPage(); currentY = margin; } }; const addText = (text, size = 10, style = 'normal', indent = 0) => { doc.setFontSize(size); doc.setFont('Helvetica', style); const lines = doc.splitTextToSize(text, maxWidth - indent); checkPageBreak(lines.length * (size * 1.2)); doc.text(lines, margin + indent, currentY); currentY += (lines.length * (size * 1.2)); }; // --- PDF Content --- // Title Block doc.setFontSize(24); doc.setFont('Helvetica', 'bold'); doc.setTextColor(62, 47, 91); doc.text(metaData.collection_title.toUpperCase() || 'COLLECTION LOOKBOOK', pageWidth / 2, currentY, { align: 'center' }); currentY += 15; doc.setFontSize(14); doc.setTextColor(108, 117, 125); doc.text(`Designer: ${metaData.designer_name || 'N/A'} | ${metaData.collection_season || 'N/A'}`, pageWidth / 2, currentY, { align: 'center' }); currentY += 10; doc.setFontSize(10); addText(`Concept: ${metaData.collection_theme || 'No theme provided.'}`, 10, 'italic', 0); currentY += 15; doc.setLineWidth(1); doc.setDrawColor(62, 47, 91); doc.line(margin, currentY, pageWidth - margin, currentY); currentY += 20; // Detailed Looks looks.forEach(look => { checkPageBreak(120); // Look Header doc.setFontSize(16); doc.setFont('Helvetica', 'bold'); doc.setTextColor(62, 47, 91); addText(`LOOK ${look.number}: ${look.title}`, 16, 'bold', 0); currentY += 5; // Metadata Table const metaTable = [ ['Model:', look.model || 'N/A'], ['Palette:', look.palette || 'N/A'], ]; doc.autoTable({ startY: currentY, head: [], body: metaTable, theme: 'plain', styles: { fontSize: 10, cellPadding: 2, font: 'Helvetica' }, columnStyles: { 0: { fontStyle: 'bold', cellWidth: 50 }, 1: { cellWidth: maxWidth - 50 } } }); currentY = doc.autoTable.previous.finalY + 5; // Garments doc.setFontSize(12); doc.setFont('Helvetica', 'bold'); doc.setTextColor(108, 117, 125); addText('Garments:', 12, 'bold', 0); doc.setFontSize(10); doc.setFont('Helvetica', 'normal'); const garmentLines = look.garments.split('\n').map(g => `• ${g.trim()}`).join('\n'); addText(garmentLines || 'N/A', 10, 'normal', 10); currentY += 5; // Styling Notes doc.setFontSize(12); doc.setFont('Helvetica', 'bold'); doc.setTextColor(108, 117, 125); addText('Styling Notes:', 12, 'bold', 0); doc.setFontSize(10); doc.setFont('Helvetica', 'normal'); addText(look.accessories || 'N/A', 10, 'normal', 10); currentY += 15; // Space before next look }); doc.save(`${metaData.collection_title.replace(/\s/g, '_') || 'Lookbook'}_Draft.pdf`); }; // --- Event Listeners and Initial Load --- generateReviewBtn.addEventListener('click', generateLookbook); pdfDownloadBtn.addEventListener('click', downloadPDF); // Tab Navigation const switchTab = (tabIndex) => { tabs.forEach((tab, index) => { tab.classList.toggle('active', index === tabIndex); contents[index].classList.toggle('active', index === tabIndex); }); currentTab = tabIndex; updateNavButtons(); if (tabIndex === 2) { generateLookbook(); } else if (tabIndex === 1) { // Rerender config to ensure correct state after switching renderLookLists(); } }; const updateNavButtons = () => { prevBtn.disabled = currentTab === 0; nextBtn.disabled = currentTab === tabs.length - 1; }; tabs.forEach((tab, index) => { tab.addEventListener('click', () => { const tabNode = tab.closest('.lookbook-tab-button'); const newIndex = Array.from(tabNode.parentNode.children).indexOf(tabNode); switchTab(newIndex); }); }); nextBtn.addEventListener('click', () => { if (currentTab < tabs.length - 1) switchTab(currentTab + 1); }); prevBtn.addEventListener('click', () => { if (currentTab > 0) switchTab(currentTab - 1); }); // Initial Setup setInitialDate(); renderLookLists(); updateNavButtons(); });
Scroll to Top