diff --git a/public/js/main.js b/public/js/main.js index 9b6079c..25176f0 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -231,6 +231,50 @@ function initializeApp() { } } +function setupTabbedInterface() { + const tabsContainer = document.getElementById('admin-tabs-nav'); + const contentContainer = document.getElementById('admin-tabs-content'); + + if (!tabsContainer) return; + + tabsContainer.addEventListener('click', (e) => { + const clickedTab = e.target.closest('.tab-btn'); + if (!clickedTab) return; + + // Get the target tab's identifier + const tabTarget = clickedTab.dataset.tab; + + // Update the tab buttons' active state + tabsContainer.querySelectorAll('.tab-btn').forEach(btn => { + btn.classList.remove('active-tab'); + }); + clickedTab.classList.add('active-tab'); + + // Update the visible content panel + contentContainer.querySelectorAll('[id^="tab-content-"]').forEach(panel => { + panel.classList.add('hidden'); + }); + document.getElementById(`tab-content-${tabTarget}`).classList.remove('hidden'); + }); +} + +// NOW, UPDATE your existing attachAdminDashboardListeners function to call this new function. + +export function attachAdminDashboardListeners() { + // Event delegation for all buttons + document.getElementById('admin-dashboard').addEventListener('click', handleAdminDashboardClick); + + // Specific form handlers + document.getElementById('create-user-form').addEventListener('submit', handleCreateUser); + document.getElementById('add-punch-form').addEventListener('submit', handleAddPunch); + document.getElementById('add-note-form').addEventListener('submit', handleAddNote); + + // ... Any other listeners you have here ... + + // ADD THIS LINE at the end of the function: + setupTabbedInterface(); +} + // --- START THE APP --- // Attach global listeners that are always present. document.getElementById('sign-out-btn').addEventListener('click', () => handleSignOut('You have been signed out.')); diff --git a/public/js/ui.js b/public/js/ui.js index 0ca95a3..7c63000 100644 --- a/public/js/ui.js +++ b/public/js/ui.js @@ -147,52 +147,71 @@ export async function renderEmployeeDashboard() { } } +// In js/ui.js + export async function renderAdminDashboard() { showView('admin'); const [logsRes, usersRes, requestsRes] = await Promise.all([apiCall('/admin/logs'), apiCall('/admin/users'), apiCall('/admin/time-off-requests/pending')]); if (!logsRes.success || !usersRes.success || !requestsRes.success) return; - // Update module-level state + // Existing data processing logic... allTimeEntries = logsRes.data; allUsers = usersRes.data; const pendingRequests = requestsRes.data; const user = JSON.parse(localStorage.getItem('user')); - const employeeTotals = allTimeEntries.reduce((acc, entry) => { const dur = entry.punch_out_time ? (new Date(entry.punch_out_time) - new Date(entry.punch_in_time)) : (Date.now() - new Date(entry.punch_in_time)); acc[entry.username] = (acc[entry.username] || 0) + dur; return acc; }, {}); const punchedInEntries = allTimeEntries.filter(e => e.status === 'in'); const employeesOnly = allUsers.filter(u => u.role === 'employee'); - - mainViews.admin.innerHTML = ` -
| Employee | Dates | Reason | Actions |
|---|---|---|---|
| ${r.username} | ${utils.formatDate(r.start_date)} - ${utils.formatDate(r.end_date)} | ${r.reason||''} | |
| No pending requests. | |||
| Employee | Total Hours |
|---|---|
| ${username} | ${utils.formatDecimal(totalMs)} |
| No data. | |
| Employee | In | Out | Duration | Actions |
|---|---|---|---|---|
| ${e.username||'N/A'} | ${utils.formatDateTime(e.punch_in_time)} | ${utils.formatDateTime(e.punch_out_time)} | ${e.punch_out_time ? utils.formatDecimal(new Date(e.punch_out_time) - new Date(e.punch_in_time)) + ' hrs' : '...'} |
| Username | Role | Actions |
|---|---|---|
| ${u.username} | ${u.role} | ${u.isPrimary ? `Primary Admin` : `${u.username !== user.username ? `` : ''}`} |
| Employee | Dates | Reason | Actions |
|---|---|---|---|
| ${r.username} | ${utils.formatDate(r.start_date)} - ${utils.formatDate(r.end_date)} | ${r.reason||''} | |
| No pending requests. | |||