added openfoodatabase

This commit is contained in:
2025-10-03 17:56:32 -07:00
parent f931edf8dd
commit 2f1bbefb94
5 changed files with 234 additions and 1 deletions

View File

@@ -6,6 +6,10 @@
<i class="bi bi-plus-circle"></i> Add New Food
</button>
<button type="button" class="btn btn-secondary btn-lg mb-4" data-bs-toggle="modal" data-bs-target="#addFromOpenFoodFactsModal" data-testid="add-from-open-food-facts">
<i class="bi bi-search"></i> Add from Open Food Facts
</button>
<h3>Foods Database</h3>
<div class="table-responsive">
<table class="table table-striped">
@@ -57,6 +61,8 @@
</div>
</div>
{% include 'modals/add_from_open_food_facts.html' %}
<!-- Add Food Modal -->
<div class="modal fade" id="addFoodModal" tabindex="-1" aria-labelledby="addFoodModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
@@ -326,4 +332,78 @@ document.addEventListener('DOMContentLoaded', function() {
};
});
</script>
<script>
// Open Food Facts Modal Logic
async function searchOpenFoodFacts() {
const query = document.querySelector('#addFromOpenFoodFactsModal input[name="openfoodfacts_query"]').value;
const resultsContainer = document.getElementById('openFoodFactsResults');
resultsContainer.innerHTML = '<div class="text-center"><div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div></div>';
try {
const response = await fetch(`/foods/search_openfoodfacts?query=${query}`);
const data = await response.json();
resultsContainer.innerHTML = ''; // Clear spinner here, before populating or showing "no results"
if (data.status === 'success' && data.results.length > 0) {
data.results.forEach(food => {
const item = document.createElement('a');
item.href = '#';
item.className = 'list-group-item list-group-item-action';
item.textContent = `${food.name} - ${food.brand}`;
item.onclick = (e) => {
e.preventDefault();
selectOpenFoodFactsProduct(food);
};
resultsContainer.appendChild(item);
});
} else {
resultsContainer.innerHTML = `<div class="list-group-item">No results found.</div>`;
}
} catch (error) {
resultsContainer.innerHTML = `<div class="list-group-item">Error: ${error.message}</div>`;
}
}
function selectOpenFoodFactsProduct(food) {
const form = document.getElementById('addOpenFoodFactsForm');
form.querySelector('input[name="name"]').value = food.name;
form.querySelector('input[name="brand"]').value = food.brand;
form.querySelector('input[name="serving_size"]').value = food.serving_size;
form.querySelector('input[name="serving_unit"]').value = food.serving_unit;
form.querySelector('input[name="calories"]').value = food.calories;
form.querySelector('input[name="protein"]').value = food.protein;
form.querySelector('input[name="carbs"]').value = food.carbs;
form.querySelector('input[name="fat"]').value = food.fat;
form.querySelector('input[name="fiber"]').value = food.fiber;
form.querySelector('input[name="sugar"]').value = food.sugar;
form.querySelector('input[name="sodium"]').value = food.sodium;
form.querySelector('input[name="calcium"]').value = food.calcium;
form.querySelector('input[name="openfoodfacts_id"]').value = food.openfoodfacts_id;
}
async function submitOpenFoodFactsForm() {
const form = document.getElementById('addOpenFoodFactsForm');
const formData = new FormData(form);
try {
const response = await fetch(form.action, {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.status === 'success') {
bootstrap.Modal.getInstance(document.getElementById('addFromOpenFoodFactsModal')).hide();
location.reload();
} else {
alert('Error: ' + result.message);
}
} catch (error) {
alert('Error submitting form: ' + error.message);
}
}
</script>
{% endblock %}

View File

@@ -0,0 +1,94 @@
<!-- Add from Open Food Facts Modal -->
<div class="modal fade" id="addFromOpenFoodFactsModal" tabindex="-1" aria-labelledby="addFromOpenFoodFactsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addFromOpenFoodFactsModalLabel">Add Food from Open Food Facts</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- Search Bar -->
<div class="input-group mb-3">
<input type="text" class="form-control" name="openfoodfacts_query" placeholder="Search for a food...">
<button class="btn btn-outline-secondary" type="button" onclick="searchOpenFoodFacts()">Search</button>
</div>
<!-- Search Results -->
<div id="openFoodFactsResults" class="list-group" style="max-height: 300px; overflow-y: auto;">
<!-- Results will be populated here -->
</div>
<hr>
<!-- Food Form -->
<form id="addOpenFoodFactsForm" action="/foods/add_openfoodfacts" method="post">
<input type="hidden" name="openfoodfacts_id">
<div class="row">
<div class="col-8 mb-3">
<label class="form-label">Name</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="col-4 mb-3">
<label class="form-label">Brand</label>
<input type="text" class="form-control" name="brand" placeholder="Optional">
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<label class="form-label">Serving Size</label>
<input type="text" class="form-control" name="serving_size" required>
</div>
<div class="col-6 mb-3">
<label class="form-label">Unit</label>
<input type="text" class="form-control" name="serving_unit" required>
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<label class="form-label">Calories</label>
<input type="number" step="0.1" class="form-control" name="calories" required>
</div>
<div class="col-6 mb-3">
<label class="form-label">Protein (g)</label>
<input type="number" step="0.1" class="form-control" name="protein" required>
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<label class="form-label">Carbs (g)</label>
<input type="number" step="0.1" class="form-control" name="carbs" required>
</div>
<div class="col-6 mb-3">
<label class="form-label">Fat (g)</label>
<input type="number" step="0.1" class="form-control" name="fat" required>
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<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 mb-3">
<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">
<div class="col-6 mb-3">
<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 mb-3">
<label class="form-label">Calcium (mg)</label>
<input type="number" step="0.1" class="form-control" name="calcium" value="0">
</div>
</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="submitOpenFoodFactsForm()">Add Food</button>
</div>
</div>
</div>
</div>