- Add openfoodfacts Python SDK dependency - Create foods/sources/openfoodfacts.py API wrapper with text_search - Add off_code field + find_or_create_from_search() to Food model - Add nutrition fields (protein, fat, carbs, fiber, sugar, sodium), ingredients, image, off_code to Drink model - Create FoodSearchView and FoodScrobbleFromSearchView at /foods/search/ - Route beverages to Drink model based on OFF category keywords - Update ManualScrobbleView to redirect '-f Food Name' to food search - Add Drinks section to home page and scrobble detail templates - Update drink_detail.html with nutrition grid and image display
157 lines
4.4 KiB
HTML
157 lines
4.4 KiB
HTML
{% extends "base_list.html" %}
|
|
{% load mathfilters %}
|
|
{% load static %}
|
|
{% load naturalduration %}
|
|
|
|
{% block title %}{{object.title}}{% endblock %}
|
|
|
|
{% block head_extra %}
|
|
<style>
|
|
.cover img {
|
|
width: 250px;
|
|
}
|
|
|
|
.cover {
|
|
float: left;
|
|
width: 252px;
|
|
padding: 0;
|
|
}
|
|
|
|
.summary {
|
|
float: left;
|
|
width: 600px;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.nutrition-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
|
gap: 0.5rem;
|
|
margin: 1rem 0;
|
|
}
|
|
|
|
.nutrition-item {
|
|
text-align: center;
|
|
padding: 0.5rem;
|
|
border: 1px solid #dee2e6;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.nutrition-item .value {
|
|
font-size: 1.25rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.nutrition-item .label {
|
|
font-size: 0.75rem;
|
|
color: #6c757d;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block lists %}
|
|
|
|
<div class="row">
|
|
{% if object.drink_image %}
|
|
<div class="cover">
|
|
<img src="{{ object.drink_image.url }}" alt="{{ object.title }}">
|
|
</div>
|
|
{% endif %}
|
|
<div class="summary">
|
|
{% if object.description %}
|
|
<p>{{object.description|safe|linebreaks|truncatewords:160}}</p>
|
|
<hr />
|
|
{% endif %}
|
|
|
|
{% if object.calories or object.protein %}
|
|
<div class="nutrition-grid">
|
|
{% if object.calories %}
|
|
<div class="nutrition-item">
|
|
<div class="value">{{ object.calories }}</div>
|
|
<div class="label">kcal</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if object.protein %}
|
|
<div class="nutrition-item">
|
|
<div class="value">{{ object.protein }}g</div>
|
|
<div class="label">Protein</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if object.fat %}
|
|
<div class="nutrition-item">
|
|
<div class="value">{{ object.fat }}g</div>
|
|
<div class="label">Fat</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if object.carbohydrates %}
|
|
<div class="nutrition-item">
|
|
<div class="value">{{ object.carbohydrates }}g</div>
|
|
<div class="label">Carbs</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if object.fiber %}
|
|
<div class="nutrition-item">
|
|
<div class="value">{{ object.fiber }}g</div>
|
|
<div class="label">Fiber</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if object.sugar %}
|
|
<div class="nutrition-item">
|
|
<div class="value">{{ object.sugar }}g</div>
|
|
<div class="label">Sugar</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if object.ingredients %}
|
|
<h5>Ingredients</h5>
|
|
<p>{{ object.ingredients }}</p>
|
|
{% endif %}
|
|
|
|
{% if object.off_code %}
|
|
<p><small class="text-muted">OFF: {{ object.off_code }}</small></p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<p>{{scrobbles.count}} scrobbles</p>
|
|
<p>
|
|
<a href="{{object.start_url}}">Drink again</a>
|
|
</p>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md">
|
|
<h3>Last scrobbles</h3>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">Date</th>
|
|
<th scope="col">Format</th>
|
|
<th scope="col">Size</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for scrobble in scrobbles.all|dictsortreversed:"timestamp" %}
|
|
<tr>
|
|
<td><a href="{{scrobble.get_absolute_url}}">{{scrobble.local_timestamp}}</a></td>
|
|
<td>{{ scrobble.logdata.format_display }}</td>
|
|
<td>
|
|
{% if scrobble.logdata.size_ml %}
|
|
{% if request.user.profile.volume_unit == "imperial" %}
|
|
{{ scrobble.logdata.size_oz }} oz
|
|
{% else %}
|
|
{{ scrobble.logdata.size_ml }} mL
|
|
{% endif %}
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|