Show occupancy badges on normal view for bedroom-type tasks

Occupied/departing/arriving badges previously only appeared in rooms-view.
Now bedroom-type tasks (those with a newbook_site_id) show them on the
normal view too, plus a new Unoccupied badge when none apply. Normal view
drops the grey-out/dim treatment and conveys state via badge only; the
dimming stays exclusive to rooms-view.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-10-01 14:18:03 +00:00
parent d0ff70eb86
commit 42b5bd7d9e

View file

@ -102,8 +102,9 @@ export default function Summary() {
status: OPEN_STATUSES.join(','),
assigned_to: mineOnly ? user.email : undefined,
})
// When rooms-view is on, also fetch live occupancy to mark occupied tasks
const occFetch = roomsView ? fetchOccupancy().catch(() => null) : Promise.resolve(null)
// Always fetch live occupancy — bedroom-type tasks show occupancy badges on
// every view, not just the rooms-view filter.
const occFetch = fetchOccupancy().catch(() => null)
Promise.all([taskFetch, occFetch])
.then(([t, occ]) => {
@ -115,7 +116,7 @@ export default function Summary() {
})
.catch(err => setError(err.message))
.finally(() => setLoading(false))
}, [mineOnly, roomsView, user.email])
}, [mineOnly, user.email])
useEffect(() => { load() }, [load])
useEffect(() => {
@ -346,20 +347,25 @@ export default function Summary() {
{(() => {
const renderTask = (t: Task) => {
// Bedroom-type locations are the ones synced from NewBook (they carry a
// site id) — manual Rooms-category locations like corridors/stores never
// get an occupancy badge, in either view.
const sid = t.newbook_site_id ? String(t.newbook_site_id) : null
const isOccupied = roomsView && !!sid && occupiedSiteIds.has(sid)
const isDeparting = roomsView && !!sid && !isOccupied && departingSiteIds.has(sid)
const isOccupied = !!sid && occupiedSiteIds.has(sid)
const isDeparting = !!sid && !isOccupied && departingSiteIds.has(sid)
// Not exclusive with isDeparting — a departing room can also have a same-day
// incoming booking (back-to-back turnover), and both badges should show.
const isArriving = roomsView && !!sid && !isOccupied && arrivingSiteIds.has(sid)
const isArriving = !!sid && !isOccupied && arrivingSiteIds.has(sid)
const isUnoccupied = !!sid && !isOccupied && !isDeparting && !isArriving
return (
<div
key={t.id}
className={`card task-card ${t.priority === 'urgent' ? 'urgent' : t.priority === 'high' ? 'high' : ''} ${t.unusable ? 'unusable' : ''}`}
// Occupied (stayover) rooms grey out hard — not accessible today. Departing
// rooms are lightly dimmed only: guest is still in there right now, but the
// room frees up later today so it's worth flagging rather than hiding.
style={isOccupied ? { opacity: 0.5, filter: 'grayscale(0.3)' } : isDeparting ? { opacity: 0.8 } : undefined}
// Occupied (stayover) rooms grey out hard and departing rooms dim lightly,
// but only in rooms-view — that's the filtered "what can I access today"
// view. On the normal view the same occupancy state is conveyed with
// badges only, no dimming.
style={roomsView ? (isOccupied ? { opacity: 0.5, filter: 'grayscale(0.3)' } : isDeparting ? { opacity: 0.8 } : undefined) : undefined}
onClick={() => setOpenTask(t.id)}
>
<div className="task-card-main">
@ -368,6 +374,7 @@ export default function Summary() {
{isOccupied && <span className="badge badge-outline"><BedDouble size={10} strokeWidth={1.75} /> Occupied</span>}
{isDeparting && <span className="badge" style={{ background: '#ede9fe', color: '#6d28d9', border: '1px solid #c4b5fd' }}><LogOut size={10} strokeWidth={1.75} /> Departing</span>}
{isArriving && <span className="badge" style={{ background: '#fef3c7', color: '#92400e', border: '1px solid #fcd34d' }}><BedDouble size={10} strokeWidth={1.75} /> Arrival today</span>}
{!roomsView && isUnoccupied && <span className="badge" style={{ background: '#dcfce7', color: '#166534', border: '1px solid #86efac' }}><BedDouble size={10} strokeWidth={1.75} /> Unoccupied</span>}
{t.unusable && <UnusableBadge />}
{t.template_id && <span className="badge badge-outline">Recurring</span>}
</div>