`;
workoutLogList.appendChild(li);
});
}
window.removeWorkout = function(id) {
workoutLog = workoutLog.filter(w => w.id !== id);
renderWorkoutLog();
};
function calculateAndDisplayDashboard() {
if (workoutLog.length === 0) {
// Reset dashboard to empty state
totalWorkoutsEl.textContent = '0';
totalDurationEl.innerHTML = '0min';
totalDistanceEl.innerHTML = '0mi';
activityChart.innerHTML = 'No workouts logged. ';
return;
}
// Calculations
const totalWorkouts = workoutLog.length;
const totalDuration = workoutLog.reduce((sum, w) => sum + w.duration, 0);
// Normalize distances to miles for total calculation
const totalDistanceMiles = workoutLog.reduce((sum, w) => {
const distanceInMiles = w.unit === 'km' ? w.distance * 0.621371 : w.distance;
return sum + distanceInMiles;
}, 0);
// Update summary cards
totalWorkoutsEl.textContent = totalWorkouts;
totalDurationEl.innerHTML = `${totalDuration}min`;
totalDistanceEl.innerHTML = `${totalDistanceMiles.toFixed(1)}mi`;
// Update table
resultsTableBody.innerHTML = '';
const sortedLog = [...workoutLog].sort((a, b) => new Date(b.date) - new Date(a.date));
sortedLog.forEach(w => {
const row = resultsTableBody.insertRow();
const formattedDate = new Date(w.date).toLocaleDateString('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' });
row.innerHTML = `
${formattedDate}
${w.activity}
${w.duration} min
${w.distance.toFixed(1)} ${w.unit}
`;
});
// Update chart
const activityData = {};
workoutLog.forEach(w => {
activityData[w.activity] = (activityData[w.activity] || 0) + w.duration;
});
const maxDuration = Math.max(...Object.values(activityData), 1);
activityChart.innerHTML = '';
Object.entries(activityData).forEach(([activity, duration]) => {
const barHeight = (duration / maxDuration) * 100;
const barWrapper = document.createElement('div');
barWrapper.className = 'chart-bar-wrapper';
barWrapper.innerHTML = `
No data to display in chart.
'; resultsTableBody.innerHTML = '${duration} min
${activity}
`;
activityChart.appendChild(barWrapper);
});
}
// --- TAB NAVIGATION ---
window.changeTab = function(tabNumber) {
if (tabNumber === currentTab) return;
if (tabNumber === 2) {
calculateAndDisplayDashboard();
}
document.getElementById(`tab-panel-${currentTab}`).classList.add('hidden');
document.getElementById(`tab-btn-${currentTab}`).classList.remove('active', 'border-indigo-500');
document.getElementById(`tab-btn-${currentTab}`).classList.add('inactive');
document.getElementById(`tab-panel-${tabNumber}`).classList.remove('hidden');
document.getElementById(`tab-btn-${tabNumber}`).classList.add('active', 'border-indigo-500');
document.getElementById(`tab-btn-${tabNumber}`).classList.remove('inactive');
currentTab = tabNumber;
updateNavButtons();
};
window.navigateTabs = function(direction) {
const newTab = direction === 'next' ? currentTab + 1 : currentTab - 1;
if (newTab >= 1 && newTab <= 2) {
changeTab(newTab);
}
};
function updateNavButtons() {
prevBtn.disabled = (currentTab === 1);
nextBtn.disabled = (currentTab === 2);
}
// --- PDF GENERATION ---
function generatePdf() {
const contentToPrint = document.getElementById('pdf-content-container');
const pdfButtonWrapper = document.getElementById('pdf-button-wrapper');
if (!contentToPrint) {
console.error("PDF content container not found.");
return;
}
// Hide button wrapper before capture
if (pdfButtonWrapper) pdfButtonWrapper.style.display = 'none';
html2canvas(contentToPrint, {
scale: 2,
useCORS: true,
logging: false
}).then(canvas => {
// Restore button immediately after capture
if (pdfButtonWrapper) pdfButtonWrapper.style.display = 'block';
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const canvasAspectRatio = canvas.width / canvas.height;
let imgWidth = pdfWidth - 80; // 40pt margins
let imgHeight = imgWidth / canvasAspectRatio;
// If content is too tall, scale it down to fit one page
if (imgHeight > pdfHeight - 80) {
imgHeight = pdfHeight - 80;
imgWidth = imgHeight * canvasAspectRatio;
}
const x = (pdfWidth - imgWidth) / 2;
const y = 40;
pdf.addImage(imgData, 'PNG', x, y, imgWidth, imgHeight);
pdf.save('Cardio-Workout-Dashboard.pdf');
}).catch(err => {
if (pdfButtonWrapper) pdfButtonWrapper.style.display = 'block';
console.error("Error generating PDF:", err);
alert("Sorry, an error occurred while creating the PDF.");
});
}
// --- START THE APP ---
initialize();
});
