AdminDepartments: light theme, group by location, location_name support
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f3d46b8c80
commit
1dcf8bfbcb
1 changed files with 68 additions and 42 deletions
|
|
@ -6,6 +6,8 @@ interface WfDept {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
staff_count: number
|
staff_count: number
|
||||||
|
location_id: string | null
|
||||||
|
location_name: string | null
|
||||||
mapped_role_id: number | null
|
mapped_role_id: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,6 +82,16 @@ export function AdminDepartments({ user }: { user: User }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Group departments by location
|
||||||
|
const locations = Array.from(new Set(depts.map(d => d.location_name ?? ''))).filter(Boolean)
|
||||||
|
const hasMultipleLocations = locations.length > 1
|
||||||
|
const grouped: Record<string, WfDept[]> = {}
|
||||||
|
for (const d of depts) {
|
||||||
|
const key = d.location_name ?? ''
|
||||||
|
if (!grouped[key]) grouped[key] = []
|
||||||
|
grouped[key].push(d)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', height: '100dvh' }}>
|
<div style={{ display: 'flex', height: '100dvh' }}>
|
||||||
<Sidebar user={user} />
|
<Sidebar user={user} />
|
||||||
|
|
@ -96,34 +108,45 @@ export function AdminDepartments({ user }: { user: User }) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{syncResult && (
|
<p style={{ fontSize: '0.82rem', color: 'var(--text-mid)', marginBottom: syncResult ? '0.5rem' : '1.25rem' }}>
|
||||||
<div style={{ fontSize: '0.82rem', color: 'var(--text-muted)', marginBottom: '1rem',
|
|
||||||
background: 'var(--surface)', borderRadius: '6px', padding: '0.6rem 0.875rem',
|
|
||||||
border: '1px solid var(--surface-2)' }}>
|
|
||||||
{syncResult}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<p style={{ fontSize: '0.82rem', color: 'var(--text-muted)', marginBottom: '1.25rem' }}>
|
|
||||||
Map Workforce departments to roles. Self-registering employees will automatically
|
Map Workforce departments to roles. Self-registering employees will automatically
|
||||||
receive the role mapped to their department.
|
receive the role mapped to their department.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{error && <p style={{ color: 'var(--danger)', fontSize: '0.85rem', marginBottom: '1rem' }}>{error}</p>}
|
{syncResult && (
|
||||||
|
<div style={{ fontSize: '0.82rem', color: 'var(--text-mid)', marginBottom: '1rem',
|
||||||
|
background: 'var(--card-bg)', borderRadius: '6px', padding: '0.6rem 0.875rem',
|
||||||
|
border: '1px solid var(--card-border)' }}>
|
||||||
|
{syncResult}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{error && <p style={{ color: '#dc2626', fontSize: '0.85rem', marginBottom: '1rem' }}>{error}</p>}
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<p style={{ color: 'var(--text-muted)', fontSize: '0.875rem' }}>Loading departments…</p>
|
<p style={{ color: 'var(--text-mid)', fontSize: '0.875rem' }}>Loading departments…</p>
|
||||||
) : (
|
) : (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: hasMultipleLocations ? '1.5rem' : '0.5rem' }}>
|
||||||
|
{Object.entries(grouped).map(([location, locationDepts]) => (
|
||||||
|
<div key={location || 'default'}>
|
||||||
|
{hasMultipleLocations && location && (
|
||||||
|
<div style={{ fontSize: '0.72rem', fontWeight: 700, textTransform: 'uppercase',
|
||||||
|
letterSpacing: '0.06em', color: 'var(--text-mid)', marginBottom: '0.5rem',
|
||||||
|
paddingBottom: '0.25rem', borderBottom: '1px solid var(--card-border)' }}>
|
||||||
|
{location}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
|
||||||
{depts.map(dept => (
|
{locationDepts.map(dept => (
|
||||||
<div key={dept.id} style={{
|
<div key={dept.id} style={{
|
||||||
background: 'var(--surface)', borderRadius: '8px',
|
background: 'var(--card-bg)', borderRadius: '8px',
|
||||||
padding: '0.75rem 1rem', border: '1px solid var(--surface-2)',
|
padding: '0.75rem 1rem', border: '1px solid var(--card-border)',
|
||||||
|
boxShadow: 'var(--shadow-sm)',
|
||||||
display: 'flex', alignItems: 'center', gap: '1rem', flexWrap: 'wrap',
|
display: 'flex', alignItems: 'center', gap: '1rem', flexWrap: 'wrap',
|
||||||
}}>
|
}}>
|
||||||
<div style={{ flex: 1, minWidth: '140px' }}>
|
<div style={{ flex: 1, minWidth: '140px' }}>
|
||||||
<div style={{ fontWeight: 600, fontSize: '0.875rem' }}>{dept.name}</div>
|
<div style={{ fontWeight: 600, fontSize: '0.875rem' }}>{dept.name}</div>
|
||||||
<div style={{ fontSize: '0.75rem', color: 'var(--text-muted)' }}>
|
<div style={{ fontSize: '0.75rem', color: 'var(--text-mid)' }}>
|
||||||
{dept.staff_count} staff
|
{dept.staff_count} staff
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -133,8 +156,8 @@ export function AdminDepartments({ user }: { user: User }) {
|
||||||
...m, [dept.id]: e.target.value ? Number(e.target.value) : null
|
...m, [dept.id]: e.target.value ? Number(e.target.value) : null
|
||||||
}))}
|
}))}
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--navy-dark)', border: '1px solid var(--surface-2)',
|
background: 'var(--body-bg)', border: '1px solid var(--card-border)',
|
||||||
borderRadius: '6px', color: 'var(--text)', padding: '0.4rem 0.6rem',
|
borderRadius: '6px', color: 'var(--text-dark)', padding: '0.4rem 0.6rem',
|
||||||
fontSize: '0.82rem', minWidth: '160px',
|
fontSize: '0.82rem', minWidth: '160px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -146,6 +169,9 @@ export function AdminDepartments({ user }: { user: User }) {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -153,10 +179,10 @@ export function AdminDepartments({ user }: { user: User }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const goldBtn: React.CSSProperties = {
|
const goldBtn: React.CSSProperties = {
|
||||||
background: 'var(--gold)', color: 'var(--navy-dark)', border: 'none',
|
background: 'var(--navy)', color: '#fff', border: 'none',
|
||||||
borderRadius: '6px', padding: '0.5rem 1rem', fontSize: '0.875rem', fontWeight: 600,
|
borderRadius: '6px', padding: '0.5rem 1rem', fontSize: '0.875rem', fontWeight: 600, cursor: 'pointer',
|
||||||
}
|
}
|
||||||
const mutedBtn: React.CSSProperties = {
|
const mutedBtn: React.CSSProperties = {
|
||||||
background: 'var(--surface-2)', color: 'var(--text-muted)', border: '1px solid var(--surface-2)',
|
background: 'var(--body-bg)', color: 'var(--text-mid)', border: '1px solid var(--card-border)',
|
||||||
borderRadius: '6px', padding: '0.5rem 1rem', fontSize: '0.875rem',
|
borderRadius: '6px', padding: '0.5rem 1rem', fontSize: '0.875rem', cursor: 'pointer',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue