Problem
Members viewing a workspace detail page cannot see real-time occupancy — the count only updates on page refresh. There is no live connection to the backend WebSocket.
Proposed Solution
Create frontend/cntr/LiveOccupancy/LiveOccupancyWidget.tsx and frontend/cntr/LiveOccupancy/useWebSocket.ts. The hook connects to a WebSocket URL and exposes { data, status: 'connecting' | 'open' | 'closed' }. The widget listens for occupancy_update events. Props: wsUrl: string, capacity: number. All implementation must live inside frontend/cntr/.
Acceptance Criteria
Problem
Members viewing a workspace detail page cannot see real-time occupancy — the count only updates on page refresh. There is no live connection to the backend WebSocket.
Proposed Solution
Create
frontend/cntr/LiveOccupancy/LiveOccupancyWidget.tsxandfrontend/cntr/LiveOccupancy/useWebSocket.ts. The hook connects to a WebSocket URL and exposes{ data, status: 'connecting' | 'open' | 'closed' }. The widget listens foroccupancy_updateevents. Props:wsUrl: string,capacity: number. All implementation must live insidefrontend/cntr/.Acceptance Criteria
LiveOccupancyWidget.tsxanduseWebSocket.tsinfrontend/cntr/LiveOccupancy/"{current} / {capacity} occupied"connectingstateuseWebSocketcallsws.close()on component unmountLiveOccupancyWidget.test.tsxwith a mocked WebSocket