Merge pull request 'Upload files to "client/src/components"' (#18) from p4-hotfixes into master
Reviewed-on: #18
This commit was merged in pull request #18.
This commit is contained in:
@@ -77,6 +77,10 @@ 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}>
|
||||||
<div>
|
<div>
|
||||||
@@ -84,7 +88,12 @@ export default function Dashboard() {
|
|||||||
<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={{ display: 'flex', gap: '10px', alignItems: 'center' }}>
|
||||||
<input style={s.search} placeholder="Search name, dept, supervisor…" value={search} onChange={e => setSearch(e.target.value)} />
|
<input
|
||||||
|
style={s.search}
|
||||||
|
placeholder="Search name, dept, supervisor…"
|
||||||
|
value={search}
|
||||||
|
onChange={e => setSearch(e.target.value)}
|
||||||
|
/>
|
||||||
<button style={s.refreshBtn} onClick={load}>↻ Refresh</button>
|
<button style={s.refreshBtn} onClick={load}>↻ Refresh</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -129,17 +138,26 @@ export default function Dashboard() {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{filtered.length === 0 && (
|
{filtered.length === 0 && (
|
||||||
<tr><td colSpan={7} style={{ ...s.td, textAlign: 'center', ...s.zeroRow }}>No employees found.</td></tr>
|
<tr>
|
||||||
|
<td colSpan={7} style={{ ...s.td, textAlign: 'center', ...s.zeroRow }}>
|
||||||
|
No employees found.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
)}
|
)}
|
||||||
{filtered.map((emp, i) => {
|
{filtered.map((emp, i) => {
|
||||||
const risk = isAtRisk(emp.active_points);
|
const risk = isAtRisk(emp.active_points);
|
||||||
const tier = getTier(emp.active_points);
|
const tier = getTier(emp.active_points);
|
||||||
const boundary = nextTierBoundary(emp.active_points);
|
const boundary = nextTierBoundary(emp.active_points);
|
||||||
return (
|
return (
|
||||||
<tr key={emp.id} style={{ background: risk ? '#181200' : i % 2 === 0 ? '#111217' : '#151622' }}>
|
<tr
|
||||||
|
key={emp.id}
|
||||||
|
style={{ background: risk ? '#181200' : i % 2 === 0 ? '#111217' : '#151622' }}
|
||||||
|
>
|
||||||
<td style={{ ...s.td, color: '#77798a', fontSize: '12px' }}>{i + 1}</td>
|
<td style={{ ...s.td, color: '#77798a', fontSize: '12px' }}>{i + 1}</td>
|
||||||
<td style={s.td}>
|
<td style={s.td}>
|
||||||
<button style={s.nameBtn} onClick={() => setSelectedId(emp.id)}>{emp.name}</button>
|
<button style={s.nameBtn} onClick={() => setSelectedId(emp.id)}>
|
||||||
|
{emp.name}
|
||||||
|
</button>
|
||||||
{risk && (
|
{risk && (
|
||||||
<span style={s.atRiskBadge}>
|
<span style={s.atRiskBadge}>
|
||||||
⚠ {boundary - emp.active_points} pt{boundary - emp.active_points > 1 ? 's' : ''} to {getTier(boundary).label.split('—')[0].trim()}
|
⚠ {boundary - emp.active_points} pt{boundary - emp.active_points > 1 ? 's' : ''} to {getTier(boundary).label.split('—')[0].trim()}
|
||||||
@@ -149,7 +167,9 @@ export default function Dashboard() {
|
|||||||
<td style={{ ...s.td, color: '#c0c2d6' }}>{emp.department || '—'}</td>
|
<td style={{ ...s.td, color: '#c0c2d6' }}>{emp.department || '—'}</td>
|
||||||
<td style={{ ...s.td, color: '#c0c2d6' }}>{emp.supervisor || '—'}</td>
|
<td style={{ ...s.td, color: '#c0c2d6' }}>{emp.supervisor || '—'}</td>
|
||||||
<td style={s.td}><CpasBadge points={emp.active_points} /></td>
|
<td style={s.td}><CpasBadge points={emp.active_points} /></td>
|
||||||
<td style={{ ...s.td, fontWeight: 700, color: tier.color, fontSize: '16px' }}>{emp.active_points}</td>
|
<td style={{ ...s.td, fontWeight: 700, color: tier.color, fontSize: '16px' }}>
|
||||||
|
{emp.active_points}
|
||||||
|
</td>
|
||||||
<td style={{ ...s.td, color: '#c0c2d6' }}>{emp.violation_count}</td>
|
<td style={{ ...s.td, color: '#c0c2d6' }}>{emp.violation_count}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
@@ -157,13 +177,17 @@ export default function Dashboard() {
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
)}
|
)}
|
||||||
|
</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(); }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user