118 lines
4.0 KiB
Plaintext
118 lines
4.0 KiB
Plaintext
<h1 class="text-3xl font-bold mb-6">Progress & Trends</h1>
|
|
|
|
<!-- Date Range Filter -->
|
|
<div class="mb-6 flex justify-end">
|
|
<form method="GET" action="/progress" class="bg-white rounded-lg shadow-sm border p-1 inline-flex">
|
|
<button type="submit" name="days" value="7" class="px-4 py-2 rounded-md text-sm font-medium transition <%= days === 7 ? 'bg-primary text-white' : 'text-gray-600 hover:text-primary' %>">7 Days</button>
|
|
<button type="submit" name="days" value="30" class="px-4 py-2 rounded-md text-sm font-medium transition <%= days === 30 ? 'bg-primary text-white' : 'text-gray-600 hover:text-primary' %>">30 Days</button>
|
|
<button type="submit" name="days" value="90" class="px-4 py-2 rounded-md text-sm font-medium transition <%= days === 90 ? 'bg-primary text-white' : 'text-gray-600 hover:text-primary' %>">90 Days</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Summary Stats -->
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
|
|
<div class="glass rounded-xl p-4 text-center">
|
|
<p class="text-gray-500 text-xs uppercase tracking-wide">Avg Calories</p>
|
|
<p class="text-2xl font-bold text-primary"><%= avg_calories %></p>
|
|
</div>
|
|
<div class="glass rounded-xl p-4 text-center">
|
|
<p class="text-gray-500 text-xs uppercase tracking-wide">Avg Protein</p>
|
|
<p class="text-2xl font-bold text-blue-600"><%= avg_protein %>g</p>
|
|
</div>
|
|
<div class="glass rounded-xl p-4 text-center">
|
|
<p class="text-gray-500 text-xs uppercase tracking-wide">Avg Carbs</p>
|
|
<p class="text-2xl font-bold text-yellow-600"><%= avg_carbs %>g</p>
|
|
</div>
|
|
<div class="glass rounded-xl p-4 text-center">
|
|
<p class="text-gray-500 text-xs uppercase tracking-wide">Avg Fat</p>
|
|
<p class="text-2xl font-bold text-orange-600"><%= avg_fat %>g</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
|
|
<!-- Weight Chart -->
|
|
<div class="glass rounded-xl p-6">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="font-bold text-lg">Weight Trend</h3>
|
|
<% if (weight_change !== null) { %>
|
|
<span class="text-sm font-medium <%= weight_change <= 0 ? 'text-green-600' : 'text-red-600' %>">
|
|
<%= weight_change > 0 ? '+' : '' %><%= weight_change.toFixed(1) %> kg
|
|
</span>
|
|
<% } %>
|
|
</div>
|
|
<div class="h-64">
|
|
<canvas id="weightChart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Calories Chart -->
|
|
<div class="glass rounded-xl p-6">
|
|
<h3 class="font-bold text-lg mb-4">Calorie Intake</h3>
|
|
<div class="h-64">
|
|
<canvas id="calorieChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Weight Chart
|
|
const weightCtx = document.getElementById('weightChart').getContext('2d');
|
|
const weightData = <%- JSON.stringify(weight_trend) %>;
|
|
|
|
new Chart(weightCtx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: weightData.map(d => new Date(d.date).toLocaleDateString(undefined, {month:'short', day:'numeric'})),
|
|
datasets: [{
|
|
label: 'Weight (kg)',
|
|
data: weightData.map(d => d.weight_kg),
|
|
borderColor: 'rgb(220, 38, 38)', // primary red
|
|
backgroundColor: 'rgba(220, 38, 38, 0.1)',
|
|
tension: 0.3,
|
|
fill: true
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: { display: false }
|
|
},
|
|
scales: {
|
|
y: {
|
|
beginAtZero: false
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Calorie Chart
|
|
const calorieCtx = document.getElementById('calorieChart').getContext('2d');
|
|
const calorieData = <%- JSON.stringify(calorie_trend) %>;
|
|
|
|
new Chart(calorieCtx, {
|
|
type: 'bar',
|
|
data: {
|
|
labels: calorieData.map(d => new Date(d.date).toLocaleDateString(undefined, {month:'short', day:'numeric'})),
|
|
datasets: [{
|
|
label: 'Calories',
|
|
data: calorieData.map(d => d.calories),
|
|
backgroundColor: 'rgba(220, 38, 38, 0.7)',
|
|
borderRadius: 4
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: { display: false }
|
|
},
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true
|
|
}
|
|
}
|
|
}
|
|
});
|
|
</script>
|