Updated: get coordinates with 10 decimal
This commit is contained in:
@@ -90,7 +90,7 @@ class QRCode(db.Model):
|
|||||||
def coordinates_display(self):
|
def coordinates_display(self):
|
||||||
"""Get formatted coordinates for display"""
|
"""Get formatted coordinates for display"""
|
||||||
if self.has_coordinates:
|
if self.has_coordinates:
|
||||||
return f"{self.address_latitude:.8f}, {self.address_longitude:.8f}"
|
return f"{self.address_latitude:.10f}, {self.address_longitude:.10f}"
|
||||||
return "Coordinates not available"
|
return "Coordinates not available"
|
||||||
|
|
||||||
def update_coordinates(self, latitude, longitude, accuracy='geocoded'):
|
def update_coordinates(self, latitude, longitude, accuracy='geocoded'):
|
||||||
@@ -155,7 +155,7 @@ class AttendanceData(db.Model):
|
|||||||
def coordinates_display(self):
|
def coordinates_display(self):
|
||||||
"""Get formatted coordinates for display"""
|
"""Get formatted coordinates for display"""
|
||||||
if self.has_location_data:
|
if self.has_location_data:
|
||||||
return f"{self.latitude:.8f}, {self.longitude:.8f}"
|
return f"{self.latitude:.10f}, {self.longitude:.10f}"
|
||||||
return "No GPS data"
|
return "No GPS data"
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
@@ -268,7 +268,7 @@ def get_coordinates_from_address_enhanced(address):
|
|||||||
accuracy = 'poor'
|
accuracy = 'poor'
|
||||||
|
|
||||||
print(f"✅ Enhanced geocoding successful:")
|
print(f"✅ Enhanced geocoding successful:")
|
||||||
print(f" Coordinates: {lat:.8f}, {lng:.8f}")
|
print(f" Coordinates: {lat:.10f}, {lng:.10f}")
|
||||||
print(f" Accuracy: {accuracy}")
|
print(f" Accuracy: {accuracy}")
|
||||||
|
|
||||||
return lat, lng, accuracy
|
return lat, lng, accuracy
|
||||||
@@ -324,7 +324,7 @@ def geocode_address_enhanced(address):
|
|||||||
accuracy = 'low'
|
accuracy = 'low'
|
||||||
|
|
||||||
print(f"✅ Geocoded address: {address}")
|
print(f"✅ Geocoded address: {address}")
|
||||||
print(f" Coordinates: {lat:.8f}, {lng:.8f}")
|
print(f" Coordinates: {lat:.10f}, {lng:.10f}")
|
||||||
print(f" Accuracy: {accuracy} ({place_type})")
|
print(f" Accuracy: {accuracy} ({place_type})")
|
||||||
|
|
||||||
return lat, lng, accuracy
|
return lat, lng, accuracy
|
||||||
@@ -376,8 +376,8 @@ def calculate_distance_miles(lat1, lng1, lat2, lng2):
|
|||||||
distance = round(distance, 4)
|
distance = round(distance, 4)
|
||||||
|
|
||||||
print(f"📏 Enhanced distance calculation:")
|
print(f"📏 Enhanced distance calculation:")
|
||||||
print(f" Point 1: {lat1*180/3.14159:.8f}, {lng1*180/3.14159:.8f}")
|
print(f" Point 1: {lat1*180/3.14159:.10f}, {lng1*180/3.14159:.10f}")
|
||||||
print(f" Point 2: {lat2*180/3.14159:.8f}, {lng2*180/3.14159:.8f}")
|
print(f" Point 2: {lat2*180/3.14159:.10f}, {lng2*180/3.14159:.10f}")
|
||||||
print(f" Distance: {distance:.4f} miles")
|
print(f" Distance: {distance:.4f} miles")
|
||||||
|
|
||||||
return distance
|
return distance
|
||||||
@@ -455,7 +455,7 @@ def calculate_location_accuracy_enhanced(qr_address, checkin_address, checkin_la
|
|||||||
print(f"❌ Could not geocode QR address: {qr_address}")
|
print(f"❌ Could not geocode QR address: {qr_address}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
print(f"✅ QR location coordinates: {qr_lat:.8f}, {qr_lng:.8f} (accuracy: {qr_accuracy})")
|
print(f"✅ QR location coordinates: {qr_lat:.10f}, {qr_lng:.10f} (accuracy: {qr_accuracy})")
|
||||||
|
|
||||||
# Step 2: Determine check-in coordinates
|
# Step 2: Determine check-in coordinates
|
||||||
print(f"\n📱 Step 2: Determining check-in coordinates...")
|
print(f"\n📱 Step 2: Determining check-in coordinates...")
|
||||||
@@ -475,7 +475,7 @@ def calculate_location_accuracy_enhanced(qr_address, checkin_address, checkin_la
|
|||||||
checkin_coords_lat = lat_val
|
checkin_coords_lat = lat_val
|
||||||
checkin_coords_lng = lng_val
|
checkin_coords_lng = lng_val
|
||||||
checkin_source = "gps"
|
checkin_source = "gps"
|
||||||
print(f"✅ Using GPS coordinates: {lat_val:.8f}, {lng_val:.8f}")
|
print(f"✅ Using GPS coordinates: {lat_val:.10f}, {lng_val:.10f}")
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ Invalid GPS coordinates: {lat_val}, {lng_val}")
|
print(f"⚠️ Invalid GPS coordinates: {lat_val}, {lng_val}")
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
@@ -487,7 +487,7 @@ def calculate_location_accuracy_enhanced(qr_address, checkin_address, checkin_la
|
|||||||
checkin_coords_lat, checkin_coords_lng, checkin_accuracy = get_coordinates_from_address_enhanced(checkin_address)
|
checkin_coords_lat, checkin_coords_lng, checkin_accuracy = get_coordinates_from_address_enhanced(checkin_address)
|
||||||
if checkin_coords_lat is not None:
|
if checkin_coords_lat is not None:
|
||||||
checkin_source = "address"
|
checkin_source = "address"
|
||||||
print(f"✅ Using geocoded coordinates: {checkin_coords_lat:.8f}, {checkin_coords_lng:.8f} (accuracy: {checkin_accuracy})")
|
print(f"✅ Using geocoded coordinates: {checkin_coords_lat:.10f}, {checkin_coords_lng:.10f} (accuracy: {checkin_accuracy})")
|
||||||
|
|
||||||
# Check if we have valid coordinates for both locations
|
# Check if we have valid coordinates for both locations
|
||||||
if checkin_coords_lat is None or checkin_coords_lng is None:
|
if checkin_coords_lat is None or checkin_coords_lng is None:
|
||||||
@@ -502,8 +502,8 @@ def calculate_location_accuracy_enhanced(qr_address, checkin_address, checkin_la
|
|||||||
|
|
||||||
if distance is not None:
|
if distance is not None:
|
||||||
print(f"✅ Enhanced location accuracy calculated successfully!")
|
print(f"✅ Enhanced location accuracy calculated successfully!")
|
||||||
print(f" QR Location: {qr_lat:.8f}, {qr_lng:.8f}")
|
print(f" QR Location: {qr_lat:.10f}, {qr_lng:.10f}")
|
||||||
print(f" Check-in Location: {checkin_coords_lat:.8f}, {checkin_coords_lng:.8f}")
|
print(f" Check-in Location: {checkin_coords_lat:.10f}, {checkin_coords_lng:.10f}")
|
||||||
print(f" Source: {checkin_source}")
|
print(f" Source: {checkin_source}")
|
||||||
print(f" Distance: {distance:.4f} miles")
|
print(f" Distance: {distance:.4f} miles")
|
||||||
print(f" Accuracy Level: {get_location_accuracy_level_enhanced(distance)}")
|
print(f" Accuracy Level: {get_location_accuracy_level_enhanced(distance)}")
|
||||||
@@ -1387,7 +1387,7 @@ def geocode_address():
|
|||||||
'latitude': lat,
|
'latitude': lat,
|
||||||
'longitude': lng,
|
'longitude': lng,
|
||||||
'accuracy': accuracy,
|
'accuracy': accuracy,
|
||||||
'coordinates_display': f"{lat:.8f}, {lng:.8f}"
|
'coordinates_display': f"{lat:.10f}, {lng:.10f}"
|
||||||
},
|
},
|
||||||
'message': f'Address geocoded successfully with {accuracy} accuracy'
|
'message': f'Address geocoded successfully with {accuracy} accuracy'
|
||||||
})
|
})
|
||||||
@@ -1745,7 +1745,7 @@ def create_qr_code():
|
|||||||
new_qr_code.address_longitude = lng
|
new_qr_code.address_longitude = lng
|
||||||
new_qr_code.coordinate_accuracy = coordinate_accuracy
|
new_qr_code.coordinate_accuracy = coordinate_accuracy
|
||||||
new_qr_code.coordinates_updated_date = datetime.utcnow()
|
new_qr_code.coordinates_updated_date = datetime.utcnow()
|
||||||
print(f"✅ Added coordinates to QR code: {lat:.8f}, {lng:.8f}")
|
print(f"✅ Added coordinates to QR code: {lat:.10f}, {lng:.10f}")
|
||||||
except (ValueError, TypeError) as e:
|
except (ValueError, TypeError) as e:
|
||||||
print(f"⚠️ Invalid coordinates provided: {e}")
|
print(f"⚠️ Invalid coordinates provided: {e}")
|
||||||
|
|
||||||
@@ -1810,7 +1810,7 @@ def edit_qr_code(qr_id):
|
|||||||
qr_code.address_longitude = lng
|
qr_code.address_longitude = lng
|
||||||
qr_code.coordinate_accuracy = coordinate_accuracy
|
qr_code.coordinate_accuracy = coordinate_accuracy
|
||||||
qr_code.coordinates_updated_date = datetime.utcnow()
|
qr_code.coordinates_updated_date = datetime.utcnow()
|
||||||
print(f"✅ Updated coordinates for QR code: {lat:.8f}, {lng:.8f}")
|
print(f"✅ Updated coordinates for QR code: {lat:.10f}, {lng:.10f}")
|
||||||
except (ValueError, TypeError) as e:
|
except (ValueError, TypeError) as e:
|
||||||
print(f"⚠️ Invalid coordinates provided during edit: {e}")
|
print(f"⚠️ Invalid coordinates provided during edit: {e}")
|
||||||
|
|
||||||
@@ -2347,7 +2347,7 @@ def attendance_report():
|
|||||||
'gps_accuracy': gps_accuracy,
|
'gps_accuracy': gps_accuracy,
|
||||||
'accuracy_level': get_location_accuracy_level(location_accuracy) if location_accuracy else 'unknown',
|
'accuracy_level': get_location_accuracy_level(location_accuracy) if location_accuracy else 'unknown',
|
||||||
'has_location_data': record.latitude is not None and record.longitude is not None,
|
'has_location_data': record.latitude is not None and record.longitude is not None,
|
||||||
'coordinates': f"{record.latitude:.8f}, {record.longitude:.8f}" if record.latitude and record.longitude else "No GPS data",
|
'coordinates': f"{record.latitude:.10f}, {record.longitude:.10f}" if record.latitude and record.longitude else "No GPS data",
|
||||||
'has_location_accuracy_feature': has_location_accuracy
|
'has_location_accuracy_feature': has_location_accuracy
|
||||||
}
|
}
|
||||||
processed_records.append(record_dict)
|
processed_records.append(record_dict)
|
||||||
|
|||||||
+153
-129
@@ -21,58 +21,58 @@ let locationRequestActive = false;
|
|||||||
let locationWatchId = null;
|
let locationWatchId = null;
|
||||||
|
|
||||||
// BILINGUAL FUNCTIONALITY (PRESERVED FROM ORIGINAL)
|
// BILINGUAL FUNCTIONALITY (PRESERVED FROM ORIGINAL)
|
||||||
let currentLanguage = 'en';
|
let currentLanguage = "en";
|
||||||
const translations = {
|
const translations = {
|
||||||
en: {
|
en: {
|
||||||
languageText: 'EN',
|
languageText: "EN",
|
||||||
statusMessages: {
|
statusMessages: {
|
||||||
processing: 'Processing check-in...',
|
processing: "Processing check-in...",
|
||||||
success: 'Check-in successful!',
|
success: "Check-in successful!",
|
||||||
error: 'Check-in failed. Please try again.',
|
error: "Check-in failed. Please try again.",
|
||||||
duplicate: 'You have already checked in today.',
|
duplicate: "You have already checked in today.",
|
||||||
tooSoon: 'Please wait before checking in again.',
|
tooSoon: "Please wait before checking in again.",
|
||||||
multipleSuccess: 'Submitted successfully!',
|
multipleSuccess: "Submitted successfully!",
|
||||||
invalidId: 'Please enter a valid Employee ID.',
|
invalidId: "Please enter a valid Employee ID.",
|
||||||
locationError: 'Unable to get location data.',
|
locationError: "Unable to get location data.",
|
||||||
networkError: 'Network error. Please check your connection.'
|
networkError: "Network error. Please check your connection.",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
es: {
|
es: {
|
||||||
languageText: 'ES',
|
languageText: "ES",
|
||||||
statusMessages: {
|
statusMessages: {
|
||||||
processing: 'Procesando registro...',
|
processing: "Procesando registro...",
|
||||||
success: '¡Registro exitoso!',
|
success: "¡Registro exitoso!",
|
||||||
error: 'Error en el registro. Por favor intente de nuevo.',
|
error: "Error en el registro. Por favor intente de nuevo.",
|
||||||
duplicate: 'Ya se ha registrado hoy.',
|
duplicate: "Ya se ha registrado hoy.",
|
||||||
tooSoon: 'Por favor espere antes de registrarse nuevamente.',
|
tooSoon: "Por favor espere antes de registrarse nuevamente.",
|
||||||
multipleSuccess: 'Submitted successful!!',
|
multipleSuccess: "Submitted successful!!",
|
||||||
invalidId: 'Por favor ingrese un ID de empleado válido.',
|
invalidId: "Por favor ingrese un ID de empleado válido.",
|
||||||
locationError: 'No se pudo obtener datos de ubicación.',
|
locationError: "No se pudo obtener datos de ubicación.",
|
||||||
networkError: 'Error de red. Verifique su conexión.'
|
networkError: "Error de red. Verifique su conexión.",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// DOM Content Loaded Event (PRESERVED FROM ORIGINAL)
|
// DOM Content Loaded Event (PRESERVED FROM ORIGINAL)
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
console.log("🎯 QR Destination page loaded");
|
console.log("🎯 QR Destination page loaded");
|
||||||
|
|
||||||
// Initialize language functionality
|
// Initialize language functionality
|
||||||
initializeLanguage();
|
initializeLanguage();
|
||||||
|
|
||||||
// Initialize form handling
|
// Initialize form handling
|
||||||
initializeForm();
|
initializeForm();
|
||||||
|
|
||||||
// Initialize location services
|
// Initialize location services
|
||||||
initializeLocation();
|
initializeLocation();
|
||||||
|
|
||||||
// Start real-time clock
|
// Start real-time clock
|
||||||
startClock();
|
startClock();
|
||||||
|
|
||||||
// Add fade-in animation to elements
|
// Add fade-in animation to elements
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.querySelectorAll('.fade-transition').forEach(el => {
|
document.querySelectorAll(".fade-transition").forEach((el) => {
|
||||||
el.classList.add('active');
|
el.classList.add("active");
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
@@ -81,16 +81,16 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||||||
function initializeForm() {
|
function initializeForm() {
|
||||||
const form = document.getElementById("checkinForm");
|
const form = document.getElementById("checkinForm");
|
||||||
const submitButton = document.getElementById("submitCheckin");
|
const submitButton = document.getElementById("submitCheckin");
|
||||||
|
|
||||||
if (form && submitButton) {
|
if (form && submitButton) {
|
||||||
form.addEventListener("submit", handleFormSubmit);
|
form.addEventListener("submit", handleFormSubmit);
|
||||||
|
|
||||||
// Add real-time Employee ID validation
|
// Add real-time Employee ID validation
|
||||||
const employeeIdInput = document.getElementById("employee_id");
|
const employeeIdInput = document.getElementById("employee_id");
|
||||||
if (employeeIdInput) {
|
if (employeeIdInput) {
|
||||||
employeeIdInput.addEventListener("input", validateEmployeeId);
|
employeeIdInput.addEventListener("input", validateEmployeeId);
|
||||||
employeeIdInput.addEventListener("keypress", function(e) {
|
employeeIdInput.addEventListener("keypress", function (e) {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleFormSubmit(e);
|
handleFormSubmit(e);
|
||||||
}
|
}
|
||||||
@@ -101,29 +101,31 @@ function initializeForm() {
|
|||||||
|
|
||||||
function handleFormSubmit(event) {
|
function handleFormSubmit(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (isSubmitting) {
|
if (isSubmitting) {
|
||||||
console.log("⏳ Check-in already in progress, ignoring duplicate submission");
|
console.log(
|
||||||
|
"⏳ Check-in already in progress, ignoring duplicate submission"
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("🎯 Form submission triggered");
|
console.log("🎯 Form submission triggered");
|
||||||
|
|
||||||
const employeeId = document.getElementById("employee_id")?.value?.trim();
|
const employeeId = document.getElementById("employee_id")?.value?.trim();
|
||||||
|
|
||||||
if (!employeeId) {
|
if (!employeeId) {
|
||||||
showLocalizedStatusMessage('invalidId', 'error');
|
showLocalizedStatusMessage("invalidId", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (employeeId.length < 2) {
|
if (employeeId.length < 2) {
|
||||||
showLocalizedStatusMessage('invalidId', 'error');
|
showLocalizedStatusMessage("invalidId", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show processing status
|
// Show processing status
|
||||||
showLocalizedStatusMessage('processing', 'info');
|
showLocalizedStatusMessage("processing", "info");
|
||||||
|
|
||||||
// Submit the check-in
|
// Submit the check-in
|
||||||
submitCheckin();
|
submitCheckin();
|
||||||
}
|
}
|
||||||
@@ -131,32 +133,38 @@ function handleFormSubmit(event) {
|
|||||||
// ENHANCED CHECK-IN SUBMISSION WITH MULTIPLE CHECK-IN SUPPORT
|
// ENHANCED CHECK-IN SUBMISSION WITH MULTIPLE CHECK-IN SUPPORT
|
||||||
function submitCheckin() {
|
function submitCheckin() {
|
||||||
console.log("🚀 Starting check-in submission process");
|
console.log("🚀 Starting check-in submission process");
|
||||||
|
|
||||||
if (isSubmitting) {
|
if (isSubmitting) {
|
||||||
console.log("⏳ Already submitting, aborting");
|
console.log("⏳ Already submitting, aborting");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSubmitting = true;
|
isSubmitting = true;
|
||||||
updateSubmitButton(true);
|
updateSubmitButton(true);
|
||||||
|
|
||||||
const employeeId = document.getElementById("employee_id").value.trim();
|
const employeeId = document.getElementById("employee_id").value.trim();
|
||||||
|
|
||||||
if (!employeeId) {
|
if (!employeeId) {
|
||||||
showLocalizedStatusMessage('invalidId', 'error');
|
showLocalizedStatusMessage("invalidId", "error");
|
||||||
isSubmitting = false;
|
isSubmitting = false;
|
||||||
updateSubmitButton(false);
|
updateSubmitButton(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`👤 Employee ID: ${employeeId}`);
|
console.log(`👤 Employee ID: ${employeeId}`);
|
||||||
console.log(`📍 User location:`, userLocation);
|
console.log(`📍 User location:`, userLocation);
|
||||||
|
|
||||||
// Prepare form data
|
// Prepare form data
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("employee_id", employeeId);
|
formData.append("employee_id", employeeId);
|
||||||
formData.append("latitude", userLocation.latitude ? userLocation.latitude.toFixed(8) : "");
|
formData.append(
|
||||||
formData.append("longitude", userLocation.longitude ? userLocation.longitude.toFixed(8) : "");
|
"latitude",
|
||||||
|
userLocation.latitude ? userLocation.latitude.toFixed(10) : ""
|
||||||
|
);
|
||||||
|
formData.append(
|
||||||
|
"longitude",
|
||||||
|
userLocation.longitude ? userLocation.longitude.toFixed(10) : ""
|
||||||
|
);
|
||||||
formData.append("accuracy", userLocation.accuracy || "");
|
formData.append("accuracy", userLocation.accuracy || "");
|
||||||
formData.append("altitude", userLocation.altitude || "");
|
formData.append("altitude", userLocation.altitude || "");
|
||||||
formData.append("location_source", userLocation.source || "manual");
|
formData.append("location_source", userLocation.source || "manual");
|
||||||
@@ -197,17 +205,20 @@ function handleCheckinResponse(data) {
|
|||||||
if (data.success) {
|
if (data.success) {
|
||||||
handleCheckinSuccess(data);
|
handleCheckinSuccess(data);
|
||||||
} else {
|
} else {
|
||||||
const errorMsg = data.message || 'Submission failed';
|
const errorMsg = data.message || "Submission failed";
|
||||||
console.log("❌ Submission failed:", errorMsg);
|
console.log("❌ Submission failed:", errorMsg);
|
||||||
|
|
||||||
// NEW: Handle different types of check-in failures
|
// NEW: Handle different types of check-in failures
|
||||||
if (errorMsg.toLowerCase().includes('already submitted')) {
|
if (errorMsg.toLowerCase().includes("already submitted")) {
|
||||||
showLocalizedStatusMessage('duplicate', 'warning');
|
showLocalizedStatusMessage("duplicate", "warning");
|
||||||
} else if (errorMsg.toLowerCase().includes('submit again in') || errorMsg.toLowerCase().includes('minutes')) {
|
} else if (
|
||||||
|
errorMsg.toLowerCase().includes("submit again in") ||
|
||||||
|
errorMsg.toLowerCase().includes("minutes")
|
||||||
|
) {
|
||||||
// Handle 30-minute interval message
|
// Handle 30-minute interval message
|
||||||
showCustomStatusMessage(errorMsg, 'warning');
|
showCustomStatusMessage(errorMsg, "warning");
|
||||||
} else {
|
} else {
|
||||||
showLocalizedStatusMessage('error', 'error');
|
showLocalizedStatusMessage("error", "error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,18 +226,18 @@ function handleCheckinResponse(data) {
|
|||||||
// ENHANCED SUCCESS HANDLING WITH MULTIPLE CHECK-IN INFO
|
// ENHANCED SUCCESS HANDLING WITH MULTIPLE CHECK-IN INFO
|
||||||
function handleCheckinSuccess(data) {
|
function handleCheckinSuccess(data) {
|
||||||
console.log("✅ Submitted successful!");
|
console.log("✅ Submitted successful!");
|
||||||
|
|
||||||
const responseData = data.data || data || {};
|
const responseData = data.data || data || {};
|
||||||
const checkinCount = responseData.checkin_count_today || 1;
|
const checkinCount = responseData.checkin_count_today || 1;
|
||||||
const checkinSequence = responseData.checkin_sequence || 'Check-in';
|
const checkinSequence = responseData.checkin_sequence || "Check-in";
|
||||||
|
|
||||||
// Show appropriate success message based on check-in count
|
// Show appropriate success message based on check-in count
|
||||||
if (checkinCount > 1) {
|
if (checkinCount > 1) {
|
||||||
showLocalizedStatusMessage('multipleSuccess', 'success');
|
showLocalizedStatusMessage("multipleSuccess", "success");
|
||||||
} else {
|
} else {
|
||||||
showLocalizedStatusMessage('success', 'success');
|
showLocalizedStatusMessage("success", "success");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide form (PRESERVED FROM ORIGINAL)
|
// Hide form (PRESERVED FROM ORIGINAL)
|
||||||
const form = document.getElementById("checkinForm");
|
const form = document.getElementById("checkinForm");
|
||||||
if (form) {
|
if (form) {
|
||||||
@@ -237,7 +248,7 @@ function handleCheckinSuccess(data) {
|
|||||||
const successCard = document.getElementById("successCard");
|
const successCard = document.getElementById("successCard");
|
||||||
if (successCard) {
|
if (successCard) {
|
||||||
successCard.style.display = "block";
|
successCard.style.display = "block";
|
||||||
successCard.classList.add('active');
|
successCard.classList.add("active");
|
||||||
|
|
||||||
const updateElement = (id, value) => {
|
const updateElement = (id, value) => {
|
||||||
const el = document.getElementById(id);
|
const el = document.getElementById(id);
|
||||||
@@ -248,34 +259,40 @@ function handleCheckinSuccess(data) {
|
|||||||
|
|
||||||
const employeeId = responseData.employee_id || "Unknown";
|
const employeeId = responseData.employee_id || "Unknown";
|
||||||
const location = responseData.location || "Unknown Location";
|
const location = responseData.location || "Unknown Location";
|
||||||
const event = responseData.event || responseData.location_event || "Check-in";
|
const event =
|
||||||
const checkInTime = responseData.check_in_time || new Date().toLocaleTimeString();
|
responseData.event || responseData.location_event || "Check-in";
|
||||||
const checkInDate = responseData.check_in_date || new Date().toLocaleDateString();
|
const checkInTime =
|
||||||
|
responseData.check_in_time || new Date().toLocaleTimeString();
|
||||||
|
const checkInDate =
|
||||||
|
responseData.check_in_date || new Date().toLocaleDateString();
|
||||||
|
|
||||||
updateElement("successEmployeeId", employeeId);
|
updateElement("successEmployeeId", employeeId);
|
||||||
updateElement("successLocation", location);
|
updateElement("successLocation", location);
|
||||||
updateElement("successEvent", event);
|
updateElement("successEvent", event);
|
||||||
updateElement("successCheckInTime", checkInTime);
|
updateElement("successCheckInTime", checkInTime);
|
||||||
updateElement("successCheckInDate", checkInDate);
|
updateElement("successCheckInDate", checkInDate);
|
||||||
|
|
||||||
// NEW: Add check-in sequence information
|
// NEW: Add check-in sequence information
|
||||||
updateElement("successCheckinSequence", checkinSequence);
|
updateElement("successCheckinSequence", checkinSequence);
|
||||||
|
|
||||||
// Update additional info if available
|
// Update additional info if available
|
||||||
if (responseData.device_info) {
|
if (responseData.device_info) {
|
||||||
updateElement("successDeviceInfo", responseData.device_info);
|
updateElement("successDeviceInfo", responseData.device_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseData.coordinates) {
|
if (responseData.coordinates) {
|
||||||
updateElement("successCoordinates", responseData.coordinates);
|
updateElement("successCoordinates", responseData.coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseData.address) {
|
if (responseData.address) {
|
||||||
updateElement("successAddress", responseData.address);
|
updateElement("successAddress", responseData.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseData.location_accuracy) {
|
if (responseData.location_accuracy) {
|
||||||
updateElement("successLocationAccuracy", `${responseData.location_accuracy} miles`);
|
updateElement(
|
||||||
|
"successLocationAccuracy",
|
||||||
|
`${responseData.location_accuracy} miles`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,8 +320,8 @@ function addCheckInAgainOption() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
successCard.insertAdjacentHTML('beforeend', checkInAgainHtml);
|
successCard.insertAdjacentHTML("beforeend", checkInAgainHtml);
|
||||||
|
|
||||||
// Apply current language translations
|
// Apply current language translations
|
||||||
applyTranslations();
|
applyTranslations();
|
||||||
}
|
}
|
||||||
@@ -313,30 +330,30 @@ function addCheckInAgainOption() {
|
|||||||
// NEW: Reset form for new check-in
|
// NEW: Reset form for new check-in
|
||||||
function resetForNewCheckin() {
|
function resetForNewCheckin() {
|
||||||
console.log("🔄 Resetting for new check-in");
|
console.log("🔄 Resetting for new check-in");
|
||||||
|
|
||||||
// Show form again
|
// Show form again
|
||||||
const form = document.getElementById("checkinForm");
|
const form = document.getElementById("checkinForm");
|
||||||
if (form) {
|
if (form) {
|
||||||
form.style.display = "block";
|
form.style.display = "block";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide success card
|
// Hide success card
|
||||||
const successCard = document.getElementById("successCard");
|
const successCard = document.getElementById("successCard");
|
||||||
if (successCard) {
|
if (successCard) {
|
||||||
successCard.style.display = "none";
|
successCard.style.display = "none";
|
||||||
successCard.classList.remove('active');
|
successCard.classList.remove("active");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear previous employee ID
|
// Clear previous employee ID
|
||||||
const employeeIdInput = document.getElementById("employee_id");
|
const employeeIdInput = document.getElementById("employee_id");
|
||||||
if (employeeIdInput) {
|
if (employeeIdInput) {
|
||||||
employeeIdInput.value = '';
|
employeeIdInput.value = "";
|
||||||
employeeIdInput.focus();
|
employeeIdInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear status messages
|
// Clear status messages
|
||||||
clearStatusMessages();
|
clearStatusMessages();
|
||||||
|
|
||||||
// Reset location if needed
|
// Reset location if needed
|
||||||
if (!userLocation.latitude || !userLocation.longitude) {
|
if (!userLocation.latitude || !userLocation.longitude) {
|
||||||
requestLocationData();
|
requestLocationData();
|
||||||
@@ -344,7 +361,7 @@ function resetForNewCheckin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NEW: Show custom status message (for interval warnings)
|
// NEW: Show custom status message (for interval warnings)
|
||||||
function showCustomStatusMessage(message, type = 'info') {
|
function showCustomStatusMessage(message, type = "info") {
|
||||||
const statusContainer = document.getElementById("statusMessage");
|
const statusContainer = document.getElementById("statusMessage");
|
||||||
if (statusContainer) {
|
if (statusContainer) {
|
||||||
statusContainer.className = `status-message ${type}`;
|
statusContainer.className = `status-message ${type}`;
|
||||||
@@ -355,7 +372,7 @@ function showCustomStatusMessage(message, type = 'info') {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
statusContainer.style.display = "block";
|
statusContainer.style.display = "block";
|
||||||
|
|
||||||
// Auto-hide after 5 seconds
|
// Auto-hide after 5 seconds
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
statusContainer.style.display = "none";
|
statusContainer.style.display = "none";
|
||||||
@@ -366,20 +383,25 @@ function showCustomStatusMessage(message, type = 'info') {
|
|||||||
// Helper function to get appropriate icon for status type
|
// Helper function to get appropriate icon for status type
|
||||||
function getStatusIcon(type) {
|
function getStatusIcon(type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'success': return 'fa-check-circle';
|
case "success":
|
||||||
case 'error': return 'fa-exclamation-circle';
|
return "fa-check-circle";
|
||||||
case 'warning': return 'fa-clock';
|
case "error":
|
||||||
case 'info':
|
return "fa-exclamation-circle";
|
||||||
default: return 'fa-info-circle';
|
case "warning":
|
||||||
|
return "fa-clock";
|
||||||
|
case "info":
|
||||||
|
default:
|
||||||
|
return "fa-info-circle";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRESERVED: All other existing functions remain unchanged
|
// PRESERVED: All other existing functions remain unchanged
|
||||||
function showLocalizedStatusMessage(messageKey, type = 'info') {
|
function showLocalizedStatusMessage(messageKey, type = "info") {
|
||||||
const message = translations[currentLanguage].statusMessages[messageKey] ||
|
const message =
|
||||||
translations['en'].statusMessages[messageKey] ||
|
translations[currentLanguage].statusMessages[messageKey] ||
|
||||||
'Status update';
|
translations["en"].statusMessages[messageKey] ||
|
||||||
|
"Status update";
|
||||||
|
|
||||||
showCustomStatusMessage(message, type);
|
showCustomStatusMessage(message, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +414,7 @@ function clearStatusMessages() {
|
|||||||
|
|
||||||
function handleCheckinError(error) {
|
function handleCheckinError(error) {
|
||||||
console.error("❌ Check-in submission error:", error);
|
console.error("❌ Check-in submission error:", error);
|
||||||
showLocalizedStatusMessage('networkError', 'error');
|
showLocalizedStatusMessage("networkError", "error");
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSubmitButton(isLoading) {
|
function updateSubmitButton(isLoading) {
|
||||||
@@ -400,10 +422,12 @@ function updateSubmitButton(isLoading) {
|
|||||||
if (submitButton) {
|
if (submitButton) {
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
submitButton.disabled = true;
|
submitButton.disabled = true;
|
||||||
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> <span data-en="Processing..." data-es="Procesando...">Processing...</span>';
|
submitButton.innerHTML =
|
||||||
|
'<i class="fas fa-spinner fa-spin"></i> <span data-en="Processing..." data-es="Procesando...">Processing...</span>';
|
||||||
} else {
|
} else {
|
||||||
submitButton.disabled = false;
|
submitButton.disabled = false;
|
||||||
submitButton.innerHTML = '<i class="fas fa-user-check"></i> <span data-en="Submit" data-es="Someter">Submit</span>';
|
submitButton.innerHTML =
|
||||||
|
'<i class="fas fa-user-check"></i> <span data-en="Submit" data-es="Someter">Submit</span>';
|
||||||
}
|
}
|
||||||
applyTranslations();
|
applyTranslations();
|
||||||
}
|
}
|
||||||
@@ -412,18 +436,18 @@ function updateSubmitButton(isLoading) {
|
|||||||
function validateEmployeeId() {
|
function validateEmployeeId() {
|
||||||
const employeeIdInput = document.getElementById("employee_id");
|
const employeeIdInput = document.getElementById("employee_id");
|
||||||
const submitButton = document.getElementById("submitCheckin");
|
const submitButton = document.getElementById("submitCheckin");
|
||||||
|
|
||||||
if (employeeIdInput && submitButton) {
|
if (employeeIdInput && submitButton) {
|
||||||
const isValid = employeeIdInput.value.trim().length >= 2;
|
const isValid = employeeIdInput.value.trim().length >= 2;
|
||||||
submitButton.disabled = !isValid || isSubmitting;
|
submitButton.disabled = !isValid || isSubmitting;
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
employeeIdInput.classList.remove('invalid');
|
employeeIdInput.classList.remove("invalid");
|
||||||
employeeIdInput.classList.add('valid');
|
employeeIdInput.classList.add("valid");
|
||||||
} else {
|
} else {
|
||||||
employeeIdInput.classList.remove('valid');
|
employeeIdInput.classList.remove("valid");
|
||||||
if (employeeIdInput.value.length > 0) {
|
if (employeeIdInput.value.length > 0) {
|
||||||
employeeIdInput.classList.add('invalid');
|
employeeIdInput.classList.add("invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,22 +464,22 @@ function requestLocationData() {
|
|||||||
console.log("📍 Location request already active, skipping");
|
console.log("📍 Location request already active, skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!navigator.geolocation) {
|
if (!navigator.geolocation) {
|
||||||
console.log("❌ Geolocation not supported");
|
console.log("❌ Geolocation not supported");
|
||||||
userLocation.source = "manual";
|
userLocation.source = "manual";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
locationRequestActive = true;
|
locationRequestActive = true;
|
||||||
console.log("📍 Requesting location data...");
|
console.log("📍 Requesting location data...");
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
enableHighAccuracy: true,
|
enableHighAccuracy: true,
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
maximumAge: 300000
|
maximumAge: 300000,
|
||||||
};
|
};
|
||||||
|
|
||||||
navigator.geolocation.getCurrentPosition(
|
navigator.geolocation.getCurrentPosition(
|
||||||
handleLocationSuccess,
|
handleLocationSuccess,
|
||||||
handleLocationError,
|
handleLocationError,
|
||||||
@@ -465,7 +489,7 @@ function requestLocationData() {
|
|||||||
|
|
||||||
function handleLocationSuccess(position) {
|
function handleLocationSuccess(position) {
|
||||||
console.log("✅ Location obtained successfully");
|
console.log("✅ Location obtained successfully");
|
||||||
|
|
||||||
userLocation = {
|
userLocation = {
|
||||||
latitude: position.coords.latitude,
|
latitude: position.coords.latitude,
|
||||||
longitude: position.coords.longitude,
|
longitude: position.coords.longitude,
|
||||||
@@ -473,14 +497,14 @@ function handleLocationSuccess(position) {
|
|||||||
altitude: position.coords.altitude,
|
altitude: position.coords.altitude,
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
source: "gps",
|
source: "gps",
|
||||||
address: null
|
address: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("📍 Location data:", userLocation);
|
console.log("📍 Location data:", userLocation);
|
||||||
|
|
||||||
// Reverse geocode to get address
|
// Reverse geocode to get address
|
||||||
reverseGeocode(userLocation.latitude, userLocation.longitude);
|
reverseGeocode(userLocation.latitude, userLocation.longitude);
|
||||||
|
|
||||||
locationRequestActive = false;
|
locationRequestActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,26 +522,26 @@ function reverseGeocode(lat, lng) {
|
|||||||
|
|
||||||
// Language functionality remains unchanged
|
// Language functionality remains unchanged
|
||||||
function initializeLanguage() {
|
function initializeLanguage() {
|
||||||
const languageToggle = document.getElementById('languageToggle');
|
const languageToggle = document.getElementById("languageToggle");
|
||||||
if (languageToggle) {
|
if (languageToggle) {
|
||||||
languageToggle.addEventListener('click', toggleLanguage);
|
languageToggle.addEventListener("click", toggleLanguage);
|
||||||
}
|
}
|
||||||
applyTranslations();
|
applyTranslations();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleLanguage() {
|
function toggleLanguage() {
|
||||||
currentLanguage = currentLanguage === 'en' ? 'es' : 'en';
|
currentLanguage = currentLanguage === "en" ? "es" : "en";
|
||||||
applyTranslations();
|
applyTranslations();
|
||||||
console.log(`🌐 Language switched to: ${currentLanguage}`);
|
console.log(`🌐 Language switched to: ${currentLanguage}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyTranslations() {
|
function applyTranslations() {
|
||||||
const languageText = document.getElementById('languageText');
|
const languageText = document.getElementById("languageText");
|
||||||
if (languageText) {
|
if (languageText) {
|
||||||
languageText.textContent = translations[currentLanguage].languageText;
|
languageText.textContent = translations[currentLanguage].languageText;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelectorAll(`[data-${currentLanguage}]`).forEach(element => {
|
document.querySelectorAll(`[data-${currentLanguage}]`).forEach((element) => {
|
||||||
element.textContent = element.getAttribute(`data-${currentLanguage}`);
|
element.textContent = element.getAttribute(`data-${currentLanguage}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -525,12 +549,12 @@ function applyTranslations() {
|
|||||||
function startClock() {
|
function startClock() {
|
||||||
function updateClock() {
|
function updateClock() {
|
||||||
currentTime = new Date();
|
currentTime = new Date();
|
||||||
const timeElements = document.querySelectorAll('.current-time');
|
const timeElements = document.querySelectorAll(".current-time");
|
||||||
timeElements.forEach(el => {
|
timeElements.forEach((el) => {
|
||||||
el.textContent = currentTime.toLocaleTimeString();
|
el.textContent = currentTime.toLocaleTimeString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateClock();
|
updateClock();
|
||||||
setInterval(updateClock, 1000);
|
setInterval(updateClock, 1000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -723,8 +723,8 @@
|
|||||||
lngDisplay.textContent = coordinatesData.longitude.toFixed(10);
|
lngDisplay.textContent = coordinatesData.longitude.toFixed(10);
|
||||||
clearBtn.style.display = "inline-flex";
|
clearBtn.style.display = "inline-flex";
|
||||||
} else {
|
} else {
|
||||||
latDisplay.textContent = "---.------";
|
latDisplay.textContent = "---.----------";
|
||||||
lngDisplay.textContent = "---.------";
|
lngDisplay.textContent = "---.----------";
|
||||||
clearBtn.style.display = "none";
|
clearBtn.style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -916,12 +916,12 @@
|
|||||||
const clearBtn = document.getElementById('clearCoordinatesBtn');
|
const clearBtn = document.getElementById('clearCoordinatesBtn');
|
||||||
|
|
||||||
if (coordinatesData.latitude && coordinatesData.longitude) {
|
if (coordinatesData.latitude && coordinatesData.longitude) {
|
||||||
latDisplay.textContent = coordinatesData.latitude.toFixed(6);
|
latDisplay.textContent = coordinatesData.latitude.toFixed(10);
|
||||||
lngDisplay.textContent = coordinatesData.longitude.toFixed(6);
|
lngDisplay.textContent = coordinatesData.longitude.toFixed(10);
|
||||||
clearBtn.style.display = 'inline-flex';
|
clearBtn.style.display = 'inline-flex';
|
||||||
} else {
|
} else {
|
||||||
latDisplay.textContent = '---.------';
|
latDisplay.textContent = '---.----------';
|
||||||
lngDisplay.textContent = '---.------';
|
lngDisplay.textContent = '---.----------';
|
||||||
clearBtn.style.display = 'none';
|
clearBtn.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user