Fitness Workout Plan Generator

Fitness Workout Plan Generator

Plan Fundamentals

Define Exercises and Default Sets/Reps

Current Exercise Library (Editable)

Exercise Name Sets Reps Default Weight (lb) Actions

Assign Exercises to Days

Select an exercise and a day to build your workout split.

Weekly Split Preview

Review the final structured workout plan.

Generate the plan to see the export preview.

Primary Goal: ${escapeHTML(data.setup.goal)} | Duration: ${escapeHTML(data.setup.duration)}

Plan Notes / Philosophy

${escapeHTML(data.setup.notes)}

Weekly Workout Split

${scheduleHTML}
`; }; const downloadTxt = () => { const data = getPlanData(); let content = `WORKOUT PLAN: ${data.setup.name.toUpperCase()}\n`; content += "========================================\n"; content += `Goal: ${data.setup.goal}\nDuration: ${data.setup.duration}\n\n`; content += `NOTES: ${data.setup.notes}\n`; content += "========================================\n\n"; dayNames.forEach(day => { content += `--- ${day.toUpperCase()} ---\n`; const dayContent = data.schedule[day]; if (dayContent && dayContent.length > 0) { dayContent.forEach(exId => { const ex = getExerciseById(exId); if (ex) { content += `${ex.name} - ${ex.sets} sets x ${ex.reps} reps @ ${ex.weight} lb\n`; } }); } else { content += `[Rest Day or Empty]\n`; } content += "\n"; }); const blob = new Blob([content], { type: 'text/plain;charset=utf-8' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = `${data.setup.name.replace(/ /g, '_')}_plan.txt`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(a.href); }; const downloadPDF = () => { if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined' || typeof window.jspdf.autoTable === 'undefined') { alert('Error: jsPDF libraries not loaded.'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF('p', 'mm', 'a4'); const data = getPlanData(); const margin = 15; const pageWidth = doc.internal.pageSize.getWidth(); const usableWidth = pageWidth - margin * 2; let yPos = 15; // --- PDF Helper --- const addText = (text, size, style, color = [52, 73, 94], align = 'left', indent = 0) => { doc.setFontSize(size); doc.setFont(undefined, style); doc.setTextColor(color[0], color[1], color[2]); const splitText = doc.splitTextToSize(text, usableWidth - indent); if (yPos + (splitText.length * 5) > 280) { doc.addPage(); yPos = 20; } doc.text(splitText, margin + indent, yPos); yPos += (splitText.length * 5) + (size > 12 ? 3 : 1); }; const addSectionHeader = (title) => { yPos += 5; doc.setFontSize(14); doc.setFont(undefined, 'bold'); doc.setTextColor(231, 76, 60); // Red doc.text(title, margin, yPos); doc.setDrawColor(224, 224, 224); doc.line(margin, yPos + 1, pageWidth - margin, yPos + 1); yPos += 8; }; // 1. Title Block addText(data.setup.name.toUpperCase(), 18, 'bold', [44, 62, 80], 'center'); addText(`Goal: ${data.setup.goal} | Duration: ${data.setup.duration}`, 10, 'normal', [108, 117, 125], 'center'); yPos += 5; // 2. Notes addSectionHeader("Plan Notes / Philosophy"); addText(data.setup.notes, 10, 'normal', [52, 73, 94], 'left', 5); yPos += 5; // 3. Weekly Schedule addSectionHeader("Weekly Workout Split"); dayNames.forEach(day => { const dayContent = data.schedule[day]; doc.setFontSize(12); doc.setFont(undefined, 'bold'); doc.setTextColor(44, 62, 80); doc.text(day, margin, yPos); yPos += 6; if (dayContent && dayContent.length > 0) { dayContent.forEach(exId => { const ex = getExerciseById(exId); if (ex) { const line = `${ex.name}: ${ex.sets} sets x ${ex.reps} reps @ ${ex.weight} lb`; addText(line, 10, 'normal', [52, 73, 94], 'left', 10); } }); } else { addText('[REST DAY / ACTIVE RECOVERY]', 10, 'italic', [108, 117, 125], 'left', 10); } yPos += 5; }); doc.save('workout_plan.pdf'); }; // --- Event Listeners --- // Global Navigation tabButtons.forEach((btn, index) => { btn.addEventListener('click', () => showTab(index + 1)); }); nextBtn.addEventListener('click', () => showTab(currentTab + 1)); prevBtn.addEventListener('click', () => showTab(currentTab - 1)); // Tab 2 Actions (Add, Remove, Edit) exInputs.addBtn.addEventListener('click', addExercise); exInputs.tbody.addEventListener('click', (e) => { if (e.target.dataset.removeId) { removeExercise(parseInt(e.target.dataset.removeId)); } }); exInputs.tbody.addEventListener('blur', (e) => { if (e.target.tagName === 'TD' && e.target.isContentEditable) { updateExercise(parseInt(e.target.dataset.id), e.target.dataset.field, e.target.textContent); } }, true); // Tab 3 Actions scheduleInputs.assignBtn.addEventListener('click', assignExerciseToDay); // Tab 4 Actions refreshBtn.addEventListener('click', generatePreview); downloadPdfBtn.addEventListener('click', downloadPDF); downloadTxtBtn.addEventListener('click', downloadTxt); // --- Initialization --- showTab(1); // Set initial state });
Scroll to Top