initial commit
This commit is contained in:
117
views/progress.ejs
Normal file
117
views/progress.ejs
Normal file
@@ -0,0 +1,117 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user