mirror of
https://github.com/StefBuwalda/cal_counter.git
synced 2025-10-30 11:19:59 +00:00
Add barcode scanning and meal selection features
Introduces a barcode scanner page using the camera for food item entry, adds routes for selecting meal types and scanning products, and updates the test.html template to allow adding items to specific meals. Also updates branding in base.html, changes the Flask secret key, and enables SSL by default in app.py.
This commit is contained in:
62
application/user/templates/get_item.html
Normal file
62
application/user/templates/get_item.html
Normal file
@@ -0,0 +1,62 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="text-center mb-4">
|
||||
<h1 class="fw-bold">Barcode Scanner</h1>
|
||||
<p class="text-muted">Use your camera to scan barcodes</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>
|
||||
|
||||
|
||||
<script type="module">
|
||||
import { BrowserMultiFormatReader } from 'https://cdn.jsdelivr.net/npm/@zxing/library@0.21.3/+esm';
|
||||
|
||||
// constants
|
||||
const codeReader = new BrowserMultiFormatReader();
|
||||
const videoElement = document.getElementById('video');
|
||||
|
||||
|
||||
// Start scanning for barcode
|
||||
document.getElementById('startButton').addEventListener('click', async () => {
|
||||
console.log('[DEBUG] Start button clicked')
|
||||
try {
|
||||
await navigator.mediaDevices.getUserMedia({ video: true });
|
||||
} catch (err) {
|
||||
alert("No camera found or no camera permission");
|
||||
console.error("Could not access the camera:", err);
|
||||
return;
|
||||
}
|
||||
console.log('[DEBUG] Permission given and at least one device present');
|
||||
const devices = await codeReader.listVideoInputDevices();
|
||||
console.log('[DEBUG] Cameras found:', devices);
|
||||
const rearCamera = devices.find(device => device.label.toLowerCase().includes('back'))
|
||||
|| devices.find(device => device.label.toLowerCase().includes('rear'))
|
||||
|| devices[0]; // fallback
|
||||
|
||||
const selectedDeviceId = rearCamera?.deviceId;
|
||||
await codeReader.decodeFromVideoDevice(selectedDeviceId, videoElement, async (result, err) => {
|
||||
if (result) {
|
||||
// Result found, this should post the barcode
|
||||
const codeText = result.getText();
|
||||
const baseURL = "{{url_for('user.food_item', barcode='0')}}"
|
||||
window.location.href = baseURL.replace("0", encodeURIComponent(codeText))
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('stopButton').addEventListener('click', () => {
|
||||
codeReader.reset();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -23,47 +23,51 @@ Food Nutritional Info
|
||||
<p>More content here...</p>
|
||||
</div>
|
||||
<div class="p-3 mb-2 border rounded">
|
||||
<h4>Breakfast</h4>
|
||||
{% for log in logs[0] %}
|
||||
<p>{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h4 class="mb-0">Breakfast</h4>
|
||||
<a href="{{url_for('user.select_meal', meal_type=0)}}" class="btn btn-sm btn-primary">Add</a>
|
||||
</div>
|
||||
<div>
|
||||
{% for log in logs[0] %}
|
||||
<p class="p-0 mb-0">{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-3 mb-2 border rounded">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h4 class="mb-0">Lunch</h4>
|
||||
<a href="{{url_for('user.select_meal', meal_type=1)}}" class="btn btn-sm btn-primary">Add</a>
|
||||
</div>
|
||||
<div>
|
||||
{% for log in logs[1] %}
|
||||
<p class="p-0 mb-0">{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 mb-2 border rounded">
|
||||
<h4>Lunch</h4>
|
||||
{% for log in logs[1] %}
|
||||
<p>{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h4 class="mb-0">Dinner</h4>
|
||||
<a href="{{url_for('user.select_meal', meal_type=2)}}" class="btn btn-sm btn-primary">Add</a>
|
||||
</div>
|
||||
<div>
|
||||
{% for log in logs[2] %}
|
||||
<p class="p-0 mb-0">{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 mb-2 border rounded">
|
||||
<h4>Dinner</h4>
|
||||
{% for log in logs[2] %}
|
||||
<p>{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="p-3 mb-2 border rounded">
|
||||
<h4>Snacks</h4>
|
||||
{% for log in logs[3] %}
|
||||
<p>{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h4 class="mb-0">Snacks</h4>
|
||||
<a href="{{url_for('user.select_meal', meal_type=3)}}" class="btn btn-sm btn-primary">Add</a>
|
||||
</div>
|
||||
<div>
|
||||
{% for log in logs[3] %}
|
||||
<p class="p-0 mb-0">{{log.food_item.name}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container-fluid my-4">
|
||||
<div class="d-flex justify-content-center">
|
||||
<h1>Overview {{date}}</h1>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="mx-2">ENERGY</div>
|
||||
<div class="mx-2">PROTEIN</div>
|
||||
<div class="mx-2">CARBS</div>
|
||||
<div class="mx-2">FATS</div>
|
||||
</div>
|
||||
<div class="m-5"></div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div> Breakfast </div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock%}
|
||||
Reference in New Issue
Block a user