feat: add Audit Log button to Dashboard toolbar

This commit is contained in:
2026-03-07 09:26:33 -06:00
parent 7ee76468c4
commit 970bc0efea

View File

@@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import axios from 'axios'; import axios from 'axios';
import CpasBadge, { getTier } from './CpasBadge'; import CpasBadge, { getTier } from './CpasBadge';
import EmployeeModal from './EmployeeModal'; import EmployeeModal from './EmployeeModal';
import AuditLog from './AuditLog';
const AT_RISK_THRESHOLD = 2; const AT_RISK_THRESHOLD = 2;
@@ -43,7 +44,9 @@ const s = {
nameBtn: { background: 'none', border: 'none', cursor: 'pointer', fontWeight: 600, color: '#d4af37', fontSize: '14px', padding: 0, textDecoration: 'underline dotted' }, nameBtn: { background: 'none', border: 'none', cursor: 'pointer', fontWeight: 600, color: '#d4af37', fontSize: '14px', padding: 0, textDecoration: 'underline dotted' },
atRiskBadge: { display: 'inline-block', marginLeft: '8px', padding: '2px 8px', borderRadius: '10px', fontSize: '10px', fontWeight: 700, background: '#3b2e00', color: '#ffd666', border: '1px solid #d4af37', verticalAlign: 'middle' }, atRiskBadge: { display: 'inline-block', marginLeft: '8px', padding: '2px 8px', borderRadius: '10px', fontSize: '10px', fontWeight: 700, background: '#3b2e00', color: '#ffd666', border: '1px solid #d4af37', verticalAlign: 'middle' },
zeroRow: { color: '#77798a', fontStyle: 'italic', fontSize: '12px' }, zeroRow: { color: '#77798a', fontStyle: 'italic', fontSize: '12px' },
toolbarRight: { display: 'flex', gap: '10px', alignItems: 'center' },
refreshBtn: { padding: '9px 18px', background: '#d4af37', color: '#000', border: 'none', borderRadius: '6px', cursor: 'pointer', fontWeight: 600, fontSize: '13px' }, refreshBtn: { padding: '9px 18px', background: '#d4af37', color: '#000', border: 'none', borderRadius: '6px', cursor: 'pointer', fontWeight: 600, fontSize: '13px' },
auditBtn: { padding: '9px 18px', background: 'none', color: '#9ca0b8', border: '1px solid #2a2b3a', borderRadius: '6px', cursor: 'pointer', fontWeight: 600, fontSize: '13px' },
}; };
export default function Dashboard() { export default function Dashboard() {
@@ -51,6 +54,7 @@ export default function Dashboard() {
const [filtered, setFiltered] = useState([]); const [filtered, setFiltered] = useState([]);
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const [selectedId, setSelectedId] = useState(null); const [selectedId, setSelectedId] = useState(null);
const [showAudit, setShowAudit] = useState(false);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const load = useCallback(() => { const load = useCallback(() => {
@@ -77,9 +81,6 @@ export default function Dashboard() {
const maxPoints = employees.reduce((m, e) => Math.max(m, e.active_points), 0); const maxPoints = employees.reduce((m, e) => Math.max(m, e.active_points), 0);
return ( return (
// FIX: Fragment wraps both s.wrap AND EmployeeModal so the modal is
// outside the s.wrap div — React synthetic events will no longer bubble
// from inside the modal up through the Dashboard's DOM tree.
<> <>
<div style={s.wrap}> <div style={s.wrap}>
<div style={s.header}> <div style={s.header}>
@@ -87,13 +88,14 @@ export default function Dashboard() {
<div style={s.title}>Company Dashboard</div> <div style={s.title}>Company Dashboard</div>
<div style={s.subtitle}>Click any employee name to view their full profile</div> <div style={s.subtitle}>Click any employee name to view their full profile</div>
</div> </div>
<div style={{ display: 'flex', gap: '10px', alignItems: 'center' }}> <div style={s.toolbarRight}>
<input <input
style={s.search} style={s.search}
placeholder="Search name, dept, supervisor…" placeholder="Search name, dept, supervisor…"
value={search} value={search}
onChange={e => setSearch(e.target.value)} onChange={e => setSearch(e.target.value)}
/> />
<button style={s.auditBtn} onClick={() => setShowAudit(true)}>📋 Audit Log</button>
<button style={s.refreshBtn} onClick={load}> Refresh</button> <button style={s.refreshBtn} onClick={load}> Refresh</button>
</div> </div>
</div> </div>
@@ -179,15 +181,13 @@ export default function Dashboard() {
)} )}
</div> </div>
{/* FIX: EmployeeModal is now OUTSIDE <div style={s.wrap}>.
React synthetic events no longer bubble from modal buttons
up through Dashboard's component tree. */}
{selectedId && ( {selectedId && (
<EmployeeModal <EmployeeModal
employeeId={selectedId} employeeId={selectedId}
onClose={() => { setSelectedId(null); load(); }} onClose={() => { setSelectedId(null); load(); }}
/> />
)} )}
{showAudit && <AuditLog onClose={() => setShowAudit(false)} />}
</> </>
); );
} }