Files
gym-tracker/frontend/muscleGroups.js

167 lines
4.8 KiB
JavaScript
Raw Permalink Normal View History

2025-10-09 20:19:20 +02:00
// Muscle Groups Dashboard Component
// Configuration for the 6 muscle groups
const MUSCLE_GROUPS = ['Chest', 'Legs', 'Delts', 'Lats', 'Triceps', 'Biceps'];
/**
* Calculate statistics for each muscle group based on sessions
* @param {Array} sessions - Array of session objects
* @returns {Object} Statistics for each muscle group
*/
function calculateMuscleGroupStats(sessions) {
const now = new Date();
const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
const stats = {};
MUSCLE_GROUPS.forEach(muscle => {
// Filter sessions that include this muscle group
const muscleSessions = sessions.filter(session =>
session.muscle_groups.includes(muscle)
);
// Sort by date descending
const sortedSessions = muscleSessions
.map(s => ({ ...s, dateObj: new Date(s.date) }))
.sort((a, b) => b.dateObj - a.dateObj);
// Calculate days since last trained
let daysSince = null;
if (sortedSessions.length > 0) {
const lastDate = sortedSessions[0].dateObj;
const diffTime = now - lastDate;
daysSince = Math.floor(diffTime / (1000 * 60 * 60 * 24));
}
// Count sessions in last 7 days
const last7Days = sortedSessions.filter(s => s.dateObj >= sevenDaysAgo).length;
// Count sessions in last 30 days
const last30Days = sortedSessions.filter(s => s.dateObj >= thirtyDaysAgo).length;
// Determine status (good, warning, bad)
let status;
if (daysSince === null) {
status = 'bad'; // Never trained
} else if (daysSince <= 3) {
status = 'good';
} else if (daysSince <= 7) {
status = 'warning';
} else {
status = 'bad';
}
stats[muscle] = {
daysSince,
last7Days,
last30Days,
status
};
});
return stats;
}
/**
* Render muscle group cards in the dashboard
* @param {Object} stats - Statistics for each muscle group
*/
function renderMuscleGroups(stats) {
const container = document.getElementById('muscleGroupsGrid');
if (!container) return;
container.innerHTML = '';
MUSCLE_GROUPS.forEach(muscle => {
const muscleStats = stats[muscle];
const card = document.createElement('div');
card.className = `muscle-card status-${muscleStats.status}`;
const daysSinceText = muscleStats.daysSince === null
? 'Never trained'
: muscleStats.daysSince === 0
? 'Trained today'
: `${muscleStats.daysSince} day${muscleStats.daysSince === 1 ? '' : 's'} ago`;
card.innerHTML = `
<div class="muscle-card-header">
<h3 class="muscle-name">${muscle}</h3>
<div class="status-indicator ${muscleStats.status}"></div>
</div>
<div class="muscle-card-stats">
<div class="stat-row">
<span class="stat-label">Last trained:</span>
<span class="stat-value">${daysSinceText}</span>
</div>
<div class="stat-row">
<span class="stat-label">Last 7 days:</span>
<span class="stat-value">${muscleStats.last7Days}x</span>
</div>
<div class="stat-row">
<span class="stat-label">Last 30 days:</span>
<span class="stat-value">${muscleStats.last30Days}x</span>
</div>
</div>
`;
container.appendChild(card);
});
}
/**
* Calculate and update balance indicator
* @param {Object} stats - Statistics for each muscle group
*/
function updateBalanceIndicator(stats) {
const emojiElement = document.getElementById('balanceEmoji');
const textElement = document.getElementById('balanceText');
if (!emojiElement || !textElement) return;
// Check if all muscle groups meet certain criteria
const allTrainedLast7Days = MUSCLE_GROUPS.every(muscle =>
stats[muscle].last7Days >= 1
);
const allTrainedTwiceLast7Days = MUSCLE_GROUPS.every(muscle =>
stats[muscle].last7Days >= 2
);
let emoji, text, status;
if (allTrainedTwiceLast7Days) {
emoji = '=+';
text = 'Excellent Balance';
status = 'happy';
} else if (allTrainedLast7Days) {
emoji = '=';
text = 'Neutral Balance';
status = 'neutral';
} else {
emoji = '= ';
text = 'Poor Balance';
status = 'angry';
}
emojiElement.textContent = emoji;
textElement.textContent = text;
// Add status class for potential styling
const indicator = document.getElementById('balanceIndicator');
if (indicator) {
indicator.className = `balance-indicator balance-${status}`;
}
}
/**
* Update the entire muscle groups dashboard
* @param {Array} sessions - Array of session objects
*/
function updateMuscleGroupsDashboard(sessions) {
const stats = calculateMuscleGroupStats(sessions);
renderMuscleGroups(stats);
updateBalanceIndicator(stats);
}