From 2ca483f2a679878d15ffe652c7c66aed59ad9ab3 Mon Sep 17 00:00:00 2001 From: Basichy Date: Tue, 20 Jan 2026 11:35:11 +1100 Subject: [PATCH] Implement incident management system with review workflow --- .../src/pages/EmployerDashboard.css | 119 ++++++++++++++++++ .../src/pages/EmployerDashboard.js | 113 +++++++++++++++++ 2 files changed, 232 insertions(+) diff --git a/app-frontend/employer-panel/src/pages/EmployerDashboard.css b/app-frontend/employer-panel/src/pages/EmployerDashboard.css index 31808fe88..9a3f3d89c 100644 --- a/app-frontend/employer-panel/src/pages/EmployerDashboard.css +++ b/app-frontend/employer-panel/src/pages/EmployerDashboard.css @@ -277,4 +277,123 @@ body { } .ss-card__createtext { font-weight:600; +} + +/* Incident Management */ + +.ss-row .ss-incident-id { + color: #000; + font-weight: 700; +} + +.ss-status--resolved { + color: #2e7d32; +} + +/* Modal Layout */ +.create-shift-modal-backdrop { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(10, 43, 102, 0.5); + display: grid; + place-items: center; + z-index: 1000; + padding: 20px; +} + +.create-shift-card { + background: #fff; + border-radius: var(--radius-lg); + padding: 30px; + width: 100%; + box-shadow: var(--shadow); + animation: modalSlideUp 0.3s ease-out; +} + +@keyframes modalSlideUp { + from { transform: translateY(20px); opacity: 0; } + to { transform: translateY(0); opacity: 1; } +} + +.create-shift-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 24px; + border-bottom: 1px solid var(--ss-border); + padding-bottom: 16px; +} + +.form-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 8px; +} + +.form-group label { + font-weight: 700; + font-size: 13px; + text-transform: uppercase; + color: var(--ss-muted); +} + +.ss-input-static { + background: #f5f5f5; + border: 1px solid var(--ss-border); + color: var(--ss-text); + font-weight: 600; +} + +.ss-incident-description { + background: #fff9e6; + padding: 15px; + border-radius: 8px; + border: 1px solid #ffeeba; + font-size: 14px; + line-height: 1.6; +} + +.ss-evidence-img { + width: 120px; + height: 100px; + object-fit: cover; + border-radius: 8px; + border: 1px solid var(--ss-border); + transition: transform 0.2s; +} + +.ss-evidence-img:hover { + transform: scale(1.05); +} + +.actions { + display: flex; + justify-content: flex-end; + gap: 12px; +} + +.actions .primary { + background: var(--ss-blue-800); + color: #fff; + border: none; + padding: 10px 24px; + border-radius: 999px; + font-weight: 600; + cursor: pointer; +} + +.actions .secondary { + background: #f0f2f7; + color: var(--ss-blue-800); + border: none; + padding: 10px 24px; + border-radius: 999px; + font-weight: 600; + cursor: pointer; } \ 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 73717632e..587af0016 100644 --- a/app-frontend/employer-panel/src/pages/EmployerDashboard.js +++ b/app-frontend/employer-panel/src/pages/EmployerDashboard.js @@ -57,6 +57,25 @@ export default function EmployerDashboard() { const reviewScroller = useRef(null); const [showCreateModal, setShowCreateModal] = useState(false); + // States for Incident Management + const [selectedIncident, setSelectedIncident] = useState(null); + const [incidents, setIncidents] = useState([ + { + id: "INC-9921", + guard: "John Doe", + shift: "Crowd Control - Marvel", + date: "09-08-2025", + time: "10:45 PM", + status: "Pending", + severity: "High", + description: "A patron was found attempting to bypass security with restricted items. Incident was recorded and patron escorted out.", + + // Demo Image + photos: ["https://images.unsplash.com/photo-1582139329536-e7284fece509?auto=format&fit=crop&w=300&q=80"], + comments: "" + } + ]); + const shifts = useMemo(() => [ { role: "Crowd Control", company: "AIG Solutions", venue: "Marvel Stadium", rate: 55, status: { text: "Confirmed", tone: "confirmed" }, date: "09-08-2025", time: "5:00 pm - 1:00 am" }, { role: "Shopping Centre Security", company: "Vicinity Centres", venue: "Chadstone Shopping Centre", rate: 75, status: { text: "Pending", tone: "pending" }, date: "03-08-2025", time: "1:00 pm - 9:00 pm" }, @@ -76,6 +95,13 @@ export default function EmployerDashboard() { ref.current.scrollBy({ left: amt, behavior: "smooth" }); }; + const updateIncident = (id, newStatus, newSeverity, newComments) => { + setIncidents(prev => prev.map(inc => + inc.id === id ? { ...inc, status: newStatus, severity: newSeverity, comments: newComments } : inc + )); + setSelectedIncident(null); + }; + return (
@@ -159,6 +185,33 @@ export default function EmployerDashboard() {
+ {/* Incident Reports */} +

Incident Reports

+
+
+
+
+ {incidents.map((inc, i) => ( +
+
{inc.guard}
+
{inc.shift}
+
{inc.id}
+
+ {inc.date} +
+
+ {inc.status} +
+
+ +
+
+ ))} +
+
+
+
+ {/* Reviews */}

Recent Review

@@ -183,6 +236,66 @@ export default function EmployerDashboard() {
+ + {/* Incident Detail Modal */} + {selectedIncident && ( +
setSelectedIncident(null)}> +
e.stopPropagation()} style={{ maxWidth: '700px' }}> +
+
+

Incident Details ({selectedIncident.id})

+

+ Recorded on: {selectedIncident.date} at {selectedIncident.time} +

+
+ + {selectedIncident.status} + +
+ +
+
+ +
{selectedIncident.guard}
+
+
+ + +
+
+ +
+ +
{selectedIncident.description}
+
+ +
+ +
+ {selectedIncident.photos.map((url, idx) => ( + incident evidence + ))} +
+
+ +
+ +