Files
foodplanner/templates/combo.html

523 lines
20 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meal Planner</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.nav-tabs .nav-link.active {
background-color: #0d6efd;
color: white;
}
.nutrition-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 10px;
margin: 10px 0;
}
.nutrition-item {
text-align: center;
padding: 8px;
background-color: #f8f9fa;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="container-fluid">
<!-- <h1 class="mt-3 mb-4">Meal Planner</h1> -->
<div class="d-flex justify-content-between align-items-center">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link" onclick="location.href='/foods'">Foods</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" onclick="location.href='/meals'">Meals</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" onclick="location.href='/plan'">Plan A</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" onclick="location.href='/detailed'">Detailed Planner</button>
</li>
</ul>
<div class="person-toggle">
<select id="personSelect" class="form-select" onchange="switchPerson()">
<option value="Sarah" {% if person == "Sarah" %}selected{% endif %}>Sarah</option>
<option value="Stuart" {% if person == "Stuart" %}selected{% endif %}>Stuart</option>
</select>
</div>
</div>
<div class="tab-content mt-3">
{% block content %}{% endblock %}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
function switchPerson() {
const person = document.getElementById('personSelect').value;
localStorage.setItem('selectedPerson', person);
const currentUrl = new URL(window.location);
currentUrl.searchParams.set('person', person);
window.location.href = currentUrl.toString();
}
</script>
</body>
</html>
<!-- templates/index.html -->
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="col-12">
<h2>Welcome to Meal Planner</h2>
<p>Use the tabs above to navigate:</p>
<ul>
<li><strong>Foods</strong> - Manage your food database with nutritional information</li>
<li><strong>Meals</strong> - Create meals by combining foods</li>
<li><strong>Plan A</strong> - Create 2-week meal plans with daily totals</li>
<li><strong>Detailed Planner</strong> - View detailed breakdown for a specific day</li>
</ul>
</div>
</div>
{% endblock %}
<!-- templates/foods.html -->
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="col-md-4">
<h3>Add New Food</h3>
<form action="/foods/add" method="post">
<div class="mb-3">
<label class="form-label">Name</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="row">
<div class="col-6">
<label class="form-label">Serving Size</label>
<input type="text" class="form-control" name="serving_size" required>
</div>
<div class="col-6">
<label class="form-label">Unit</label>
<input type="text" class="form-control" name="serving_unit" required>
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<label class="form-label">Calories</label>
<input type="number" step="0.1" class="form-control" name="calories" required>
</div>
<div class="col-6">
<label class="form-label">Protein (g)</label>
<input type="number" step="0.1" class="form-control" name="protein" required>
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<label class="form-label">Carbs (g)</label>
<input type="number" step="0.1" class="form-control" name="carbs" required>
</div>
<div class="col-6">
<label class="form-label">Fat (g)</label>
<input type="number" step="0.1" class="form-control" name="fat" required>
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<label class="form-label">Fiber (g)</label>
<input type="number" step="0.1" class="form-control" name="fiber" value="0">
</div>
<div class="col-6">
<label class="form-label">Sugar (g)</label>
<input type="number" step="0.1" class="form-control" name="sugar" value="0">
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<label class="form-label">Sodium (mg)</label>
<input type="number" step="0.1" class="form-control" name="sodium" value="0">
</div>
<div class="col-6">
<label class="form-label">Calcium (mg)</label>
<input type="number" step="0.1" class="form-control" name="calcium" value="0">
</div>
</div>
<button type="submit" class="btn btn-primary mt-3">Add Food</button>
</form>
</div>
<div class="col-md-8">
<h3>Foods Database</h3>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Serving</th>
<th>Cal</th>
<th>Protein</th>
<th>Carbs</th>
<th>Fat</th>
<th>Fiber</th>
<th>Sodium</th>
<th>Calcium</th>
</tr>
</thead>
<tbody>
{% for food in foods %}
<tr>
<td>{{ food.name }}</td>
<td>{{ food.serving_size }} {{ food.serving_unit }}</td>
<td>{{ "%.1f"|format(food.calories) }}</td>
<td>{{ "%.1f"|format(food.protein) }}g</td>
<td>{{ "%.1f"|format(food.carbs) }}g</td>
<td>{{ "%.1f"|format(food.fat) }}g</td>
<td>{{ "%.1f"|format(food.fiber) }}g</td>
<td>{{ "%.1f"|format(food.sodium) }}mg</td>
<td>{{ "%.1f"|format(food.calcium) }}mg</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
<!-- templates/meals.html -->
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="col-md-4">
<h3>Create New Meal</h3>
<form action="/meals/add" method="post">
<div class="mb-3">
<label class="form-label">Meal Name</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="mb-3">
<label class="form-label">Meal Type</label>
<select class="form-control" name="meal_type" required>
<option value="breakfast">Breakfast</option>
<option value="lunch">Lunch</option>
<option value="dinner">Dinner</option>
<option value="snack">Snack</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Create Meal</button>
</form>
<div class="mt-4">
<h4>Add Food to Meal</h4>
<form id="addFoodForm">
<div class="mb-3">
<label class="form-label">Select Meal</label>
<select class="form-control" id="mealSelect">
<option value="">Choose meal...</option>
{% for meal in meals %}
<option value="{{ meal.id }}">{{ meal.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Select Food</label>
<select class="form-control" id="foodSelect">
<option value="">Choose food...</option>
{% for food in foods %}
<option value="{{ food.id }}">{{ food.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Quantity</label>
<input type="number" step="0.1" class="form-control" id="quantity" value="1">
</div>
<button type="button" onclick="addFoodToMeal()" class="btn btn-success">Add Food</button>
</form>
</div>
</div>
<div class="col-md-8">
<h3>Meals</h3>
{% for meal in meals %}
<div class="card mb-3">
<div class="card-header">
<strong>{{ meal.name }}</strong> - {{ meal.meal_type.title() }}
</div>
<div class="card-body">
{% if meal.meal_foods %}
<ul>
{% for meal_food in meal.meal_foods %}
<li>{{ meal_food.quantity }} × {{ meal_food.food.name }}</li>
{% endfor %}
</ul>
{% else %}
<em>No foods added yet</em>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
<script>
function addFoodToMeal() {
const mealId = document.getElementById('mealSelect').value;
const foodId = document.getElementById('foodSelect').value;
const quantity = document.getElementById('quantity').value;
if (!mealId || !foodId || !quantity) {
alert('Please fill all fields');
return;
}
const formData = new FormData();
formData.append('food_id', foodId);
formData.append('quantity', quantity);
fetch(`/meals/${mealId}/add_food`, {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
location.reload();
}
});
}
</script>
{% endblock %}
<!-- templates/plan.html -->
{% extends "base.html" %}
{% block content %}
<h3>2-Week Plan for {{ person }}</h3>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Date</th>
<th>Meals</th>
<th>Calories</th>
<th>Protein</th>
<th>Carbs</th>
<th>Fat</th>
<th>Net Carbs</th>
<th>Calcium</th>
<th>Sodium</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for date in dates %}
<tr>
<td>{{ date.strftime('%m/%d') }}</td>
<td>
{% for plan in plans[date] %}
<span class="badge bg-secondary me-1">{{ plan.meal.name }}</span>
{% endfor %}
</td>
<td>{{ "%.0f"|format(daily_totals[date].calories or 0) }}</td>
<td>{{ "%.1f"|format(daily_totals[date].protein or 0) }}g ({{ daily_totals[date].protein_pct or 0 }}%)</td>
<td>{{ "%.1f"|format(daily_totals[date].carbs or 0) }}g ({{ daily_totals[date].carbs_pct or 0 }}%)</td>
<td>{{ "%.1f"|format(daily_totals[date].fat or 0) }}g ({{ daily_totals[date].fat_pct or 0 }}%)</td>
<td>{{ "%.1f"|format(daily_totals[date].net_carbs or 0) }}g</td>
<td>{{ "%.0f"|format(daily_totals[date].calcium or 0) }}mg</td>
<td>{{ "%.0f"|format(daily_totals[date].sodium or 0) }}mg</td>
<td>
<button class="btn btn-sm btn-primary" onclick="addMealToDay('{{ date }}')">Add Meal</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Add Meal Modal -->
<div class="modal fade" id="addMealModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Meal to Plan</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="addMealForm">
<input type="hidden" id="planDate" name="plan_date">
<input type="hidden" name="person" value="{{ person }}">
<div class="mb-3">
<label class="form-label">Select Meal</label>
<select class="form-control" name="meal_id" required>
<option value="">Choose meal...</option>
{% for meal in meals %}
<option value="{{ meal.id }}">{{ meal.name }} ({{ meal.meal_type }})</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Meal Time</label>
<select class="form-control" name="meal_time" required>
<option value="Breakfast">Breakfast</option>
<option value="Lunch">Lunch</option>
<option value="Dinner">Dinner</option>
<option value="Snack 1">Snack 1</option>
<option value="Snack 2">Snack 2</option>
<option value="Beverage 1">Beverage 1</option>
<option value="Beverage 2">Beverage 2</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="submitMealToPlan()">Add Meal</button>
</div>
</div>
</div>
</div>
<script>
function addMealToDay(date) {
document.getElementById('planDate').value = date;
new bootstrap.Modal(document.getElementById('addMealModal')).show();
}
function submitMealToPlan() {
const form = document.getElementById('addMealForm');
const formData = new FormData(form);
fetch('/plan/add', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
location.reload();
}
});
}
</script>
{% endblock %}
<!-- templates/detailed.html -->
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="col-md-6">
<h3>Detailed View for {{ person }}</h3>
<form method="get">
<input type="hidden" name="person" value="{{ person }}">
<div class="input-group mb-3">
<input type="date" class="form-control" name="plan_date" value="{{ selected_date }}">
<button class="btn btn-primary" type="submit">View Date</button>
</div>
</form>
</div>
</div>
<h4>{{ selected_date.strftime('%A, %B %d, %Y') }}</h4>
{% for meal_detail in meal_details %}
<div class="card mb-3">
<div class="card-header">
<strong>{{ meal_detail.plan.meal.name }}</strong> - {{ meal_detail.plan.meal.meal_type.title() }}
</div>
<div class="card-body">
<h6>Foods:</h6>
<ul>
{% for meal_food in meal_detail.foods %}
<li>{{ meal_food.quantity }} × {{ meal_food.food.name }}
({{ meal_food.food.serving_size }} {{ meal_food.food.serving_unit }})
</li>
{% endfor %}
</ul>
<div class="nutrition-grid">
<div class="nutrition-item">
<strong>{{ "%.0f"|format(meal_detail.nutrition.calories) }}</strong><br>
<small>Calories</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(meal_detail.nutrition.protein) }}g</strong><br>
<small>Protein ({{ meal_detail.nutrition.protein_pct or 0 }}%)</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(meal_detail.nutrition.carbs) }}g</strong><br>
<small>Carbs ({{ meal_detail.nutrition.carbs_pct or 0 }}%)</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(meal_detail.nutrition.fat) }}g</strong><br>
<small>Fat ({{ meal_detail.nutrition.fat_pct or 0 }}%)</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(meal_detail.nutrition.net_carbs or 0) }}g</strong><br>
<small>Net Carbs</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.0f"|format(meal_detail.nutrition.calcium) }}mg</strong><br>
<small>Calcium</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.0f"|format(meal_detail.nutrition.sodium) }}mg</strong><br>
<small>Sodium</small>
</div>
</div>
</div>
</div>
{% endfor %}
<!-- Day Totals -->
<div class="card bg-light">
<div class="card-header">
<strong>Daily Totals</strong>
</div>
<div class="card-body">
<div class="nutrition-grid">
<div class="nutrition-item">
<strong>{{ "%.0f"|format(day_totals.calories) }}</strong><br>
<small>Total Calories</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(day_totals.protein) }}g</strong><br>
<small>Protein ({{ day_totals.protein_pct or 0 }}%)</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(day_totals.carbs) }}g</strong><br>
<small>Carbs ({{ day_totals.carbs_pct or 0 }}%)</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(day_totals.fat) }}g</strong><br>
<small>Fat ({{ day_totals.fat_pct or 0 }}%)</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.1f"|format(day_totals.net_carbs or 0) }}g</strong><br>
<small>Net Carbs</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.0f"|format(day_totals.calcium) }}mg</strong><br>
<small>Total Calcium</small>
</div>
<div class="nutrition-item">
<strong>{{ "%.0f"|format(day_totals.sodium) }}mg</strong><br>
<small>Total Sodium</small>
</div>
</div>
</div>
</div>
{% if not meal_details %}
<div class="alert alert-info">
No meals planned for this date. Go to the Plan A tab to add meals.
</div>
{% endif %}
{% endblock %}