Recipe Generator

Recipe Generator

1. Recipe Parameters
2. Ingredients & Restrictions

Hold Ctrl/Cmd to select multiple.

Your Generated Recipe

Click "Generate Recipe" in the previous tab to create your draft.

Manage Recipe Lists

Cuisines

Meal Types

Dietary Restrictions

Customized Parameters: ${recipe.parameters.Cuisine} / ${recipe.parameters.Complexity}

${recipe.info}

Ingredients

    ${recipe.ingredients.map(i => `
  • ${i}
  • `).join('')}

Instructions

    ${recipe.instructions.map(i => `
  1. ${i}
  2. `).join('')}

Quick Reference

Servings: ${recipe.parameters.Servings} | Meal Type: ${recipe.parameters.Meal} | Restrictions: ${recipe.parameters.Restrictions}

`; reviewCard.innerHTML = html; } // --- PDF Generation --- function downloadPDF() { if (!lastGeneratedRecipe) { alert("Please generate a recipe first."); return; } const recipe = lastGeneratedRecipe; const { jsPDF } = window.jspdf; const doc = new jsPDF(); let currentY = 30; const margin = 20; // Title doc.setFontSize(22); doc.setFont(undefined, 'bold'); doc.text(recipe.title, doc.internal.pageSize.width / 2, currentY, { align: 'center' }); currentY += 15; // Info doc.setFontSize(10); doc.setFont(undefined, 'italic'); const infoLines = doc.splitTextToSize(recipe.info, doc.internal.pageSize.width - margin * 2); doc.text(infoLines, margin, currentY); currentY += (infoLines.length * 6) + 15; // Table (Parameters) const paramHead = [['Cuisine', 'Meal Type', 'Servings', 'Complexity', 'Restrictions']]; const paramBody = [[ recipe.parameters.Cuisine, recipe.parameters.Meal, recipe.parameters.Servings, recipe.parameters.Complexity, recipe.parameters.Restrictions ]]; doc.autoTable({ startY: currentY, head: paramHead, body: paramBody, theme: 'grid', headStyles: { fillColor: [59, 130, 246] }, // --primary-color styles: { fontSize: 8, cellPadding: 3 } }); currentY = doc.autoTable.previous.finalY + 15; // Ingredients doc.setFontSize(14); doc.setFont(undefined, 'bold'); doc.text('Ingredients', margin, currentY); currentY += 5; doc.line(margin, currentY, doc.internal.pageSize.width - margin, currentY); currentY += 10; doc.setFontSize(10); doc.setFont(undefined, 'normal'); recipe.ingredients.forEach(item => { doc.text(`• ${item}`, margin, currentY); currentY += 8; }); currentY += 10; // Instructions doc.setFontSize(14); doc.setFont(undefined, 'bold'); doc.text('Instructions', margin, currentY); currentY += 5; doc.line(margin, currentY, doc.internal.pageSize.width - margin, currentY); currentY += 10; doc.setFontSize(10); doc.setFont(undefined, 'normal'); recipe.instructions.forEach((step, index) => { const stepText = `${index + 1}. ${step}`; const lines = doc.splitTextToSize(stepText, doc.internal.pageSize.width - margin * 2); doc.text(lines, margin, currentY); currentY += (lines.length * 7) + 3; }); doc.save('Generated_Recipe.pdf'); } pdfDownloadBtn.addEventListener('click', downloadPDF); // --- Tab Navigation --- function switchTab(tabIndex) { tabs.forEach((tab, index) => { tab.classList.toggle('active', index === tabIndex); contents[index].classList.toggle('active', index === tabIndex); }); currentTab = tabIndex; updateNavButtons(); } function updateNavButtons() { prevBtn.disabled = currentTab === 0; nextBtn.disabled = currentTab === tabs.length - 1; } tabs.forEach((tab, index) => { tab.addEventListener('click', () => switchTab(index)); }); nextBtn.addEventListener('click', () => { if (currentTab < tabs.length - 1) switchTab(currentTab + 1); }); prevBtn.addEventListener('click', () => { if (currentTab > 0) switchTab(currentTab - 1); }); // --- Initial Setup --- generateBtn.addEventListener('click', generateRecipe); populateDropdowns(); renderConfigLists(); updateNavButtons(); });
Scroll to Top