156 lines
5.6 KiB
HTML
156 lines
5.6 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static i18n%}
|
|
|
|
{% block content %}
|
|
<div class="container my-4">
|
|
<h3 class="mb-4">{{ _("Scan Vehicle Code")}}</h3>
|
|
|
|
<form id="car-form" class="mb-3">
|
|
<div class="mb-3">
|
|
<label for="vin_no" class="form-label">{{ _("VIN / Barcode / QR Code")}}</label>
|
|
<input type="text" class="form-control" id="vin_no" name="vin_no" readonly>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<button type="button" class="btn btn-primary" id="capture-btn">{{ _("Start Scanning")}}</button>
|
|
<button type="submit" class="btn btn-success">{{ _("Search") }}</button>
|
|
</div>
|
|
</form>
|
|
|
|
<div id="camera-container" class="my-3" style="display:none;">
|
|
<video id="camera" class="border rounded" autoplay playsinline width="100%"></video>
|
|
<div class="mt-2 d-flex gap-2">
|
|
<button class="btn btn-warning" id="toggle-btn">{{ _("Switch Camera")}}</button>
|
|
<button class="btn btn-info" id="scan-btn">{{ _("Scan") }}</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="result" class="alert mt-3" style="display:none;"></div>
|
|
</div>
|
|
|
|
<script>
|
|
function getCookie(name) {
|
|
let cookieValue = null;
|
|
if (document.cookie && document.cookie !== '') {
|
|
const cookies = document.cookie.split(';');
|
|
for (let cookie of cookies) {
|
|
cookie = cookie.trim();
|
|
if (cookie.startsWith(name + '=')) {
|
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return cookieValue;
|
|
}
|
|
|
|
const captureBtn = document.getElementById('capture-btn');
|
|
const cameraContainer = document.getElementById('camera-container');
|
|
const videoElement = document.getElementById('camera');
|
|
const toggleBtn = document.getElementById('toggle-btn');
|
|
const scanBtn = document.getElementById('scan-btn');
|
|
const vinInput = document.getElementById('vin_no');
|
|
const resultElement = document.getElementById('result');
|
|
const form = document.getElementById('car-form');
|
|
|
|
let mediaStream = null;
|
|
let currentCameraIndex = 0;
|
|
let cameras = [];
|
|
|
|
form.addEventListener('submit', function (e) {
|
|
e.preventDefault(); // Prevent form reload
|
|
});
|
|
|
|
async function getCameras() {
|
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
cameras = devices.filter(device => device.kind === 'videoinput');
|
|
}
|
|
|
|
async function startCamera(deviceId) {
|
|
if (mediaStream) {
|
|
mediaStream.getTracks().forEach(track => track.stop());
|
|
}
|
|
|
|
mediaStream = await navigator.mediaDevices.getUserMedia({
|
|
video: { deviceId: { exact: deviceId } }
|
|
});
|
|
|
|
videoElement.srcObject = mediaStream;
|
|
}
|
|
|
|
toggleBtn.addEventListener('click', async () => {
|
|
if (cameras.length > 1) {
|
|
currentCameraIndex = (currentCameraIndex + 1) % cameras.length;
|
|
await startCamera(cameras[currentCameraIndex].deviceId);
|
|
}
|
|
});
|
|
|
|
scanBtn.addEventListener('click', () => {
|
|
resultElement.style.display = 'block';
|
|
resultElement.className = 'alert alert-secondary';
|
|
resultElement.textContent = 'Scanning...';
|
|
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = videoElement.videoWidth;
|
|
canvas.height = videoElement.videoHeight;
|
|
const context = canvas.getContext('2d');
|
|
context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
|
|
|
|
canvas.toBlob((blob) => {
|
|
const formData = new FormData();
|
|
formData.append('image', blob, 'code_image.jpg');
|
|
|
|
fetch('{% url "car_search" %}', {
|
|
method: 'POST',
|
|
headers: {
|
|
"X-Requested-With": "XMLHttpRequest",
|
|
'X-CSRFToken': getCookie('csrftoken')
|
|
},
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
if (data.redirect_url) {
|
|
window.location.href = data.redirect_url;
|
|
} else {
|
|
vinInput.value = data.code;
|
|
resultElement.className = 'alert alert-success';
|
|
resultElement.textContent = `Code found: ${data.code}`;
|
|
}
|
|
} else {
|
|
resultElement.className = 'alert alert-danger';
|
|
resultElement.textContent = `Error: ${data.error}`;
|
|
}
|
|
})
|
|
.catch(err => {
|
|
resultElement.className = 'alert alert-danger';
|
|
resultElement.textContent = 'Unexpected error occurred.';
|
|
console.error(err);
|
|
})
|
|
.finally(() => {
|
|
stopCamera();
|
|
});
|
|
});
|
|
});
|
|
|
|
captureBtn.addEventListener('click', async () => {
|
|
cameraContainer.style.display = 'block';
|
|
await getCameras();
|
|
if (cameras.length > 0) {
|
|
await startCamera(cameras[currentCameraIndex].deviceId);
|
|
} else {
|
|
resultElement.className = 'alert alert-warning';
|
|
resultElement.textContent = 'No cameras found.';
|
|
resultElement.style.display = 'block';
|
|
}
|
|
});
|
|
|
|
function stopCamera() {
|
|
if (mediaStream) {
|
|
mediaStream.getTracks().forEach(track => track.stop());
|
|
mediaStream = null;
|
|
}
|
|
cameraContainer.style.display = 'none';
|
|
}
|
|
</script>
|
|
{% endblock content %} |