diff --git a/public/index.html b/public/index.html
index a9af8eb..f5165f3 100644
--- a/public/index.html
+++ b/public/index.html
@@ -151,13 +151,12 @@
async function renderEmployeeDashboard() {
clearInterval(employeeTimerInterval);
- // Fetch notes along with other data
const [statusRes, timeOffRes, notesRes] = await Promise.all([apiCall('/status'), apiCall('/user/time-off-requests'), apiCall('/user/notes')]);
if (!statusRes.success || !timeOffRes.success || !notesRes.success) return;
const entries = statusRes.data;
const requests = timeOffRes.data;
- const notes = notesRes.data; // Get notes data
+ const notes = notesRes.data;
const last = entries[0];
const punchedIn = last?.status === 'in';
let totalMilliseconds = entries.reduce((acc, e) => {
@@ -181,36 +180,28 @@
-
-
My Account
-
-
-
-
My Total Hours (This Pay Period)
-
${formatDecimal(totalMilliseconds)}
-
+
My Account
+
My Total Hours (This Pay Period)
${formatDecimal(totalMilliseconds)}
+
My Time Log
| In | Out | Duration (Hours) |
${entries.map(e => `| ${formatDateTime(e.punch_in_time)} | ${formatDateTime(e.punch_out_time)} | ${e.status === 'in' ? 'Running...' : formatDecimal(new Date(e.punch_out_time) - new Date(e.punch_in_time))} |
`).join('') || '| No entries. |
'}
@@ -219,6 +210,8 @@
document.getElementById('punch-btn').addEventListener('click', handlePunch);
document.getElementById('change-password-btn').addEventListener('click', renderChangePasswordModal);
document.getElementById('time-off-form').addEventListener('submit', handleTimeOffRequest);
+ document.getElementById('view-request-history-btn').addEventListener('click', handleViewRequestHistoryClick); // Attach handler to new button
+
if (punchedIn) {
const durationCell = document.getElementById(`duration-${last.id}`);
const totalHoursCell = document.getElementById('employee-total-hours');
@@ -400,6 +393,48 @@ async function renderAdminDashboard() {
renderAdminDashboard();
}
}
+
+function renderRequestHistoryModal(requests) {
+ const modalBody = `
+
+
+
+ | Dates | Reason | Status |
+
+
+ ${requests.map(r => `
+
+ | ${formatDate(r.start_date)} - ${formatDate(r.end_date)} |
+ ${r.reason || ''} |
+ ${r.status} |
+
+ `).join('') || '| No history found. |
'}
+
+
+
`;
+
+ // Using a simplified modal since we only need a "Close" button
+ modalContainer.innerHTML = `
+
+
+
+
Full Time Off History
+
+
+ ${modalBody}
+
+
`;
+
+ document.querySelector('.cancel-modal-btn').addEventListener('click', () => modalContainer.innerHTML = '');
+ document.querySelector('.modal-overlay').addEventListener('click', (e) => { if (e.target === e.currentTarget) modalContainer.innerHTML = ''; });
+}
+
+async function handleViewRequestHistoryClick() {
+ const res = await apiCall('/user/time-off-requests/history');
+ if (res.success) {
+ renderRequestHistoryModal(res.data);
+ }
+}
async function handleAddNote(e) {
e.preventDefault();
const userId = e.target.elements['note-user-select'].value;
diff --git a/server.js b/server.js
index 9f2bdfc..289e365 100644
--- a/server.js
+++ b/server.js
@@ -177,12 +177,34 @@ function setupRoutes() {
app.get('/api/user/time-off-requests', authenticateToken, async (req, res) => {
try {
- const rows = await db.all("SELECT * FROM time_off_requests WHERE user_id = ? ORDER BY start_date DESC", [req.user.id]);
- res.json(rows);
- } catch {
- res.status(500).json({ message: "Failed to fetch requests." });
+ // This query now only gets requests that are pending OR have an end date in the future.
+ const rows = await db.all(
+ `SELECT * FROM time_off_requests
+ WHERE user_id = ? AND (status = 'pending' OR end_date >= date('now'))
+ ORDER BY start_date ASC`,
+ [req.user.id]
+ );
+ res.json(rows);
+ } catch (err) {
+ console.error("Error fetching time off requests:", err);
+ res.status(500).json({ message: "Failed to fetch requests." });
}
- });
+});
+
+app.get('/api/user/time-off-requests/history', authenticateToken, async (req, res) => {
+ try {
+ // This query gets ALL requests for the user, sorted by newest first.
+ const rows = await db.all(
+ "SELECT * FROM time_off_requests WHERE user_id = ? ORDER BY start_date DESC",
+ [req.user.id]
+ );
+ res.json(rows);
+ } catch (err) {
+ console.error("Error fetching time off history:", err);
+ res.status(500).json({ message: "Failed to fetch request history." });
+ }
+});
+
// --- Admin Tools ---
app.post('/api/admin/force-clock-out', authenticateToken, requireRole('admin'), async (req, res) => {