Strength Training Progress Tracker

Log a New Workout

Sets

Not enough data to analyze. Keep logging your workouts!

'; elements.aiAnalysisLoading.classList.add('hidden'); elements.aiAnalysisContainer.classList.remove('hidden'); return; } const prompt = `You are an expert strength training coach. A user is tracking their progress for the exercise: "${exerciseName}". Here is their workout history for this exercise, sorted by date: ${exerciseData} Please analyze this progress. Identify any positive trends, such as consistent increases in weight or volume. Point out any potential plateaus where progress has stalled. Based on the data, provide 2-3 specific, actionable tips to help the user continue making progress. For example, suggest changing rep ranges, increasing frequency, improving form (general tips), or adding accessory exercises. Keep the tone encouraging and motivational. Format your response using simple HTML like

for titles,

for paragraphs, and

    and
  • for lists.`; const apiKey = ""; // API key is handled by the environment const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`; const payload = { contents: [{ parts: [{ text: prompt }] }] }; try { const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`API request failed with status ${response.status}`); } const result = await response.json(); const analysisText = result.candidates?.[0]?.content?.parts?.[0]?.text; if (analysisText) { elements.aiAnalysisContainer.innerHTML = analysisText; } else { throw new Error("No content received from API."); } } catch (error) { console.error("Gemini API Error:", error); elements.aiAnalysisContainer.innerHTML = '

    Sorry, the AI coach is unavailable right now. Please try again later.

    '; } finally { elements.aiAnalysisLoading.classList.add('hidden'); elements.aiAnalysisContainer.classList.remove('hidden'); } } elements.analyzeProgressBtn.addEventListener('click', analyzeProgressWithGemini); // --- PDF DOWNLOAD FUNCTIONALITY --- async function downloadPDF() { const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const contentArea = elements.pdfContentArea; if (!contentArea) { console.error("PDF content area not found!"); return; } document.body.classList.add('pdf-export-mode'); try { const canvas = await html2canvas(contentArea, { scale: 2, useCORS: true, logging: false }); document.body.classList.remove('pdf-export-mode'); const imgData = canvas.toDataURL('image/png'); const imgProps = pdf.getImageProperties(imgData); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; let heightLeft = pdfHeight; let position = 0; const pageHeight = pdf.internal.pageSize.getHeight(); pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, pdfHeight); heightLeft -= pageHeight; while (heightLeft > 0) { position = heightLeft - pdfHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, pdfHeight); heightLeft -= pageHeight; } const selectedExercise = exercises.find(ex => ex.id === parseInt(elements.progressExerciseSelect.value)); const fileName = `Strength_Progress_${selectedExercise.name.replace(/\s+/g, '_')}.pdf`; pdf.save(fileName); } catch (error) { console.error("Error generating PDF:", error); document.body.classList.remove('pdf-export-mode'); alert("An error occurred while generating the PDF. Please try again."); } } elements.downloadPdfBtn.addEventListener('click', downloadPDF); // --- INITIALIZATION --- function initializeTool() { populateExerciseDropdowns(); renderExerciseList(); elements.workoutDate.valueAsDate = new Date(); addSet(); updateNavButtons(); updateProgressView(); } initializeTool(); });

Scroll to Top