+ Click Punch In/Punch Out. The app will ask for browser location before submitting attendance.
+
+
+ If branch geofence/IP verification is not configured, attendance may be approved without location check. Configure branch attendance geo/IP settings to enforce verification.
+
+
+
+
+
+
+
๐
+
+
Enable location for attendance
+
+ To mark attendance, this app needs your current location to verify whether you are within your branch geofence.
+ Click Continue, then choose Allow in the browser location popup.
+
+
+ If you are outside the branch or location is denied/unavailable, your attendance can still be saved.
+ It will require approval only when branch geofence/IP verification is configured.
+
+
+
+
+
+
+
+
+
{% endif %}
@@ -51,6 +87,7 @@ window.EmployeePortalGeo = window.EmployeePortalGeo || (function () {
'border-slate-200 bg-slate-50 text-slate-600'
);
}
+
function setHidden(form, lat, lon, acc) {
var latInput = form.querySelector('input[name="latitude"]');
var lonInput = form.querySelector('input[name="longitude"]');
@@ -59,35 +96,84 @@ window.EmployeePortalGeo = window.EmployeePortalGeo || (function () {
if (lonInput) lonInput.value = lon || '';
if (accInput) accInput.value = acc || '';
}
+
+ function openLocationModal() {
+ return new Promise(function (resolve) {
+ var modal = document.getElementById('employee-location-consent-modal');
+ var modalContinue = document.getElementById('employee-location-modal-continue');
+ var modalCancel = document.getElementById('employee-location-modal-cancel');
+ if (!modal || !modalContinue || !modalCancel) {
+ resolve(true);
+ return;
+ }
+
+ function cleanup(result) {
+ modal.classList.add('hidden');
+ modal.classList.remove('flex');
+ modal.setAttribute('aria-hidden', 'true');
+ modalContinue.removeEventListener('click', onContinue);
+ modalCancel.removeEventListener('click', onCancel);
+ resolve(result);
+ }
+ function onContinue() { cleanup(true); }
+ function onCancel() {
+ updateStatus('Attendance punch cancelled. Location permission was not requested.', 'warn');
+ cleanup(false);
+ }
+
+ modalContinue.addEventListener('click', onContinue);
+ modalCancel.addEventListener('click', onCancel);
+ modal.classList.remove('hidden');
+ modal.classList.add('flex');
+ modal.setAttribute('aria-hidden', 'false');
+ modalContinue.focus();
+ });
+ }
+
+ function captureLocation(form) {
+ return new Promise(function (resolve) {
+ if (!navigator.geolocation) {
+ setHidden(form, '', '', '');
+ updateStatus('Browser geolocation is not available. Attendance can be saved, but geofence verification cannot be performed.', 'warn');
+ resolve(false);
+ return;
+ }
+ updateStatus('Browser location popup opened. Please choose Allow to capture location...', 'info');
+ navigator.geolocation.getCurrentPosition(function (pos) {
+ var c = pos.coords || {};
+ setHidden(form, c.latitude, c.longitude, c.accuracy);
+ updateStatus('Location captured. Accuracy: ' + Math.round(c.accuracy || 0) + ' meters.', 'ok');
+ resolve(true);
+ }, function (err) {
+ setHidden(form, '', '', '');
+ var reason = 'Location permission denied or unavailable.';
+ if (err && err.code === 1) reason = 'Location permission denied. Allow location for this site in browser settings.';
+ if (err && err.code === 2) reason = 'Location unavailable. Enable device location service and try again.';
+ if (err && err.code === 3) reason = 'Location capture timed out. Try again with stable GPS/location service.';
+ updateStatus(reason + ' Attendance can be saved, but geofence verification cannot be performed.', 'warn');
+ resolve(false);
+ }, { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });
+ });
+ }
+
function bind() {
document.querySelectorAll('.employee-attendance-geo-form').forEach(function (form) {
if (form.dataset.geoBound === '1') return;
form.dataset.geoBound = '1';
- form.addEventListener('submit', function (event) {
+ form.addEventListener('submit', async function (event) {
if (form.dataset.geoSubmitted === '1') return;
event.preventDefault();
- if (!navigator.geolocation) {
- updateStatus('Browser geolocation is not available. Punch will continue without location.', 'warn');
- form.dataset.geoSubmitted = '1';
- form.submit();
- return;
- }
- updateStatus('Requesting browser location. Please click Allow...', 'info');
- navigator.geolocation.getCurrentPosition(function (pos) {
- var c = pos.coords || {};
- setHidden(form, c.latitude, c.longitude, c.accuracy);
- updateStatus('Location captured. Accuracy: ' + Math.round(c.accuracy || 0) + ' meters.', 'ok');
- form.dataset.geoSubmitted = '1';
- form.submit();
- }, function () {
- setHidden(form, '', '', '');
- updateStatus('Location denied/unavailable. Punch will continue and may need approval if branch geofence is enabled.', 'warn');
- form.dataset.geoSubmitted = '1';
- form.submit();
- }, {enableHighAccuracy: true, timeout: 12000, maximumAge: 0});
+
+ var proceed = await openLocationModal();
+ if (!proceed) return;
+
+ await captureLocation(form);
+ form.dataset.geoSubmitted = '1';
+ form.submit();
});
});
}
+
return {bind: bind};
})();
window.EmployeePortalGeo.bind();
diff --git a/app/modules/employees/templates/employees/self_attendance.html b/app/modules/employees/templates/employees/self_attendance.html
index 6eec7d4..9e11066 100644
--- a/app/modules/employees/templates/employees/self_attendance.html
+++ b/app/modules/employees/templates/employees/self_attendance.html
@@ -115,7 +115,7 @@
Click Continue, then choose Allow in the browser location popup.
- If you are outside the branch or location is denied/unavailable, your attendance can still be saved as pending approval for OD/client visit review.
+ If you are outside the branch or location is denied/unavailable, your attendance can still be saved. It will require approval only when branch geofence/IP verification is configured.
@@ -200,7 +200,7 @@
geoAttempted = true;
if (!navigator.geolocation) {
setHidden('', '', '');
- updateStatus('Browser geolocation is not available. Punch will be saved as pending approval if branch geofence is enabled.', 'warn');
+ updateStatus('Browser geolocation is not available. Attendance can be saved, but geofence verification cannot be performed if location is denied/unavailable.', 'warn');
resolve(false);
return;
}
@@ -219,7 +219,7 @@
if (err && err.code === 1) reason = 'Location permission denied. Please allow location for this site in browser settings.';
if (err && err.code === 2) reason = 'Location unavailable. Please enable device GPS/location service and try again.';
if (err && err.code === 3) reason = 'Location capture timed out. Please try again near a window or with GPS enabled.';
- updateStatus(reason + ' Punch will be saved as pending approval if branch geofence is enabled.', 'warn');
+ updateStatus(reason + ' Attendance can be saved, but geofence verification cannot be performed if location is denied/unavailable.', 'warn');
resolve(false);
}, { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });
});