Form changes Horizon - Upload Daily Field Work Photo

This commit is contained in:
Tanuja Pansare 2026-11-02 12:47:30 +05:30
parent 07a127d003
commit f5b6ae5550
1 changed files with 85 additions and 33 deletions

View File

@ -190,6 +190,13 @@
style="display:none;"> style="display:none;">
<div class="d-flex flex-wrap gap-2 mt-2"> <div class="d-flex flex-wrap gap-2 mt-2">
<button type="button" id="switch-photo-camera"
class="btn btn-info" style="display:none;">
<i class="mdi mdi-camera-switch me-1"></i>
Switch Camera
</button>
<button type="button" id="capture-photo" <button type="button" id="capture-photo"
class="btn btn-success" style="display:none;"> class="btn btn-success" style="display:none;">
Capture Photo Capture Photo
@ -392,30 +399,34 @@
let photoStream = null; let photoStream = null;
let photoStream = null;
let currentCamera = 'environment';
const video = document.getElementById('photo-camera-preview'); const video = document.getElementById('photo-camera-preview');
const preview = document.getElementById('photo-captured-preview'); const preview = document.getElementById('photo-captured-preview');
const photoInput = document.getElementById('field-upload_photo'); const photoInput = document.getElementById('field-upload_photo');
$('#start-photo-camera').on('click', async function () { // Start camera
async function startPhotoCamera(cameraType = currentCamera) {
try { try {
// Stop previous camera before switching
stopPhotoCamera();
currentCamera = cameraType;
if (!navigator.mediaDevices || if (!navigator.mediaDevices ||
!navigator.mediaDevices.getUserMedia) { !navigator.mediaDevices.getUserMedia) {
throw new Error('Camera API is unavailable. Use HTTPS or localhost.'); throw new Error('Camera access requires HTTPS or localhost.');
} }
// Request camera permission
photoStream = await navigator.mediaDevices.getUserMedia({ photoStream = await navigator.mediaDevices.getUserMedia({
video: { video: {
facingMode: { ideal: 'environment' } facingMode: { exact: currentCamera }
}, },
audio: false audio: false
}); });
// Check required elements
if (!video || !preview || !photoInput) {
throw new Error('Camera elements are missing from the page.');
}
video.srcObject = photoStream; video.srcObject = photoStream;
video.style.display = 'block'; video.style.display = 'block';
preview.style.display = 'none'; preview.style.display = 'none';
@ -423,43 +434,73 @@
await video.play(); await video.play();
$('#start-photo-camera').hide(); $('#start-photo-camera').hide();
$('#switch-photo-camera').show();
$('#capture-photo').show(); $('#capture-photo').show();
$('#retake-photo').hide(); $('#retake-photo').hide();
} catch (error) { } catch (error) {
console.error('Camera error:', error); console.error('Camera error:', error);
// Stop any partially opened camera stream stopPhotoCamera();
if (photoStream) {
photoStream.getTracks().forEach(track => track.stop());
photoStream = null;
}
if (error.name === 'NotAllowedError' || // Some devices do not support the requested camera.
error.name === 'PermissionDeniedError') { // Fall back to the browser's preferred camera.
if (error.name === 'OverconstrainedError' ||
error.name === 'NotFoundError') {
try {
photoStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: false
});
video.srcObject = photoStream;
video.style.display = 'block';
await video.play();
$('#start-photo-camera').hide();
$('#switch-photo-camera').show();
$('#capture-photo').show();
return;
} catch (fallbackError) {
console.error('Fallback camera error:', fallbackError);
}
}
Swal.fire({ Swal.fire({
icon: 'warning', icon: 'warning',
title: 'Camera Access Denied', title: 'Camera Unavailable',
text: 'Please enable camera permission for this website in your browser settings, then try again.' text: 'Please check camera permission and camera availability.'
});
} else {
Swal.fire({
icon: 'error',
title: 'Unable to Open Camera',
text: error.message || 'Please check your camera and try again.'
}); });
} }
} }
// Open camera
$('#start-photo-camera').on('click', function () {
startPhotoCamera('environment');
}); });
// Switch between front and back cameras
$('#switch-photo-camera').on('click', function () {
const nextCamera =
currentCamera === 'environment' ? 'user' : 'environment';
startPhotoCamera(nextCamera);
});
// Capture photo
$('#capture-photo').on('click', function () { $('#capture-photo').on('click', function () {
if (!photoStream || !video.videoWidth) { if (!photoStream || !video.videoWidth) {
return; return;
} }
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.width = video.videoWidth; canvas.width = video.videoWidth;
canvas.height = video.videoHeight; canvas.height = video.videoHeight;
@ -468,6 +509,7 @@
); );
canvas.toBlob(function (blob) { canvas.toBlob(function (blob) {
if (!blob) { if (!blob) {
Swal.fire('Error', 'Could not capture the photo.', 'error'); Swal.fire('Error', 'Could not capture the photo.', 'error');
return; return;
@ -489,28 +531,38 @@
stopPhotoCamera(); stopPhotoCamera();
$('#start-photo-camera').show();
$('#switch-photo-camera').hide();
$('#capture-photo').hide(); $('#capture-photo').hide();
$('#start-photo-camera').hide(); $('#retake-photo').hide();
$('#retake-photo').show();
}, 'image/jpeg', 0.9); }, 'image/jpeg', 0.9);
}); });
// Retake photo
$('#retake-photo').on('click', function () { $('#retake-photo').on('click', function () {
photoInput.value = ''; photoInput.value = '';
preview.src = ''; preview.src = '';
preview.style.display = 'none'; preview.style.display = 'none';
$('#retake-photo').hide(); $('#retake-photo').hide();
$('#start-photo-camera').trigger('click');
startPhotoCamera(currentCamera);
}); });
// Stop camera
function stopPhotoCamera() { function stopPhotoCamera() {
if (photoStream) { if (photoStream) {
photoStream.getTracks().forEach(track => track.stop()); photoStream.getTracks().forEach(track => track.stop());
photoStream = null; photoStream = null;
} }
if (video) {
video.srcObject = null; video.srcObject = null;
} }
}
window.addEventListener('beforeunload', stopPhotoCamera); window.addEventListener('beforeunload', stopPhotoCamera);