From 7e372308940e3dc5b949730037f895c6a24eec12 Mon Sep 17 00:00:00 2001 From: Edison Date: Mon, 3 Nov 2025 13:35:35 +0800 Subject: [PATCH] calculations --- backend/workerRoutes.js | 11 ++++++----- src/views/WorkerDashboard.vue | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/backend/workerRoutes.js b/backend/workerRoutes.js index 9eb3239..860603e 100644 --- a/backend/workerRoutes.js +++ b/backend/workerRoutes.js @@ -95,12 +95,13 @@ export default function(db) { router.use(authenticateJWT); // Definitive version with distance calculation and specific error messages +router.post('/clock', async (req, res) => { + try { + const { userId, eventType, qrCodeValue, latitude, longitude, device_epoch_ms } = req.body; -// Definitive version with distance calculation and specific error messages - router.post('/clock', async (req, res) => { - try { - const { userId, eventType, qrCodeValue, latitude, longitude } = req.body; - const currentTimestamp = new Date().toISOString().slice(0, 19).replace('T', ' '); + // Use the device's recorded instant if provided; fall back to server time. + const ts = Number.isFinite(+device_epoch_ms) ? new Date(Number(device_epoch_ms)) : new Date(); + const currentTimestamp = ts.toISOString().slice(0, 19).replace('T', ' '); // 1. Kill Switch Enforcement const clockingAllowed = await isClockingEnabled(db); diff --git a/src/views/WorkerDashboard.vue b/src/views/WorkerDashboard.vue index 029d8b5..a814715 100644 --- a/src/views/WorkerDashboard.vue +++ b/src/views/WorkerDashboard.vue @@ -186,13 +186,29 @@ const fetchCurrentStatus = async () => { } } +const getTimeContext = () => { + const tzName = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC' + const offsetMin = -new Date().getTimezoneOffset() // east of UTC => positive + return { device_epoch_ms: Date.now(), tz_name: tzName, offset_min: offsetMin } +} + const sendClockEvent = async (qrCodeValue, latitude, longitude) => { const eventType = isClockedIn.value ? 'clock_out' : 'clock_in' try { + const payload = { + userId, + eventType, + qrCodeValue, + latitude, + longitude, + ...getTimeContext() // new: device_epoch_ms, tz_name, offset_min + } + await apiFetch('/api/clock', { method: 'POST', - body: JSON.stringify({ userId, eventType, qrCodeValue, latitude, longitude }), + body: JSON.stringify(payload), }); + const newClockStatus = !isClockedIn.value isClockedIn.value = newClockStatus triggerOverlay(t(newClockStatus ? 'successClockIn' : 'successClockOut'), 'success');