diff --git a/templates/verification_review.html b/templates/verification_review.html
index 1e604c3..2bcc304 100644
--- a/templates/verification_review.html
+++ b/templates/verification_review.html
@@ -177,7 +177,7 @@
@@ -554,6 +567,56 @@
margin-bottom: 0.5rem;
}
+ .photo-actions {
+ display: flex;
+ gap: 0.5rem;
+ justify-content: center;
+ margin-top: 0.75rem;
+ }
+
+ .btn-photo {
+ width: 36px;
+ height: 36px;
+ border: none;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.2s;
+ text-decoration: none;
+ }
+
+ .btn-photo.download {
+ background: #3b82f6;
+ color: white;
+ }
+
+ .btn-photo.download:hover {
+ background: #2563eb;
+ transform: translateY(-2px);
+ }
+
+ .btn-photo.email {
+ background: #8b5cf6;
+ color: white;
+ }
+
+ .btn-photo.email:hover {
+ background: #7c3aed;
+ transform: translateY(-2px);
+ }
+
+ .btn-photo.view {
+ background: #10b981;
+ color: white;
+ }
+
+ .btn-photo.view:hover {
+ background: #059669;
+ transform: translateY(-2px);
+ }
+
.details-section {
display: flex;
flex-direction: column;
@@ -661,11 +724,22 @@
return;
}
- // Optional: Add note
- let note = '';
- if (status === 'rejected') {
- note = prompt('Optional: Add a note explaining why this was rejected:');
- if (note === null) return; // User cancelled
+ // Prompt for reason
+ const reasonPrompt = status === 'approved'
+ ? 'Optional: Enter a reason for approval:'
+ : 'Please enter a reason for rejection:';
+
+ let note = prompt(reasonPrompt);
+
+ // For rejection, reason is required
+ if (status === 'rejected' && (!note || note.trim() === '')) {
+ alert('A reason is required when rejecting a verification.');
+ return;
+ }
+
+ // User cancelled the prompt
+ if (note === null) {
+ return;
}
// Disable buttons
@@ -708,5 +782,90 @@
});
});
});
+
+ // Download verification photo
+ function downloadPhoto(recordId, employeeId, checkInDate) {
+ const card = document.querySelector(`[data-record-id="${recordId}"]`);
+ const photoElement = card.querySelector('.verification-photo');
+
+ if (!photoElement) {
+ alert('No photo available to download.');
+ return;
+ }
+
+ const photoSrc = photoElement.src;
+ const fileName = `verification_photo_${employeeId}_${checkInDate}.jpg`;
+
+ // Handle base64 data URL
+ if (photoSrc.startsWith('data:')) {
+ const link = document.createElement('a');
+ link.href = photoSrc;
+ link.download = fileName;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ console.log('[LOG] Photo downloaded:', fileName);
+ } else {
+ // Handle regular URL - fetch and download
+ fetch(photoSrc)
+ .then(response => response.blob())
+ .then(blob => {
+ const url = window.URL.createObjectURL(blob);
+ const link = document.createElement('a');
+ link.href = url;
+ link.download = fileName;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ window.URL.revokeObjectURL(url);
+ console.log('[LOG] Photo downloaded:', fileName);
+ })
+ .catch(error => {
+ console.error('[ERROR] Failed to download photo:', error);
+ alert('Failed to download photo. Please try again.');
+ });
+ }
+ }
+
+ // Send verification details by email
+ function sendByEmail(recordId, employeeId, employeeName, checkInDate, checkInTime, locationName, locationEvent, verificationStatus, qrAddress, checkInAddress, distance, deviceInfo) {
+ // Build the verification record URL
+ const recordUrl = window.location.origin + `/verification-review/${recordId}`;
+
+ // Build email subject
+ const subject = encodeURIComponent(`Verification Review - Employee ${employeeId} (${employeeName}) - ${checkInDate}`);
+
+ // Build email body with verification details
+ let body = `VERIFICATION PHOTO REVIEW DETAILS\n`;
+ body += `================================\n\n`;
+ body += `VIEW VERIFICATION RECORD ONLINE:\n`;
+ body += `${recordUrl}\n\n`;
+ body += `EMPLOYEE INFORMATION\n`;
+ body += `--------------------\n`;
+ body += `Employee ID: ${employeeId}\n`;
+ body += `Employee Name: ${employeeName}\n`;
+ body += `Check-in Date: ${checkInDate}\n`;
+ body += `Check-in Time: ${checkInTime}\n`;
+ body += `Verification Status: ${verificationStatus.toUpperCase()}\n\n`;
+ body += `LOCATION INFORMATION\n`;
+ body += `--------------------\n`;
+ body += `Location Name: ${locationName}\n`;
+ body += `Event Type: ${locationEvent}\n`;
+ body += `Distance from QR: ${distance} miles\n`;
+ body += `QR Code Address: ${qrAddress}\n`;
+ body += `Check-in Address: ${checkInAddress}\n`;
+ body += `Device: ${deviceInfo}\n\n`;
+ body += `--------------------\n`;
+ body += `Record ID: ${recordId}\n\n`;
+ body += `Note: Click the link above to view the verification photo and full details.\n`;
+
+ const encodedBody = encodeURIComponent(body);
+
+ // Open default email client
+ const mailtoLink = `mailto:?subject=${subject}&body=${encodedBody}`;
+ window.location.href = mailtoLink;
+
+ console.log('[LOG] Email client opened for verification record:', recordId);
+ }
{% endblock %}
\ No newline at end of file
diff --git a/templates/verification_review_detail.html b/templates/verification_review_detail.html
index 756758b..b6b7b57 100644
--- a/templates/verification_review_detail.html
+++ b/templates/verification_review_detail.html
@@ -210,6 +210,50 @@ QR Code Management{% endblock %} {% block extra_head %}
box-shadow: 0 6px 16px rgba(107, 114, 128, 0.3);
}
+ .btn-download {
+ background: #3b82f6;
+ color: white;
+ }
+
+ .btn-download:hover {
+ background: #2563eb;
+ transform: translateY(-2px);
+ box-shadow: 0 6px 16px rgba(59, 130, 246, 0.3);
+ }
+
+ .btn-email {
+ background: #8b5cf6;
+ color: white;
+ }
+
+ .btn-email:hover {
+ background: #7c3aed;
+ transform: translateY(-2px);
+ box-shadow: 0 6px 16px rgba(139, 92, 246, 0.3);
+ }
+
+ .photo-actions {
+ display: flex;
+ gap: 10px;
+ justify-content: center;
+ margin-top: 15px;
+ flex-wrap: wrap;
+ }
+
+ .photo-actions .btn {
+ padding: 10px 20px;
+ font-size: 0.9rem;
+ font-weight: 600;
+ border-radius: 6px;
+ border: none;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ transition: all 0.2s;
+ text-decoration: none;
+ }
+
.alert {
padding: 15px 20px;
border-radius: 8px;
@@ -369,7 +413,18 @@ QR Code Management{% endblock %} {% block extra_head %}
src="{{ record.verification_photo }}"
alt="Verification Photo for {{ record.employee_id }}"
class="verification-photo"
+ id="verificationPhoto"
/>
+
+
+
+
{% else %}
@@ -408,6 +463,7 @@ QR Code Management{% endblock %} {% block extra_head %}
{% endblock %}