From 7ee76468c4b8aec028a1ab6365dd6c8c509ea753 Mon Sep 17 00:00:00 2001 From: jason Date: Sat, 7 Mar 2026 09:25:49 -0600 Subject: [PATCH] feat: wire EditEmployeeModal and AmendViolationModal into EmployeeModal --- client/src/components/EmployeeModal.jsx | 107 ++++++++++++++++-------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/client/src/components/EmployeeModal.jsx b/client/src/components/EmployeeModal.jsx index aca7091..4706e87 100755 --- a/client/src/components/EmployeeModal.jsx +++ b/client/src/components/EmployeeModal.jsx @@ -2,6 +2,8 @@ import React, { useState, useEffect, useCallback } from 'react'; import axios from 'axios'; import CpasBadge, { getTier } from './CpasBadge'; import NegateModal from './NegateModal'; +import EditEmployeeModal from './EditEmployeeModal'; +import AmendViolationModal from './AmendViolationModal'; const s = { overlay: { @@ -18,10 +20,15 @@ const s = { padding: '24px 28px', position: 'sticky', top: 0, zIndex: 10, borderBottom: '1px solid #222', }, + headerRow: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }, closeBtn: { float: 'right', background: 'none', border: 'none', color: 'white', fontSize: '22px', cursor: 'pointer', lineHeight: 1, marginTop: '-2px', }, + editEmpBtn: { + background: 'none', border: '1px solid #555', color: '#ccc', borderRadius: '5px', + padding: '4px 10px', fontSize: '11px', cursor: 'pointer', marginTop: '8px', fontWeight: 600, + }, body: { padding: '24px 28px', flex: 1 }, scoreRow: { display: 'flex', gap: '12px', flexWrap: 'wrap', marginBottom: '24px' }, scoreCard: { @@ -62,19 +69,31 @@ const s = { borderRadius: '4px', padding: '3px 8px', fontSize: '11px', cursor: 'pointer', fontWeight: 600, }, + amendBtn: { + background: 'none', border: '1px solid #4db6ac', color: '#4db6ac', + borderRadius: '4px', padding: '3px 8px', fontSize: '11px', + cursor: 'pointer', marginRight: '4px', fontWeight: 600, + }, deleteConfirm: { background: '#3c1114', border: '1px solid #f5c6cb', borderRadius: '6px', padding: '12px', marginTop: '8px', fontSize: '12px', color: '#ffb3b8', }, + amendBadge: { + display: 'inline-block', marginLeft: '4px', padding: '1px 5px', borderRadius: '8px', + fontSize: '9px', fontWeight: 700, background: '#0e2a2a', color: '#4db6ac', + border: '1px solid #1a4a4a', verticalAlign: 'middle', + }, }; export default function EmployeeModal({ employeeId, onClose }) { - const [employee, setEmployee] = useState(null); - const [score, setScore] = useState(null); + const [employee, setEmployee] = useState(null); + const [score, setScore] = useState(null); const [violations, setViolations] = useState([]); - const [loading, setLoading] = useState(true); - const [negating, setNegating] = useState(null); + const [loading, setLoading] = useState(true); + const [negating, setNegating] = useState(null); const [confirmDel, setConfirmDel] = useState(null); + const [editingEmp, setEditingEmp] = useState(false); + const [amending, setAmending] = useState(null); // violation object const load = useCallback(() => { setLoading(true); @@ -96,9 +115,9 @@ export default function EmployeeModal({ employeeId, onClose }) { const handleDownloadPdf = async (violId, empName, date) => { const response = await axios.get(`/api/violations/${violId}/pdf`, { responseType: 'blob' }); - const url = window.URL.createObjectURL(new Blob([response.data], { type: 'application/pdf' })); + const url = window.URL.createObjectURL(new Blob([response.data], { type: 'application/pdf' })); const link = document.createElement('a'); - link.href = url; + link.href = url; link.download = `CPAS_${(empName || '').replace(/[^a-z0-9]/gi, '_')}_${date}.pdf`; document.body.appendChild(link); link.click(); @@ -119,39 +138,42 @@ export default function EmployeeModal({ employeeId, onClose }) { }; const handleNegate = async ({ resolution_type, details, resolved_by }) => { - await axios.patch(`/api/violations/${negating.id}/negate`, { - resolution_type, details, resolved_by, - }); + await axios.patch(`/api/violations/${negating.id}/negate`, { resolution_type, details, resolved_by }); setNegating(null); setConfirmDel(null); load(); }; - const tier = score ? getTier(score.active_points) : null; - const active = violations.filter((v) => !v.negated); + const tier = score ? getTier(score.active_points) : null; + const active = violations.filter((v) => !v.negated); const negated = violations.filter((v) => v.negated); - // FIX: overlay click only closes if clicking the backdrop itself, NOT children - const handleOverlayClick = (e) => { - if (e.target === e.currentTarget) onClose(); - }; + const handleOverlayClick = (e) => { if (e.target === e.currentTarget) onClose(); }; return ( - // FIX: panel uses onClick stopPropagation to prevent bubbling to overlay
e.stopPropagation()}> {/* ── Header ── */}
- -
- {employee ? employee.name : 'Employee'} -
- {employee && ( -
- {employee.department} {employee.supervisor && `· Supervisor: ${employee.supervisor}`} +
+
+
+ {employee ? employee.name : 'Employee'} +
+ {employee && ( +
+ {employee.department} {employee.supervisor && `· Supervisor: ${employee.supervisor}`} +
+ )} + {employee && ( + + )}
- )} + +
{/* ── Body ── */} @@ -190,7 +212,7 @@ export default function EmployeeModal({ employeeId, onClose }) { {/* ── Active Violations ── */}
Active Violations
{active.length === 0 ? ( -
+
No active violations on record.
) : ( @@ -208,17 +230,22 @@ export default function EmployeeModal({ employeeId, onClose }) { {v.incident_date} -
{v.violation_name}
+
+ {v.violation_name} + {v.amendment_count > 0 && ( + {v.amendment_count} edit{v.amendment_count !== 1 ? 's' : ''} + )} +
{v.category}
{v.details && ( -
- {v.details} -
+
{v.details}
)} {v.points} - {/* FIX: All buttons use e.stopPropagation() to prevent overlay close */} +
)} {v.resolved_by && ( -
- by {v.resolved_by} -
+
by {v.resolved_by}
)} @@ -349,7 +374,7 @@ export default function EmployeeModal({ employeeId, onClose }) {
- {/* FIX: NegateModal rendered OUTSIDE the panel so it sits at root z-index:2000 */} + {/* Modals rendered outside panel to avoid z-index nesting issues */} {negating && ( setNegating(null)} /> )} + {editingEmp && employee && ( + setEditingEmp(false)} + onSaved={load} + /> + )} + {amending && ( + setAmending(null)} + onSaved={load} + /> + )}
); }