diff --git a/app.py b/app.py index 577363b..a7c4d04 100644 --- a/app.py +++ b/app.py @@ -7201,7 +7201,6 @@ def export_time_attendance_csv(records, timestamp, filter_str): # Write header writer.writerow([ - 'ID', 'Employee ID', 'Employee Name', 'Platform', @@ -7210,17 +7209,12 @@ def export_time_attendance_csv(records, timestamp, filter_str): 'Location Name', 'Action Description', 'Event Description', - 'Recorded Address', - 'Import Batch ID', - 'Import Date', - 'Import Source', - 'Created Date' + 'Recorded Address' ]) # Write data rows for record in records: writer.writerow([ - record.id, record.employee_id, record.employee_name, record.platform or '', @@ -7229,11 +7223,7 @@ def export_time_attendance_csv(records, timestamp, filter_str): record.location_name, record.action_description, record.event_description or '', - record.recorded_address or '', - record.import_batch_id or '', - record.import_date.strftime('%Y-%m-%d %H:%M:%S') if record.import_date else '', - record.import_source or '', - record.created_date.strftime('%Y-%m-%d %H:%M:%S') if record.created_date else '' + record.recorded_address or '' ]) # Prepare response @@ -7272,9 +7262,9 @@ def export_time_attendance_excel(records, timestamp, filter_str): # Headers headers = [ - 'ID', 'Employee ID', 'Employee Name', 'Platform', 'Date', 'Time', + 'Employee ID', 'Employee Name', 'Platform', 'Date', 'Time', 'Location Name', 'Action Description', 'Event Description', - 'Recorded Address', 'Import Batch ID', 'Import Date', 'Import Source' + 'Recorded Address' ] # Write headers @@ -7289,7 +7279,6 @@ def export_time_attendance_excel(records, timestamp, filter_str): # Write data for row_num, record in enumerate(records, 2): data = [ - record.id, record.employee_id, record.employee_name, record.platform or '', @@ -7298,10 +7287,7 @@ def export_time_attendance_excel(records, timestamp, filter_str): record.location_name, record.action_description, record.event_description or '', - record.recorded_address or '', - record.import_batch_id or '', - record.import_date.strftime('%Y-%m-%d %H:%M:%S') if record.import_date else '', - record.import_source or '' + record.recorded_address or '' ] for col_num, value in enumerate(data, 1): diff --git a/templates/time_attendance_records.html b/templates/time_attendance_records.html index a61f304..22ed1c6 100644 --- a/templates/time_attendance_records.html +++ b/templates/time_attendance_records.html @@ -35,10 +35,23 @@ Import Data {% endif %} - +
+ + +
@@ -328,10 +341,57 @@ function confirmDelete(recordId, employeeName, date) { } } -function exportRecords() { - alert('Export functionality coming soon!'); +function toggleExportMenu(event) { + event.stopPropagation(); + const menu = document.getElementById('exportMenu'); + const isVisible = menu.style.display === 'block'; + + // Close menu if open, open if closed + menu.style.display = isVisible ? 'none' : 'block'; } +function exportRecords(format) { + // Close the dropdown menu + document.getElementById('exportMenu').style.display = 'none'; + + // Get current filter values + const employeeId = document.querySelector('input[name="employee_id"]')?.value || ''; + const locationName = document.querySelector('input[name="location_name"]')?.value || ''; + const startDate = document.querySelector('input[name="start_date"]')?.value || ''; + const endDate = document.querySelector('input[name="end_date"]')?.value || ''; + + // Build query parameters + const params = new URLSearchParams(); + if (employeeId) params.append('employee_id', employeeId); + if (locationName) params.append('location_name', locationName); + if (startDate) params.append('start_date', startDate); + if (endDate) params.append('end_date', endDate); + params.append('format', format); + + // Redirect to export endpoint + window.location.href = `/time-attendance/export?${params.toString()}`; +} + +// Close dropdown when clicking outside +document.addEventListener('click', function(event) { + const menu = document.getElementById('exportMenu'); + const exportWrapper = document.querySelector('.export-dropdown-wrapper'); + + if (menu && exportWrapper && !exportWrapper.contains(event.target)) { + menu.style.display = 'none'; + } +}); + +// Close dropdown with Escape key +document.addEventListener('keydown', function(event) { + if (event.key === 'Escape') { + const menu = document.getElementById('exportMenu'); + if (menu) { + menu.style.display = 'none'; + } + } +}); + // Initialize filters state document.addEventListener('DOMContentLoaded', function() { const filterBody = document.getElementById('filterBody'); @@ -430,5 +490,81 @@ document.addEventListener('DOMContentLoaded', function() { display: none; } } +.export-dropdown-wrapper { + position: relative; + display: inline-block; +} + +.export-dropdown-menu { + position: absolute; + top: calc(100% + 0.5rem); + right: 0; + background: #ffffff; + border: 1px solid #e2e8f0; + border-radius: 0.5rem; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + z-index: 1000; + min-width: 200px; + overflow: hidden; + animation: slideDown 0.2s ease-out; +} + +@keyframes slideDown { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.export-option { + width: 100%; + padding: 0.875rem 1rem; + border: none; + background: none; + text-align: left; + cursor: pointer; + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 0.9375rem; + color: #0f172a; + transition: background-color 0.15s ease; + border-bottom: 1px solid #f1f5f9; +} + +.export-option:last-child { + border-bottom: none; +} + +.export-option:hover { + background: #f8fafc; +} + +.export-option:active { + background: #f1f5f9; +} + +.export-option i { + font-size: 1.125rem; + width: 20px; + text-align: center; +} + +.export-option span { + font-weight: 500; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .export-dropdown-menu { + right: auto; + left: 0; + min-width: 180px; + } +} {% endblock %} \ No newline at end of file