Add food item management and improve barcode workflow

Implemented routes and forms for adding and viewing food items by barcode, including templates for displaying and entering nutritional information. Enhanced the scan workflow to redirect to food item details or entry form. Added admin ability to delete food items. Improved UI for login and scan pages. Updated FoodItem model and form fields for consistency and accuracy.
This commit is contained in:
2025-06-29 08:39:25 +02:00
parent 0919048cfd
commit a39f54dbb0
10 changed files with 260 additions and 90 deletions

View File

@@ -1,76 +1,32 @@
{% extends "base.html" %}
{% block content %}
<div id="main" class="container text-center">
<div class="container py-5">
<div class="text-center mb-4">
<h1 class="fw-bold">📷 ZXing Barcode Scanner</h1>
<p class="text-muted">Use your camera to scan barcodes in real time.</p>
</div>
<div class="d-flex justify-content-center mb-4">
<video id="video" class="border rounded shadow-sm" style="width: 100%; max-width: 500px;" autoplay
muted></video>
</div>
<div class="d-flex justify-content-center">
<button id="startButton" class="btn btn-primary px-4">Start Scanning</button>
<button id="stopButton" class="btn btn-danger px-4 ms-3">Stop</button>
</div>
</div>
<template id="scan_result">
<div>
<h5>Result:</h5>
<p id="result" class="fw-bold text-success"></p>
</div>
<div id="product-info"></div>
</template>
<template id="template_Reader">
<h1 class="mb-4">📷 ZXing Barcode Scanner</h1>
<div class="mb-3">
<video id="video" class="border rounded shadow-sm" width="100%" style="max-width: 500px;"></video>
</div>
<div class="mb-3">
<button id="startButton" class="btn btn-primary">Start Scanning</button>
<button id="stopButton" class="btn btn-danger ms-2">Stop</button>
</div>
</template>
<script type="module">
import { BrowserMultiFormatReader } from 'https://cdn.jsdelivr.net/npm/@zxing/library@0.21.3/+esm';
const mainElement = document.getElementById('main');
const readerTemplate = document.getElementById('template_Reader')
const readerClone = readerTemplate.content.cloneNode(true);
const resultTemplate = document.getElementById('scan_result')
const resultClone = resultTemplate.content.cloneNode(true);
mainElement.appendChild(readerClone);
// constants
const codeReader = new BrowserMultiFormatReader();
const videoElement = document.getElementById('video');
async function fetchProductData(barcode) {
// Step 1: GET Data
const response = await fetch(`/nutri/${barcode}`);
// Step 2: Check if response wasn't ok
if (!response.ok) throw new Error('Network response was not ok');
// Step 3: Convert response to json and check if empty
const nutritionData = await response.json();
mainElement.innerHTML = '';
mainElement.appendChild(resultClone);
const resultElement = document.getElementById('result');
resultElement.textContent = barcode;
const container = document.getElementById('product-info');
if (Object.keys(nutritionData).length === 0) {
// No data, enter new data
}
else {
container.innerHTML = `
<h2>${nutritionData.name}</h2>
<p><strong>Barcode:</strong> ${nutritionData.barcode}</p>
<p><strong>Energy:</strong> ${nutritionData.energy_100g} kcal per 100g</p>
<p><strong>Carbs:</strong> ${nutritionData.carbs_100g} g</p>
<p><strong>Sugar:</strong> ${nutritionData.sugar_100g} g</p>
<p><strong>Fats:</strong> ${nutritionData.fats_100g} g</p>
<p><strong>Saturated Fats:</strong> ${nutritionData.saturated_fats_100g} g</p>
<p><strong>Protein:</strong> ${nutritionData.protein_100g} g</p>
`;
}
}
// Start scanning for barcode
document.getElementById('startButton').addEventListener('click', async () => {
console.log('[DEBUG] Start button clicked')
@@ -89,20 +45,14 @@
await codeReader.decodeFromVideoDevice(selectedDeviceId, videoElement, async (result, err) => {
if (result) {
const codeText = result.getText();
try {
await fetchProductData(codeText)
codeReader.reset();
} catch (error) {
console.error('Error fetching nutrition data:', error);
}
const baseURL = "{{url_for('food_item', barcode='0')}}"
window.location.href = baseURL.replace("0", encodeURIComponent(codeText))
}
});
});
document.getElementById('stopButton').addEventListener('click', () => {
codeReader.reset();
resultElement.textContent = '';
container.innerHTML = ""
});
</script>
{% endblock %}