diff --git a/app-frontend/employer-panel/src/pages/EmployerDashboard.css b/app-frontend/employer-panel/src/pages/EmployerDashboard.css index d46d5d17f..e0641cb9c 100644 --- a/app-frontend/employer-panel/src/pages/EmployerDashboard.css +++ b/app-frontend/employer-panel/src/pages/EmployerDashboard.css @@ -436,6 +436,18 @@ body { flex-wrap: wrap; } +.ss-request-reason { + font-size: 13px; + color: var(--ss-muted); +} + +.ss-request-actions { + display: flex; + gap: 10px; + justify-content: flex-end; +} + +/* Incident Management */ .ss-incident-toolbar { display: grid; grid-template-columns: 2fr repeat(3, minmax(130px, 1fr)) auto; @@ -842,4 +854,82 @@ body { .form-grid { grid-template-columns: 1fr; } + + .ss-priority-topstats { + grid-template-columns: 1fr; + } +} + +.ss-requests-list { + display: flex; + flex-direction: column; + gap: 12px; +} + +.ss-request-row { + display: grid; + grid-template-columns: 2fr 1fr 1.2fr; + gap: 16px; + align-items: center; + background: #fff; + border-radius: 14px; + padding: 16px; + box-shadow: var(--shadow-soft); +} + +.ss-request-left { + display: flex; + flex-direction: column; + gap: 6px; +} + +.ss-request-type { + font-size: 14px; + font-weight: 700; + color: #162447; +} + +.ss-request-employee { + font-size: 13px; + color: #4f5b73; +} + +.ss-request-reason { + font-size: 12px; + color: var(--ss-muted); +} + +.ss-request-middle { + display: flex; + align-items: center; + justify-content: center; +} + +.ss-request-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 10px; + flex-wrap: wrap; +} + +.ss-secondary { + background: #f0f2f7; + color: var(--ss-blue-800); + border: none; + padding: 8px 14px; + border-radius: 999px; + font-weight: 600; + cursor: pointer; +} + +.ss-secondary--danger { + background: #fdeaea; + color: var(--ss-red); +} + +.ss-primary:disabled, +.ss-secondary:disabled { + opacity: 0.6; + cursor: not-allowed; } \ No newline at end of file diff --git a/app-frontend/employer-panel/src/pages/EmployerDashboard.js b/app-frontend/employer-panel/src/pages/EmployerDashboard.js index 3c0b4b774..dbc2e0353 100644 --- a/app-frontend/employer-panel/src/pages/EmployerDashboard.js +++ b/app-frontend/employer-panel/src/pages/EmployerDashboard.js @@ -1,7 +1,6 @@ import React, { useMemo, useRef, useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import "./EmployerDashboard.css"; -import translations from '../i18n/translations'; /* --- icons --- */ const IconCalendar = (props) => ( @@ -139,6 +138,45 @@ export default function EmployerDashboard() { const [incidentSeverityFilter, setIncidentSeverityFilter] = useState("All"); const [incidentSort, setIncidentSort] = useState("Newest"); + const [requests, setRequests] = useState([ + { + id: "REQ-1001", + type: "Shift Swap", + employee: "John Doe", + shift: "Crowd Control - Marvel Stadium", + requestDate: "28-04-2026", + reason: "Requested shift swap due to university exam.", + status: "Pending", + }, + { + id: "REQ-1002", + type: "Leave", + employee: "Amy Huggins", + shift: "Shopping Centre Security - Chadstone", + requestDate: "29-04-2026", + reason: "Medical appointment.", + status: "Pending", + }, + { + id: "REQ-1003", + type: "Shift Swap", + employee: "Andrew Goddard", + shift: "Event Security - Rod Laver Arena", + requestDate: "30-04-2026", + reason: "Requested swap with another available guard.", + status: "Approved", + }, + { + id: "REQ-1004", + type: "Leave", + employee: "Amy Huggins", + shift: "Shopping Centre Security - Chadstone", + requestDate: "01-05-2026", + reason: "Family commitment.", + status: "Rejected", + }, + ]); + const [incidents, setIncidents] = useState([ { id: "INC-9921", @@ -226,7 +264,7 @@ export default function EmployerDashboard() { return { id: shift._id || shift.id || idx, - title: shift.title || shift.role || "Shift 1", + title: shift.title || shift.role || "Shift", location: formatLocation(shift.location || shift.venue), date: formatShiftDate(shift.date || shift.shiftDate), time: @@ -237,6 +275,7 @@ export default function EmployerDashboard() { payRate: shift.payRate ?? shift.rate ?? shift.hourlyRate ?? 0, priority: shift.priority || (idx % 3 === 0 ? "High" : idx % 3 === 1 ? "Medium" : "Low"), + assignedGuards: shift.assignedGuards ?? shift.guardsAssigned ?? 0, }; }); @@ -254,6 +293,7 @@ export default function EmployerDashboard() { status: { text: "Open", tone: "confirmed" }, payRate: 23, priority: "High", + assignedGuards: 2, }, { id: 2, @@ -264,6 +304,7 @@ export default function EmployerDashboard() { status: { text: "Open", tone: "confirmed" }, payRate: 23, priority: "High", + assignedGuards: 1, }, { id: 3, @@ -274,6 +315,7 @@ export default function EmployerDashboard() { status: { text: "Open", tone: "confirmed" }, payRate: 23, priority: "High", + assignedGuards: 3, }, { id: 4, @@ -284,6 +326,7 @@ export default function EmployerDashboard() { status: { text: "Open", tone: "confirmed" }, payRate: 23, priority: "High", + assignedGuards: 2, }, { id: 5, @@ -294,6 +337,7 @@ export default function EmployerDashboard() { status: { text: "Open", tone: "confirmed" }, payRate: 23, priority: "High", + assignedGuards: 2, }, { id: 6, @@ -304,6 +348,7 @@ export default function EmployerDashboard() { status: { text: "Pending", tone: "pending" }, payRate: 25, priority: "Medium", + assignedGuards: 1, }, { id: 7, @@ -314,6 +359,7 @@ export default function EmployerDashboard() { status: { text: "Completed", tone: "completed" }, payRate: 24, priority: "Low", + assignedGuards: 4, }, ]); } finally { @@ -441,6 +487,11 @@ export default function EmployerDashboard() { ); }, [incidents]); + const pendingRequestCount = useMemo( + () => requests.filter((req) => req.status === "Pending").length, + [requests] + ); + const updateIncident = (id, newStatus, newSeverity, newComments) => { setIncidents((prev) => prev.map((inc) => @@ -458,6 +509,12 @@ export default function EmployerDashboard() { }); }; + const updateRequestStatus = (id, newStatus) => { + setRequests((prev) => + prev.map((req) => (req.id === id ? { ...req, status: newStatus } : req)) + ); + }; + const scrollByAmount = (ref, amt) => { if (!ref.current) return; ref.current.scrollBy({ left: amt, behavior: "smooth" }); @@ -661,6 +718,62 @@ export default function EmployerDashboard() { +
+ {pendingRequestCount} pending · {requests.length} total +
+@@ -807,7 +920,11 @@ export default function EmployerDashboard() { {selectedIncident && (