Strength Training Progress Tracker
Log a New Workout
View Progress
Workout History
| Date | Sets | Total Volume (lbs) | Max Weight (lbs) |
|---|
AI Coach Analysis
Your AI coach is analyzing your progress...
No data available for this exercise yet. Log a workout to get started!
Manage Exercise List
Add New Exercise
Current Exercises
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 likefor 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(); });
