Updated: add verification review detail
This commit is contained in:
@@ -639,15 +639,15 @@ function createTableRow(record, displayIndex) {
|
||||
let locationAccuracyBadge;
|
||||
|
||||
if (record.verification_required && record.verification_status === 'pending') {
|
||||
// Show Review Needed badge for pending verification
|
||||
locationAccuracyBadge = `<span class="location-accuracy-badge badge-review-needed"
|
||||
onclick="openVerificationPhotoModal('${record.id}')"
|
||||
style="cursor: pointer;"
|
||||
// Show Review Needed badge for pending verification - LINK to review page
|
||||
locationAccuracyBadge = `<a href="/verification-review/${record.id}"
|
||||
class="location-accuracy-badge badge-review-needed"
|
||||
style="cursor: pointer; text-decoration: none;"
|
||||
title="Click to review verification photo - Distance: ${record.location_accuracy ? record.location_accuracy.toFixed(3) : 'N/A'} miles">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Review Needed
|
||||
<small>(${record.location_accuracy ? record.location_accuracy.toFixed(3) : 'N/A'} mi)</small>
|
||||
</span>`;
|
||||
</a>`;
|
||||
} else if (record.verification_status === 'approved') {
|
||||
// Show Verified badge for approved verification
|
||||
locationAccuracyBadge = `<span class="location-accuracy-badge badge-verified"
|
||||
@@ -838,11 +838,11 @@ function createTableRow(record, displayIndex) {
|
||||
<div class="record-actions">
|
||||
${
|
||||
record.verification_required && record.verification_status === 'pending'
|
||||
? `<button onclick="openVerificationPhotoModal('${record.id}')"
|
||||
? `<a href="/verification-review/${record.id}"
|
||||
class="action-btn btn-review"
|
||||
title="Review Verification Photo">
|
||||
<i class="fas fa-camera"></i>
|
||||
</button>`
|
||||
</a>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
@@ -1176,237 +1176,4 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
|
||||
console.log("Enhanced export functionality initialized");
|
||||
});
|
||||
|
||||
// ============================================
|
||||
// VERIFICATION PHOTO REVIEW FUNCTIONS
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Open verification photo modal for review
|
||||
* @param {string} recordId - The attendance record ID
|
||||
*/
|
||||
function openVerificationPhotoModal(recordId) {
|
||||
console.log(`Opening verification photo modal for record: ${recordId}`);
|
||||
|
||||
const modal = document.getElementById("verificationPhotoModal");
|
||||
const modalBody = document.getElementById("verificationPhotoModalBody");
|
||||
|
||||
if (!modal || !modalBody) {
|
||||
console.error("Verification photo modal elements not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
modalBody.innerHTML = `
|
||||
<div class="verification-loading">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<p>Loading verification photo...</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
modal.style.display = "block";
|
||||
|
||||
// Fetch record details with verification photo
|
||||
fetch(`/api/attendance/${recordId}/verification-details`)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch verification details");
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((data) => {
|
||||
if (!data.success) {
|
||||
throw new Error(data.message || "Failed to load verification data");
|
||||
}
|
||||
|
||||
renderVerificationPhotoModal(data.record);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error loading verification photo:", error);
|
||||
modalBody.innerHTML = `
|
||||
<div class="verification-error">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<p>Error loading verification photo. Please try again.</p>
|
||||
<button onclick="closeVerificationPhotoModal()" class="btn btn-secondary">Close</button>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render verification photo modal content
|
||||
* @param {Object} record - The attendance record with verification data
|
||||
*/
|
||||
function renderVerificationPhotoModal(record) {
|
||||
const modalBody = document.getElementById("verificationPhotoModalBody");
|
||||
|
||||
const content = `
|
||||
<div class="verification-photo-review">
|
||||
<!-- Employee & Date Info -->
|
||||
<div class="verification-header-info">
|
||||
<h3>
|
||||
<i class="fas fa-user"></i>
|
||||
Employee: ${record.employee_id}
|
||||
</h3>
|
||||
<p>
|
||||
<i class="fas fa-calendar"></i>
|
||||
${record.check_in_date} at ${record.check_in_time}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Verification Photo -->
|
||||
<div class="verification-photo-container">
|
||||
${
|
||||
record.verification_photo
|
||||
? `<img src="${record.verification_photo}"
|
||||
alt="Verification Photo"
|
||||
class="verification-photo-large"
|
||||
onclick="window.open(this.src, '_blank')"
|
||||
style="cursor: zoom-in;"
|
||||
title="Click to view full size" />`
|
||||
: `<div class="no-photo">
|
||||
<i class="fas fa-image"></i>
|
||||
<p>No verification photo available</p>
|
||||
</div>`
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Location Details -->
|
||||
<div class="verification-details-grid">
|
||||
<div class="verification-detail-card">
|
||||
<h4>Location Name</h4>
|
||||
<p>${record.location_name}</p>
|
||||
</div>
|
||||
|
||||
<div class="verification-detail-card">
|
||||
<h4>Distance from QR</h4>
|
||||
<p>${parseFloat(record.location_accuracy).toFixed(3)} miles</p>
|
||||
</div>
|
||||
|
||||
<div class="verification-detail-card">
|
||||
<h4>Verification Status</h4>
|
||||
<p>
|
||||
<span class="verification-status-pending">
|
||||
<i class="fas fa-clock"></i>
|
||||
Pending Review
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="verification-detail-card">
|
||||
<h4>Device</h4>
|
||||
<p>${record.device_info || "Unknown"}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Address Information -->
|
||||
<div class="verification-detail-card" style="grid-column: 1 / -1;">
|
||||
<h4>Check-in Address</h4>
|
||||
<p>${record.checked_in_address || "No address recorded"}</p>
|
||||
</div>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="verification-actions">
|
||||
<button onclick="updateVerificationStatus(${
|
||||
record.id
|
||||
}, 'approved')" class="btn-approve">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
Approve Check-in
|
||||
</button>
|
||||
<button onclick="updateVerificationStatus(${
|
||||
record.id
|
||||
}, 'rejected')" class="btn-reject">
|
||||
<i class="fas fa-times-circle"></i>
|
||||
Reject Check-in
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
modalBody.innerHTML = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close verification photo modal
|
||||
*/
|
||||
function closeVerificationPhotoModal() {
|
||||
const modal = document.getElementById("verificationPhotoModal");
|
||||
if (modal) {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update verification status (approve/reject)
|
||||
* @param {number} recordId - The attendance record ID
|
||||
* @param {string} status - The new status ('approved' or 'rejected')
|
||||
*/
|
||||
function updateVerificationStatus(recordId, status) {
|
||||
if (
|
||||
!confirm(
|
||||
`Are you sure you want to ${status} this verification?\n\nThis action will be logged for audit purposes.`
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Updating verification status for record ${recordId} to ${status}`);
|
||||
|
||||
// Show loading state
|
||||
const modalBody = document.getElementById("verificationPhotoModalBody");
|
||||
modalBody.innerHTML = `
|
||||
<div class="verification-loading">
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<p>Updating verification status...</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Send update request
|
||||
fetch(`/verification-review/${recordId}/update`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
status: status,
|
||||
note: `Verification ${status} from attendance report review`,
|
||||
}),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.success) {
|
||||
alert(
|
||||
`Verification ${status} successfully!\n\nThe page will reload to show the updated status.`
|
||||
);
|
||||
closeVerificationPhotoModal();
|
||||
// Reload the page to show updated status
|
||||
window.location.reload();
|
||||
} else {
|
||||
throw new Error(data.message || "Failed to update verification status");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error updating verification status:", error);
|
||||
alert(`Error: ${error.message}\n\nPlease try again.`);
|
||||
// Reload modal to show previous state
|
||||
openVerificationPhotoModal(recordId);
|
||||
});
|
||||
}
|
||||
|
||||
// Close verification modal when clicking outside
|
||||
window.addEventListener("click", function (event) {
|
||||
const verificationModal = document.getElementById("verificationPhotoModal");
|
||||
|
||||
if (event.target === verificationModal) {
|
||||
closeVerificationPhotoModal();
|
||||
}
|
||||
});
|
||||
|
||||
// Keyboard shortcut for closing verification modal
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.key === "Escape") {
|
||||
closeVerificationPhotoModal();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user