diff --git a/public/js/main.js b/public/js/main.js index d727d9c..0d4e13e 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -23,6 +23,7 @@ import { let user = null; let authToken = null; let lastAdminTab = 'overview'; +let lastEmployeeTab = 'dashboard'; export { lastAdminTab }; // --- NOTIFICATION LOGIC --- @@ -165,6 +166,26 @@ async function handleViewRequestHistoryClick() { } } +async function loadEmployeeCalendar() { + const iframe = document.getElementById('employee-calendar-iframe'); + const empty = document.getElementById('employee-calendar-empty'); + const link = document.getElementById('employee-calendar-link'); + if (!iframe || !empty || !link) return; + const res = await apiCall('/calendar-url'); + if (!res.success) return; + const url = res.data?.url || ''; + if (!url) { + iframe.removeAttribute('src'); + empty.classList.remove('hidden'); + link.classList.add('hidden'); + return; + } + iframe.src = url; + link.href = url; + link.classList.remove('hidden'); + empty.classList.add('hidden'); +} + async function handleEditSubmit(e) { e.preventDefault(); const id = e.target.elements['edit-id'].value; @@ -450,6 +471,16 @@ export function attachEmployeeDashboardListeners() { if (timeOffForm) { timeOffForm.addEventListener('submit', handleTimeOffRequest); } + + setupEmployeeTabs(); + if (lastEmployeeTab !== 'dashboard') { + const tabsContainer = document.getElementById('employee-tabs-nav'); + tabsContainer?.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active-tab')); + tabsContainer?.querySelector(`.tab-btn[data-tab="${lastEmployeeTab}"]`)?.classList.add('active-tab'); + document.getElementById('tab-content-employee-dashboard')?.classList.add('hidden'); + document.getElementById(`tab-content-employee-${lastEmployeeTab}`)?.classList.remove('hidden'); + } + if (lastEmployeeTab === 'calendar') loadEmployeeCalendar(); } export function attachAdminDashboardListeners() { @@ -527,6 +558,30 @@ function setupTabbedInterface() { }); } +function setupEmployeeTabs() { + const tabsContainer = document.getElementById('employee-tabs-nav'); + const contentContainer = document.getElementById('employee-tabs-content'); + if (!tabsContainer || !contentContainer) return; + + tabsContainer.addEventListener('click', (e) => { + const clickedTab = e.target.closest('.tab-btn'); + if (!clickedTab) return; + + const tabTarget = clickedTab.dataset.tab; + lastEmployeeTab = tabTarget; + + tabsContainer.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active-tab')); + clickedTab.classList.add('active-tab'); + + contentContainer.querySelectorAll('[id^="tab-content-employee-"]').forEach(panel => { + panel.classList.add('hidden'); + }); + document.getElementById(`tab-content-employee-${tabTarget}`).classList.remove('hidden'); + + if (tabTarget === 'calendar') loadEmployeeCalendar(); + }); +} + // --- START THE APP --- // Register the service worker when the page loads if ('serviceWorker' in navigator) { diff --git a/public/js/ui.js b/public/js/ui.js index 422a744..00b3e3a 100644 --- a/public/js/ui.js +++ b/public/js/ui.js @@ -94,71 +94,92 @@ export async function renderEmployeeDashboard() { }, 0); mainViews.employee.innerHTML = ` -
${punchedIn ? 'Punched In' : 'Punched Out'}
-${punchedIn ? 'Since:' : 'Last Punch:'} ${utils.formatDateTime(punchedIn ? last.punch_in_time : last?.punch_out_time)}
+${punchedIn ? 'Punched In' : 'Punched Out'}
+${punchedIn ? 'Since:' : 'Last Punch:'} ${utils.formatDateTime(punchedIn ? last.punch_in_time : last?.punch_out_time)}
+"${note.note_text}"
- ${note.admin_username} on ${utils.formatDate(note.created_at)}
You have no new notes.
'}${utils.formatDecimal(totalMilliseconds)}
| Dates | +Reason | +Status | +Actions | +
|---|---|---|---|
| ${utils.formatDate(r.start_date)} - ${utils.formatDate(r.end_date)} | +${r.reason || ''} | +${r.status} | +
+ ${r.status === 'pending' ? `
+
+
+
+
+ ` : ''}
+ |
+
| No upcoming or pending requests. | |||
| In | Out | Duration (Hours) |
|---|---|---|
| ${utils.formatDateTime(e.punch_in_time)} | ${utils.formatDateTime(e.punch_out_time)} | ${e.status === 'in' ? 'Running...' : utils.formatDecimal(new Date(e.punch_out_time) - new Date(e.punch_in_time))} |
| No entries. | ||
"${note.note_text}"
- ${note.admin_username} on ${utils.formatDate(note.created_at)}
You have no new notes.
'}${utils.formatDecimal(totalMilliseconds)}
| Dates | -Reason | -Status | -Actions | -
|---|---|---|---|
| ${utils.formatDate(r.start_date)} - ${utils.formatDate(r.end_date)} | -${r.reason || ''} | -${r.status} | -
- ${r.status === 'pending' ? `
-
-
-
-
- ` : ''}
- |
-
| No upcoming or pending requests. | |||
| In | Out | Duration (Hours) |
|---|---|---|
| ${utils.formatDateTime(e.punch_in_time)} | ${utils.formatDateTime(e.punch_out_time)} | ${e.status === 'in' ? 'Running...' : utils.formatDecimal(new Date(e.punch_out_time) - new Date(e.punch_in_time))} |
| No entries. | ||