Collapse Departments and Assignees pickers in the event form
Both lists grow with staff/department count and were always fully expanded — matches the History section's existing collapsible pattern, showing a summary of the current selection when closed.
This commit is contained in:
parent
d6542f4503
commit
056680999c
1 changed files with 64 additions and 36 deletions
|
|
@ -64,6 +64,8 @@ export default function EventForm({ eventId, initialDate, occurrenceStart, scope
|
|||
|
||||
const [historyOpen, setHistoryOpen] = useState(false)
|
||||
const [history, setHistory] = useState<ActivityLogEntry[] | null>(null)
|
||||
const [deptsOpen, setDeptsOpen] = useState(false)
|
||||
const [assigneesOpen, setAssigneesOpen] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
fetchCalendars().then(setCalendars).catch(() => {})
|
||||
|
|
@ -303,51 +305,77 @@ export default function EventForm({ eventId, initialDate, occurrenceStart, scope
|
|||
)}
|
||||
|
||||
<div className="field">
|
||||
<label>Departments</label>
|
||||
{editingOccurrence ? (
|
||||
<div className="chip-bar" style={{ margin: 0 }}>
|
||||
{selectedDepts.length === 0 && <span className="field-hint">None</span>}
|
||||
{selectedDepts.map(d => <span key={d.id} className="badge badge-outline">{d.name}</span>)}
|
||||
</div>
|
||||
<>
|
||||
<label>Departments</label>
|
||||
<div className="chip-bar" style={{ margin: 0 }}>
|
||||
{selectedDepts.length === 0 && <span className="field-hint">None</span>}
|
||||
{selectedDepts.map(d => <span key={d.id} className="badge badge-outline">{d.name}</span>)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||
{departments.map(dept => (
|
||||
<label key={dept.id} className="field-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedDepts.some(d => d.id === dept.id)}
|
||||
onChange={() => toggleDept(dept)}
|
||||
disabled={!permitted}
|
||||
/>
|
||||
{dept.name}
|
||||
</label>
|
||||
))}
|
||||
{departments.length === 0 && <span className="field-hint">No departments configured.</span>}
|
||||
<div className="filter-section" style={{ marginBottom: 0 }}>
|
||||
<div className="filter-section-header" onClick={() => setDeptsOpen(v => !v)}>
|
||||
<span className="filter-section-label">Departments</span>
|
||||
<span className={`filter-section-summary${selectedDepts.length === 0 ? ' muted' : ''}`}>
|
||||
{selectedDepts.length === 0 ? 'None selected' : selectedDepts.map(d => d.name).join(', ')}
|
||||
</span>
|
||||
<ChevronDown size={14} strokeWidth={1.75} className={`filter-section-chevron${deptsOpen ? ' open' : ''}`} />
|
||||
</div>
|
||||
{deptsOpen && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginTop: 8 }}>
|
||||
{departments.map(dept => (
|
||||
<label key={dept.id} className="field-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedDepts.some(d => d.id === dept.id)}
|
||||
onChange={() => toggleDept(dept)}
|
||||
disabled={!permitted}
|
||||
/>
|
||||
{dept.name}
|
||||
</label>
|
||||
))}
|
||||
{departments.length === 0 && <span className="field-hint">No departments configured.</span>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label>Assignees</label>
|
||||
{editingOccurrence ? (
|
||||
<div className="chip-bar" style={{ margin: 0 }}>
|
||||
{selectedAssignees.length === 0 && <span className="field-hint">None</span>}
|
||||
{selectedAssignees.map(a => <span key={a.email} className="badge badge-outline">{a.name}</span>)}
|
||||
</div>
|
||||
<>
|
||||
<label>Assignees</label>
|
||||
<div className="chip-bar" style={{ margin: 0 }}>
|
||||
{selectedAssignees.length === 0 && <span className="field-hint">None</span>}
|
||||
{selectedAssignees.map(a => <span key={a.email} className="badge badge-outline">{a.name}</span>)}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||
{users.map(u => (
|
||||
<label key={u.email} className="field-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedAssignees.some(a => a.email === u.email)}
|
||||
onChange={() => toggleAssignee(u)}
|
||||
disabled={!permitted}
|
||||
/>
|
||||
{u.name}
|
||||
</label>
|
||||
))}
|
||||
{users.length === 0 && <span className="field-hint">No staff available.</span>}
|
||||
<div className="filter-section" style={{ marginBottom: 0 }}>
|
||||
<div className="filter-section-header" onClick={() => setAssigneesOpen(v => !v)}>
|
||||
<span className="filter-section-label">Assignees</span>
|
||||
<span className={`filter-section-summary${selectedAssignees.length === 0 ? ' muted' : ''}`}>
|
||||
{selectedAssignees.length === 0 ? 'None selected' : selectedAssignees.map(a => a.name).join(', ')}
|
||||
</span>
|
||||
<ChevronDown size={14} strokeWidth={1.75} className={`filter-section-chevron${assigneesOpen ? ' open' : ''}`} />
|
||||
</div>
|
||||
{assigneesOpen && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginTop: 8 }}>
|
||||
{users.map(u => (
|
||||
<label key={u.email} className="field-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedAssignees.some(a => a.email === u.email)}
|
||||
onChange={() => toggleAssignee(u)}
|
||||
disabled={!permitted}
|
||||
/>
|
||||
{u.name}
|
||||
</label>
|
||||
))}
|
||||
{users.length === 0 && <span className="field-hint">No staff available.</span>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue