Fix check-in page issue, display check-in information

This commit is contained in:
2025-09-16 20:58:59 -04:00
parent 7933fcc24f
commit 6603a1cd06
3 changed files with 219 additions and 142 deletions
+11 -4
View File
@@ -3736,8 +3736,9 @@ def qr_checkin(qr_url):
'employee_id': attendance.employee_id,
'location': attendance.location_name,
'location_event': qr_code.location_event,
'check_in_time': attendance.check_in_time.strftime('%H:%M:%S'),
'check_in_date': attendance.check_in_date.strftime('%m/%d/%Y'),
'event': qr_code.location_event, # Add both for compatibility
'check_in_time': attendance.check_in_time.strftime('%I:%M %p'), # 12-hour format
'check_in_date': attendance.check_in_date.strftime('%B %d, %Y'), # Full date format
'device_info': attendance.device_info,
'ip_address': attendance.ip_address,
'location_accuracy': location_accuracy,
@@ -3752,13 +3753,19 @@ def qr_checkin(qr_url):
if location_data['latitude'] and location_data['longitude']:
response_data['data']['coordinates'] = f"{location_data['latitude']:.10f}, {location_data['longitude']:.10f}"
# Enhanced logging for successful check-in with all details
print(f"✅ Check-in completed successfully")
print(f" Employee: {attendance.employee_id}")
print(f" Time: {attendance.check_in_time}")
print(f" Employee ID: {attendance.employee_id}")
print(f" Time: {attendance.check_in_time.strftime('%I:%M %p')}")
print(f" Date: {attendance.check_in_date.strftime('%B %d, %Y')}")
print(f" Location: {attendance.location_name}")
print(f" Action: {qr_code.location_event}")
print(f" Address: {attendance.address}")
print(f" Today's count: {today_checkin_count}")
# Log to database for audit trail
logger_handler.logger.info(f"Check-in success - Employee: {attendance.employee_id}, Location: {attendance.location_name}, Time: {attendance.check_in_time}, Action: {qr_code.location_event}")
return jsonify(response_data), 200
except Exception as e:
+102 -90
View File
@@ -142,10 +142,11 @@ function initializeForm() {
function disableFormImmediately() {
// Find and disable submit button immediately
const submitButton = document.getElementById("submitCheckin") ||
document.getElementById("submitButton") ||
document.querySelector('button[type="submit"]') ||
document.querySelector('.btn-primary');
const submitButton =
document.getElementById("submitCheckin") ||
document.getElementById("submitButton") ||
document.querySelector('button[type="submit"]') ||
document.querySelector(".btn-primary");
const employeeIdInput = document.getElementById("employee_id");
const form = document.getElementById("checkinForm");
@@ -155,11 +156,14 @@ function disableFormImmediately() {
submitButton.style.opacity = "0.5";
submitButton.style.cursor = "not-allowed";
submitButton.style.pointerEvents = "none";
submitButton.setAttribute('data-location-blocked', 'true');
submitButton.setAttribute("data-location-blocked", "true");
// Store original content
if (!submitButton.getAttribute('data-original-content')) {
submitButton.setAttribute('data-original-content', submitButton.innerHTML);
if (!submitButton.getAttribute("data-original-content")) {
submitButton.setAttribute(
"data-original-content",
submitButton.innerHTML
);
}
// Show loading/checking state
@@ -172,7 +176,7 @@ function disableFormImmediately() {
if (employeeIdInput) {
employeeIdInput.disabled = true;
employeeIdInput.style.opacity = "0.7";
employeeIdInput.setAttribute('data-location-blocked', 'true');
employeeIdInput.setAttribute("data-location-blocked", "true");
employeeIdInput.placeholder = "Checking location services...";
}
@@ -257,7 +261,7 @@ function proceedWithCheckin() {
function showLocationServicesBlockedMessage() {
const messages = {
en: "Check-in blocked: Location Services must be enabled to continue.",
es: "Registro bloqueado: Los Servicios de Ubicación deben estar habilitados para continuar."
es: "Registro bloqueado: Los Servicios de Ubicación deben estar habilitados para continuar.",
};
const currentLang = currentLanguage || "en";
@@ -349,6 +353,8 @@ function handleCheckinResponse(data) {
// ENHANCED SUCCESS HANDLING WITH MULTIPLE CHECK-IN INFO
function handleCheckinSuccess(data) {
console.log("✅ Success data received:", data);
const responseData = data.data || data || {};
const checkinCount = responseData.checkin_count_today || 1;
const checkinSequence = responseData.checkin_sequence || "Check-in";
@@ -379,15 +385,36 @@ function handleCheckinSuccess(data) {
}
};
const employeeId = responseData.employee_id || "Unknown";
// Get employee ID from form input if not in response data
const employeeIdInput = document.getElementById("employee_id");
const employeeId =
responseData.employee_id ||
(employeeIdInput
? employeeIdInput.value.trim().toUpperCase()
: "Unknown");
const location = responseData.location || "Unknown Location";
const event =
responseData.event || responseData.location_event || "Check-in";
const checkInTime =
responseData.check_in_time || new Date().toLocaleTimeString();
const checkInDate =
responseData.check_in_date || new Date().toLocaleDateString();
// Format current date and time if not provided in response
const now = new Date();
const checkInTime =
responseData.check_in_time ||
now.toLocaleTimeString("en-US", {
hour: "2-digit",
minute: "2-digit",
hour12: true,
});
const checkInDate =
responseData.check_in_date ||
now.toLocaleDateString("en-US", {
year: "numeric",
month: "short",
day: "numeric",
});
// Update success card elements
updateElement("successEmployeeId", employeeId);
updateElement("successLocation", location);
updateElement("successEvent", event);
@@ -416,36 +443,11 @@ function handleCheckinSuccess(data) {
`${responseData.location_accuracy} miles`
);
}
}
// NEW: Add option to check in again after success
//setTimeout(() => {
// addCheckInAgainOption();
//}, 3000);
}
// NEW: Add option to check in again
function addCheckInAgainOption() {
const successCard = document.getElementById("successCard");
if (successCard && !document.getElementById("checkInAgainButton")) {
const checkInAgainHtml = `
<div class="check-in-again-section" style="margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid #e0e4e7;">
<p class="check-in-again-text" style="margin-bottom: 1rem; color: #64748b; font-size: 0.9rem;">
<span data-en="Need to check in again? You can do so after 30 minutes."
data-es="¿Necesita registrarse nuevamente? Puede hacerlo después de 30 minutos.">
Need to check in again? You can do so after 30 minutes.
</span>
</p>
<button id="checkInAgainButton" class="btn btn-outline" style="width: 100%;" onclick="resetForNewCheckin()">
<i class="fas fa-redo"></i>
<span data-en="Check In Again" data-es="Registrarse Nuevamente">Check In Again</span>
</button>
</div>
`;
successCard.insertAdjacentHTML("beforeend", checkInAgainHtml);
// Apply current language translations
applyTranslations();
// Log successful check-in with details
console.log(
`✅ Check-in successful for Employee ID: ${employeeId}, Location: ${location}, Time: ${checkInTime}, Date: ${checkInDate}, Action: ${event}`
);
}
}
@@ -874,10 +876,11 @@ function checkLocationServicesStatus() {
function blockCheckInProcess(shouldBlock) {
// Try multiple possible submit button IDs from your codebase
const submitButton = document.getElementById("submitCheckin") ||
document.getElementById("submitButton") ||
document.querySelector('button[type="submit"]') ||
document.querySelector('.btn-primary');
const submitButton =
document.getElementById("submitCheckin") ||
document.getElementById("submitButton") ||
document.querySelector('button[type="submit"]') ||
document.querySelector(".btn-primary");
const employeeIdInput = document.getElementById("employee_id");
const form = document.getElementById("checkinForm");
@@ -894,11 +897,14 @@ function blockCheckInProcess(shouldBlock) {
submitButton.style.pointerEvents = "none";
// Add data attribute to track blocking state
submitButton.setAttribute('data-location-blocked', 'true');
submitButton.setAttribute("data-location-blocked", "true");
// Store original button content
if (!submitButton.getAttribute('data-original-content')) {
submitButton.setAttribute('data-original-content', submitButton.innerHTML);
if (!submitButton.getAttribute("data-original-content")) {
submitButton.setAttribute(
"data-original-content",
submitButton.innerHTML
);
}
// Update button text to show it's blocked
@@ -912,7 +918,7 @@ function blockCheckInProcess(shouldBlock) {
submitButton.parentNode.replaceChild(newButton, submitButton);
// Add blocking event listener
newButton.addEventListener('click', function(e) {
newButton.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
showLocationServicesBlockedMessage();
@@ -923,7 +929,7 @@ function blockCheckInProcess(shouldBlock) {
if (employeeIdInput) {
employeeIdInput.disabled = true;
employeeIdInput.style.opacity = "0.7";
employeeIdInput.setAttribute('data-location-blocked', 'true');
employeeIdInput.setAttribute("data-location-blocked", "true");
}
if (form) {
@@ -931,7 +937,7 @@ function blockCheckInProcess(shouldBlock) {
form.style.pointerEvents = "none";
// Override form submission completely
form.onsubmit = function(e) {
form.onsubmit = function (e) {
e.preventDefault();
e.stopPropagation();
showLocationServicesBlockedMessage();
@@ -952,16 +958,18 @@ function blockCheckInProcess(shouldBlock) {
submitButton.style.pointerEvents = "auto";
// Remove blocking data attribute
submitButton.removeAttribute('data-location-blocked');
submitButton.removeAttribute("data-location-blocked");
// Restore original button content
const originalContent = submitButton.getAttribute('data-original-content');
const originalContent = submitButton.getAttribute(
"data-original-content"
);
if (originalContent) {
submitButton.innerHTML = originalContent;
}
// Re-attach proper event listeners
submitButton.onclick = function(e) {
submitButton.onclick = function (e) {
e.preventDefault();
handleFormSubmit(e);
return false;
@@ -971,7 +979,7 @@ function blockCheckInProcess(shouldBlock) {
if (employeeIdInput) {
employeeIdInput.disabled = false;
employeeIdInput.style.opacity = "1";
employeeIdInput.removeAttribute('data-location-blocked');
employeeIdInput.removeAttribute("data-location-blocked");
}
if (form) {
@@ -979,7 +987,7 @@ function blockCheckInProcess(shouldBlock) {
form.style.pointerEvents = "auto";
// Restore proper form submission handler
form.onsubmit = function(e) {
form.onsubmit = function (e) {
e.preventDefault();
handleFormSubmit(e);
return false;
@@ -998,31 +1006,31 @@ function showLocationServicesWarning(errorType) {
hideLocationServicesWarning();
const warningMessages = {
en: {
not_supported:
"⚠️ Location Services Not Supported<br><strong>Check-in is currently blocked.</strong><br>Your browser does not support location services required for check-in.<br><br>Los servicios de ubicación no son compatibles. El registro está bloqueado.",
permission_denied:
"⚠️ Location Access Denied<br><strong>Check-in is currently blocked.</strong><br>Please enable location access in your browser settings to continue with check-in.<br><br>Acceso a ubicación denegado. Habilite el acceso para continuar.",
position_unavailable:
"⚠️ Location Services Disabled<br><strong>Check-in is currently blocked.</strong><br>Please turn on Location Services in your device settings and refresh the page.<br><br>Servicios de ubicación deshabilitados. Active los servicios y actualice la página.",
timeout:
"⚠️ Location Services Not Responding<br><strong>Check-in is currently blocked.</strong><br>Location services may be disabled. Please check your device settings.<br><br>Los servicios de ubicación no responden. Verifique la configuración.",
unknown_error:
"⚠️ Location Services Error<br><strong>Check-in is currently blocked.</strong><br>Unable to access location services. Please check your settings and try again.<br><br>Error de servicios de ubicación. Verifique la configuración.",
},
es: {
not_supported:
"⚠️ Servicios de Ubicación No Compatibles<br><strong>El registro está bloqueado.</strong><br>Su navegador no es compatible con los servicios de ubicación requeridos.",
permission_denied:
"⚠️ Acceso a Ubicación Denegado<br><strong>El registro está bloqueado.</strong><br>Habilite el acceso a la ubicación en la configuración de su navegador.",
position_unavailable:
"⚠️ Servicios de Ubicación Deshabilitados<br><strong>El registro está bloqueado.</strong><br>Active los Servicios de Ubicación en la configuración y actualice la página.",
timeout:
"⚠️ Servicios de Ubicación No Responden<br><strong>El registro está bloqueado.</strong><br>Los servicios pueden estar deshabilitados. Verifique la configuración.",
unknown_error:
"⚠️ Error de Servicios de Ubicación<br><strong>El registro está bloqueado.</strong><br>No se puede acceder a los servicios. Verifique la configuración.",
},
};
en: {
not_supported:
"⚠️ Location Services Not Supported<br><strong>Check-in is currently blocked.</strong><br>Your browser does not support location services required for check-in.<br><br>Los servicios de ubicación no son compatibles. El registro está bloqueado.",
permission_denied:
"⚠️ Location Access Denied<br><strong>Check-in is currently blocked.</strong><br>Please enable location access in your browser settings to continue with check-in.<br><br>Acceso a ubicación denegado. Habilite el acceso para continuar.",
position_unavailable:
"⚠️ Location Services Disabled<br><strong>Check-in is currently blocked.</strong><br>Please turn on Location Services in your device settings and refresh the page.<br><br>Servicios de ubicación deshabilitados. Active los servicios y actualice la página.",
timeout:
"⚠️ Location Services Not Responding<br><strong>Check-in is currently blocked.</strong><br>Location services may be disabled. Please check your device settings.<br><br>Los servicios de ubicación no responden. Verifique la configuración.",
unknown_error:
"⚠️ Location Services Error<br><strong>Check-in is currently blocked.</strong><br>Unable to access location services. Please check your settings and try again.<br><br>Error de servicios de ubicación. Verifique la configuración.",
},
es: {
not_supported:
"⚠️ Servicios de Ubicación No Compatibles<br><strong>El registro está bloqueado.</strong><br>Su navegador no es compatible con los servicios de ubicación requeridos.",
permission_denied:
"⚠️ Acceso a Ubicación Denegado<br><strong>El registro está bloqueado.</strong><br>Habilite el acceso a la ubicación en la configuración de su navegador.",
position_unavailable:
"⚠️ Servicios de Ubicación Deshabilitados<br><strong>El registro está bloqueado.</strong><br>Active los Servicios de Ubicación en la configuración y actualice la página.",
timeout:
"⚠️ Servicios de Ubicación No Responden<br><strong>El registro está bloqueado.</strong><br>Los servicios pueden estar deshabilitados. Verifique la configuración.",
unknown_error:
"⚠️ Error de Servicios de Ubicación<br><strong>El registro está bloqueado.</strong><br>No se puede acceder a los servicios. Verifique la configuración.",
},
};
const currentLang = currentLanguage || "en";
const message =
@@ -1084,15 +1092,18 @@ function initializeLocationServicesCheck() {
console.log("✅ Initial Location Services check passed");
})
.catch(() => {
console.log("❌ Initial Location Services check failed - Check-in blocked");
console.log(
"❌ Initial Location Services check failed - Check-in blocked"
);
});
}, 1000);
// Override form initialization to ensure our handlers are used
setTimeout(() => {
const form = document.getElementById("checkinForm");
const submitButton = document.getElementById("submitCheckin") ||
document.querySelector('button[type="submit"]');
const submitButton =
document.getElementById("submitCheckin") ||
document.querySelector('button[type="submit"]');
if (form) {
// Remove existing event listeners by cloning
@@ -1100,16 +1111,17 @@ function initializeLocationServicesCheck() {
form.parentNode.replaceChild(newForm, form);
// Add our controlled event listener
newForm.addEventListener('submit', handleFormSubmit);
newForm.addEventListener("submit", handleFormSubmit);
}
if (submitButton) {
// Find the new submit button after form cloning
const newSubmitButton = document.getElementById("submitCheckin") ||
document.querySelector('button[type="submit"]');
const newSubmitButton =
document.getElementById("submitCheckin") ||
document.querySelector('button[type="submit"]');
if (newSubmitButton) {
newSubmitButton.addEventListener('click', function(e) {
newSubmitButton.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
handleFormSubmit(e);
+67 -9
View File
@@ -829,7 +829,6 @@
</form>
</div>
<!-- Success Card -->
<div class="success-card" id="successCard">
<div class="success-icon">
<i class="fas fa-check"></i>
@@ -841,20 +840,79 @@
</h2>
<div class="bilingual-container">
<p>
<span class="english-text"
>Your submission has been recorded successfully.</span
>
<span class="english-text">Your submission has been recorded successfully.</span>
<span class="language-separator">/</span>
<span class="spanish-text"
>Su registro ha sido guardado exitosamente.</span
>
<span class="spanish-text">Su registro ha sido guardado exitosamente.</span>
</p>
</div>
<!-- Enhanced Success Details with Employee Information -->
<div class="success-details" id="successDetails">
<!-- Success details will be populated here -->
<div class="detail-row">
<span class="detail-label">
<span class="english-text">Employee ID</span>
<span class="language-separator">/</span>
<span class="spanish-text">ID del Empleado</span>
</span>
<span class="detail-value" id="successEmployeeId">-</span>
</div>
<div class="detail-row">
<span class="detail-label">
<span class="english-text">Date</span>
<span class="language-separator">/</span>
<span class="spanish-text">Fecha</span>
</span>
<span class="detail-value" id="successCheckInDate">-</span>
</div>
<div class="detail-row">
<span class="detail-label">
<span class="english-text">Time</span>
<span class="language-separator">/</span>
<span class="spanish-text">Hora</span>
</span>
<span class="detail-value" id="successCheckInTime">-</span>
</div>
<div class="detail-row">
<span class="detail-label">
<span class="english-text">Action</span>
<span class="language-separator">/</span>
<span class="spanish-text">Acción</span>
</span>
<span class="detail-value" id="successEvent">-</span>
</div>
<div class="detail-row">
<span class="detail-label">
<span class="english-text">Location</span>
<span class="language-separator">/</span>
<span class="spanish-text">Ubicación</span>
</span>
<span class="detail-value" id="successLocation">-</span>
</div>
<!-- Optional Additional Details (hidden by default) -->
<div class="detail-row" style="display: none;" id="successAddressRow">
<span class="detail-label">
<span class="english-text">Address</span>
<span class="language-separator">/</span>
<span class="spanish-text">Dirección</span>
</span>
<span class="detail-value" id="successAddress">-</span>
</div>
<div class="detail-row" style="display: none;" id="successAccuracyRow">
<span class="detail-label">
<span class="english-text">Accuracy</span>
<span class="language-separator">/</span>
<span class="spanish-text">Precisión</span>
</span>
<span class="detail-value" id="successLocationAccuracy">-</span>
</div>
</div>
</div>
</div>
<!-- Enhanced JavaScript with preserved functionality -->
<script src="{{ url_for('static', filename='js/qr_destination.js') }}"></script>