From 63a35481f98940a21f717c50b5d4ba4ab5e8f31f Mon Sep 17 00:00:00 2001 From: pataniaeli Date: Tue, 25 Aug 2026 17:48:28 -0400 Subject: [PATCH 1/6] Bump version to 1.12.4 Co-Authored-By: Claude Sonnet 5 --- app/(dashboard)/layout.tsx | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/(dashboard)/layout.tsx b/app/(dashboard)/layout.tsx index 7a20f3b..4ada843 100644 --- a/app/(dashboard)/layout.tsx +++ b/app/(dashboard)/layout.tsx @@ -244,7 +244,7 @@ export default function DashboardLayout({ Chambers

NU Student Gov. Association

-

v1.12.3

+

v1.12.4

{userName && (

{getGreeting()},
{userName}

diff --git a/package-lock.json b/package-lock.json index c8af67d..ca4e55d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "chambers", - "version": "1.12.3", + "version": "1.12.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "chambers", - "version": "1.12.3", + "version": "1.12.4", "dependencies": { "@supabase/ssr": "^0.9.0", "@supabase/supabase-js": "^2.99.1", diff --git a/package.json b/package.json index b6ae32d..73f7c3c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chambers", - "version": "1.12.3", + "version": "1.12.4", "private": true, "scripts": { "dev": "next dev", From 22205d7ac903eb29081a94aef584be3dd3108df2 Mon Sep 17 00:00:00 2001 From: pataniaeli Date: Tue, 25 Aug 2026 17:49:19 -0400 Subject: [PATCH 2/6] Fix #10: make Administrator tab bar horizontally scrollable on mobile The main content area has overflow-x-hidden, and the tab row had no scroll container of its own, so tabs past the viewport edge (including Advanced Settings) were unreachable on mobile. Co-Authored-By: Claude Sonnet 5 --- app/(dashboard)/administrator/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/(dashboard)/administrator/page.tsx b/app/(dashboard)/administrator/page.tsx index c56a8fc..5830735 100644 --- a/app/(dashboard)/administrator/page.tsx +++ b/app/(dashboard)/administrator/page.tsx @@ -28,12 +28,12 @@ export default function AdministratorPage() {

Administrator

-
+
{(['Bookings', 'SGA Spaces', 'Cancellations', 'Requests', 'Advanced Settings'] as Tab[]).map(tab => ( + +

{monthLabel}

+
+ +
+ +
+ {WEEKDAY_LABELS.map(label => ( +
+ {label} +
+ ))} + {cells.map((cell, i) => { + if (!cell) return
+ const dayBookings = byDate.get(cell.dateKey) ?? [] + const isToday = cell.dateKey === todayKey() + const isSelected = cell.dateKey === selectedDate + return ( + + ) + })} +
+ + {selectedDate && ( +
+

+ {new Date(selectedDate + 'T00:00:00').toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })} +

+ {selectedBookings.length === 0 ? ( +

No bookings on this day.

+ ) : ( +
+ {selectedBookings.map(b => ( +
onSelect(b)} className="flex items-center gap-4 px-5 py-3.5 hover:bg-[#1a4d8a] transition-colors cursor-pointer"> +
+
+

{b.location}

+

{b.bodyName} · {formatTime(b.startTime)} – {formatTime(b.endTime)}

+
+ {b.status} +
+ ))} +
+ )} +
+ )} +
+ ) +} diff --git a/app/(dashboard)/my-rooms/page.tsx b/app/(dashboard)/my-rooms/page.tsx index 962a055..36db458 100644 --- a/app/(dashboard)/my-rooms/page.tsx +++ b/app/(dashboard)/my-rooms/page.tsx @@ -1,11 +1,23 @@ 'use client' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import CancelModal from './cancel-modal' import RevisionModal from './revision-modal' import BookingDetailModal from './booking-detail-modal' import NotificationBell from './notification-bell' +import CalendarView from './calendar-view' import { Skeleton } from '@/app/_components/skeleton' +import { + type FlatBooking, + SENATE_TYPES, + statusColors, + statusBarColors, + statusTextColors, + senateTypeBadgeColors, + DEFAULT_SENATE_BADGE, + formatTime, + formatDate, +} from './shared' function MyRoomsSkeleton() { return ( @@ -57,78 +69,9 @@ function MyRoomsSkeleton() { } type Filter = 1 | 3 | 7 +type ViewMode = 'list' | 'calendar' -const statusColors: Record = { - 'Reserved': 'bg-[#0f3d20] border-[#22c55e]', - 'Alternate Room': 'bg-[#0e2f4f] border-[#4285f4]', - 'Alternate Time': 'bg-[#0e2f4f] border-[#4285f4]', - 'Waitlisted': 'bg-[#3d0f0f] border-[#ef4444]', - 'Unavailable': 'bg-[#3d0f0f] border-[#ef4444]', - 'Pending Cancellation': 'bg-[#3d2200] border-[#f97316]', - 'Cancelled': 'bg-[#2a1042] border-[#a855f7]', - 'Virtual': 'bg-[#062f3b] border-[#06b6d4]', - 'Missed': 'bg-[#1a1a2e] border-[#a78bfa]', - 'Repurposed': 'bg-[#1a1a1a] border-white', - 'Tentative': 'bg-[#2d2800] border-[#fef08a]', -} - -const statusBarColors: Record = { - 'Reserved': 'bg-[#22c55e]', - 'Alternate Room': 'bg-[#4285f4]', - 'Alternate Time': 'bg-[#4285f4]', - 'Waitlisted': 'bg-[#ef4444]', - 'Unavailable': 'bg-[#ef4444]', - 'Pending Cancellation': 'bg-[#f97316]', - 'Cancelled': 'bg-[#a855f7]', - 'Virtual': 'bg-[#06b6d4]', - 'Missed': 'bg-[#a78bfa]', - 'Repurposed': 'bg-white', - 'Tentative': 'bg-[#fef08a]', -} - -const statusTextColors: Record = { - 'Reserved': 'text-[#4ade80]', - 'Alternate Room': 'text-[#4285f4]', - 'Alternate Time': 'text-[#4285f4]', - 'Waitlisted': 'text-[#f87171]', - 'Unavailable': 'text-[#f87171]', - 'Pending Cancellation': 'text-[#fb923c]', - 'Cancelled': 'text-[#c084fc]', - 'Virtual': 'text-[#22d3ee]', - 'Missed': 'text-[#a78bfa]', - 'Repurposed': 'text-white', - 'Tentative': 'text-[#fef08a]', -} - -interface FlatBooking { - id: string - bookingId: string //parent booking id - bodyId: string - type: 'One-Time Room' | 'Weekly Room' | 'Tabling' - bodyName: string - purpose: string - location: string - date: string - startTime: string - endTime: string - status: string - reservationCode: string | null - senateType: string | null -} - -function formatTime(time: string) { - const [h, m] = time.split(':') - const hour = parseInt(h) - const ampm = hour >= 12 ? 'PM' : 'AM' - const displayHour = hour % 12 || 12 - return `${displayHour}:${m} ${ampm}` -} - -function formatDate(date: string) { - return new Date(date + 'T00:00:00').toLocaleDateString('en-US', { - weekday: 'short', month: 'short', day: 'numeric' - }) -} +const SENATE_TYPE_FILTER_KEY = 'chambers-senate-type-filter' function isWithinDays(dateStr: string, days: number) { const now = new Date() @@ -144,6 +87,10 @@ export default function MyRoomsPage() { const [loading, setLoading] = useState(true) const [leadershipBodyIds, setLeadershipBodyIds] = useState([]) const [detailBooking, setDetailBooking] = useState(null) + const [viewMode, setViewMode] = useState('list') + const [search, setSearch] = useState('') + const [statusFilter, setStatusFilter] = useState('All') + const [senateTypeFilter, setSenateTypeFilter] = useState>(new Set(SENATE_TYPES)) const [cancellingBooking, setCancellingBooking] = useState<{ id: string type: 'One-Time Room' | 'Weekly Room' | 'Tabling' @@ -162,6 +109,29 @@ export default function MyRoomsPage() { location: string } | null>(null) + useEffect(() => { + try { + const stored = localStorage.getItem(SENATE_TYPE_FILTER_KEY) + if (stored) setSenateTypeFilter(new Set(JSON.parse(stored))) + } catch { + // Ignore malformed/unavailable storage — falls back to showing all types. + } + }, []) + + const toggleSenateType = (type: string) => { + setSenateTypeFilter(prev => { + const next = new Set(prev) + if (next.has(type)) next.delete(type) + else next.add(type) + try { + localStorage.setItem(SENATE_TYPE_FILTER_KEY, JSON.stringify([...next])) + } catch { + // Best-effort persistence only. + } + return next + }) + } + const fetchBookings = async () => { setLoading(true) // /api/my-rooms already resolves the caller's Leadership bodies, so this @@ -251,12 +221,54 @@ export default function MyRoomsPage() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []) - const filteredUpcoming = all.filter(b => isWithinDays(b.date, filter)) + const hasSenateBookings = useMemo(() => all.some(b => b.bodyName === 'Senate'), [all]) + + const passesSenateFilter = (b: FlatBooking) => + b.bodyName !== 'Senate' || !b.senateType || senateTypeFilter.has(b.senateType) + + const filteredUpcoming = all.filter(b => isWithinDays(b.date, filter) && passesSenateFilter(b)) + + const statusOptions = useMemo( + () => ['All', ...Array.from(new Set(all.map(b => b.status))).sort()], + [all] + ) + + const visibleAll = useMemo(() => { + const q = search.trim().toLowerCase() + return all.filter(b => { + if (!passesSenateFilter(b)) return false + if (statusFilter !== 'All' && b.status !== statusFilter) return false + if (q && !(b.location.toLowerCase().includes(q) || b.purpose.toLowerCase().includes(q) || b.bodyName.toLowerCase().includes(q))) return false + return true + }) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [all, search, statusFilter, senateTypeFilter]) + + const filtersActive = search.trim() !== '' || statusFilter !== 'All' if (loading) return return (
+ {hasSenateBookings && ( +
+ Senate Sessions + {SENATE_TYPES.map(t => ( + + ))} +
+ )} + {/* My Upcoming Spaces */}
@@ -298,7 +310,7 @@ export default function MyRoomsPage() {

{formatTime(b.startTime)} – {formatTime(b.endTime)}

{b.senateType && ( - {b.senateType} + {b.senateType} )}
@@ -319,56 +331,109 @@ export default function MyRoomsPage() { {/* All Bookings */}
-

All Bookings

+
+

All Bookings

+
+ {(['list', 'calendar'] as ViewMode[]).map(mode => ( + + ))} +
+
+ {all.length === 0 ? (

No bookings found.

- ) : (() => { - const bodyMap = new Map() - for (const b of all) { - if (!bodyMap.has(b.bodyId)) bodyMap.set(b.bodyId, { bodyName: b.bodyName, bookings: [] }) - bodyMap.get(b.bodyId)!.bookings.push(b) - } - const groups = Array.from(bodyMap.entries()).map(([bodyId, { bodyName, bookings }]) => ({ - bodyId, bodyName, bookings, - isLeadership: leadershipBodyIds.includes(bodyId), - })) - groups.sort((a, b) => { - if (a.isLeadership !== b.isLeadership) return a.isLeadership ? -1 : 1 - return a.bodyName.localeCompare(b.bodyName) - }) - return ( -
- {groups.map(group => ( -
-

- {group.bodyName} - {group.isLeadership && ( - (Leadership) - )} -

-
- {group.bookings.map(b => ( -
setDetailBooking(b)} className="flex items-center gap-4 px-5 py-3.5 hover:bg-[#1a4d8a] transition-colors cursor-pointer"> -
-
-
-

{b.location}

- {b.senateType && ( - {b.senateType} - )} + ) : ( + <> +
+ setSearch(e.target.value)} + placeholder="Search by room, purpose, or body…" + className="flex-1 min-w-[200px] px-3 py-2 rounded-lg bg-[#0e2f4f] border border-[#1e5080] text-sm text-[#f0f6ff] placeholder:text-[#4a6b8a] focus:outline-none focus:border-[#4285f4]" + /> + + {filtersActive && ( + + )} +
+ + {visibleAll.length === 0 ? ( +

No bookings match your filters.

+ ) : viewMode === 'calendar' ? ( + + ) : (() => { + const bodyMap = new Map() + for (const b of visibleAll) { + if (!bodyMap.has(b.bodyId)) bodyMap.set(b.bodyId, { bodyName: b.bodyName, bookings: [] }) + bodyMap.get(b.bodyId)!.bookings.push(b) + } + const groups = Array.from(bodyMap.entries()).map(([bodyId, { bodyName, bookings }]) => ({ + bodyId, bodyName, bookings, + isLeadership: leadershipBodyIds.includes(bodyId), + })) + groups.sort((a, b) => { + if (a.isLeadership !== b.isLeadership) return a.isLeadership ? -1 : 1 + return a.bodyName.localeCompare(b.bodyName) + }) + return ( +
+ {groups.map(group => ( +
+

+ {group.bodyName} + {group.isLeadership && ( + (Leadership) + )} +

+
+ {group.bookings.map(b => ( +
setDetailBooking(b)} className="flex items-center gap-4 px-5 py-3.5 hover:bg-[#1a4d8a] transition-colors cursor-pointer"> +
+
+
+

{b.location}

+ {b.senateType && ( + {b.senateType} + )} +
+

{formatDate(b.date)} · {formatTime(b.startTime)} – {formatTime(b.endTime)}

+
+ {b.type === 'One-Time Room' ? 'One-Time/Multiple Room' : b.type} + {b.status}
-

{formatDate(b.date)} · {formatTime(b.startTime)} – {formatTime(b.endTime)}

-
- {b.type === 'One-Time Room' ? 'One-Time/Multiple Room' : b.type} - {b.status} + ))}
- ))} -
+
+ ))}
- ))} -
- ) - })()} + ) + })()} + + )}
{detailBooking && ( ) -} \ No newline at end of file +} diff --git a/app/(dashboard)/my-rooms/shared.ts b/app/(dashboard)/my-rooms/shared.ts new file mode 100644 index 0000000..fee721c --- /dev/null +++ b/app/(dashboard)/my-rooms/shared.ts @@ -0,0 +1,82 @@ +export interface FlatBooking { + id: string + bookingId: string //parent booking id + bodyId: string + type: 'One-Time Room' | 'Weekly Room' | 'Tabling' + bodyName: string + purpose: string + location: string + date: string + startTime: string + endTime: string + status: string + reservationCode: string | null + senateType: string | null +} + +export const SENATE_TYPES = ['Full Body', 'Weekly', 'Office Hours'] as const + +export const statusColors: Record = { + 'Reserved': 'bg-[#0f3d20] border-[#22c55e]', + 'Alternate Room': 'bg-[#0e2f4f] border-[#4285f4]', + 'Alternate Time': 'bg-[#0e2f4f] border-[#4285f4]', + 'Waitlisted': 'bg-[#3d0f0f] border-[#ef4444]', + 'Unavailable': 'bg-[#3d0f0f] border-[#ef4444]', + 'Pending Cancellation': 'bg-[#3d2200] border-[#f97316]', + 'Cancelled': 'bg-[#2a1042] border-[#a855f7]', + 'Virtual': 'bg-[#062f3b] border-[#06b6d4]', + 'Missed': 'bg-[#1a1a2e] border-[#a78bfa]', + 'Repurposed': 'bg-[#1a1a1a] border-white', + 'Tentative': 'bg-[#2d2800] border-[#fef08a]', +} + +export const statusBarColors: Record = { + 'Reserved': 'bg-[#22c55e]', + 'Alternate Room': 'bg-[#4285f4]', + 'Alternate Time': 'bg-[#4285f4]', + 'Waitlisted': 'bg-[#ef4444]', + 'Unavailable': 'bg-[#ef4444]', + 'Pending Cancellation': 'bg-[#f97316]', + 'Cancelled': 'bg-[#a855f7]', + 'Virtual': 'bg-[#06b6d4]', + 'Missed': 'bg-[#a78bfa]', + 'Repurposed': 'bg-white', + 'Tentative': 'bg-[#fef08a]', +} + +export const statusTextColors: Record = { + 'Reserved': 'text-[#4ade80]', + 'Alternate Room': 'text-[#4285f4]', + 'Alternate Time': 'text-[#4285f4]', + 'Waitlisted': 'text-[#f87171]', + 'Unavailable': 'text-[#f87171]', + 'Pending Cancellation': 'text-[#fb923c]', + 'Cancelled': 'text-[#c084fc]', + 'Virtual': 'text-[#22d3ee]', + 'Missed': 'text-[#a78bfa]', + 'Repurposed': 'text-white', + 'Tentative': 'text-[#fef08a]', +} + +// Muted, tinted pills (matching statusColors' style) instead of a solid block, +// distinct per session type so they stay legible when grouped together. +export const senateTypeBadgeColors: Record = { + 'Full Body': 'bg-[#2a1042] text-[#c084fc] border border-[#a855f7]/40', + 'Weekly': 'bg-[#0e2f4f] text-[#93c5fd] border border-[#4285f4]/40', + 'Office Hours': 'bg-[#062f3b] text-[#22d3ee] border border-[#06b6d4]/40', +} +export const DEFAULT_SENATE_BADGE = 'bg-[#1e3a5f] text-[#93b8d8] border border-[#2d5f8f]/40' + +export function formatTime(time: string) { + const [h, m] = time.split(':') + const hour = parseInt(h) + const ampm = hour >= 12 ? 'PM' : 'AM' + const displayHour = hour % 12 || 12 + return `${displayHour}:${m} ${ampm}` +} + +export function formatDate(date: string) { + return new Date(date + 'T00:00:00').toLocaleDateString('en-US', { + weekday: 'short', month: 'short', day: 'numeric' + }) +} From d35e3ea2e78c509a01364895ca4c2a65770b2c4e Mon Sep 17 00:00:00 2001 From: pataniaeli Date: Tue, 25 Aug 2026 18:13:57 -0400 Subject: [PATCH 5/6] Address PR feedback: calendar as default, team labels, Senate prefs in Settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Calendar is now the default My Rooms view instead of the list. - Calendar entries (day cells and the expanded day panel) show the booking's team, not the room — the room stays as secondary detail. - The Senate session-type filter moved out of My Rooms entirely and into a "Senate Session Types Shown in My Rooms" section in the Settings modal, gated on actually holding a Senate body membership (verified against board_memberships, any role). It's now a real per-user preference (senate_type_preferences jsonb column, same pattern as email_preferences) instead of a localStorage toggle, so it follows the user across devices. My Rooms refetches when the preference changes via a small window event, since the Settings modal can be open on top of it. Co-Authored-By: Claude Sonnet 5 --- app/(dashboard)/my-rooms/calendar-view.tsx | 6 +- app/(dashboard)/my-rooms/page.tsx | 63 +++---------------- app/(dashboard)/settings-modal.tsx | 38 +++++++++++ app/api/me/settings/route.ts | 13 +++- app/api/my-rooms/route.ts | 15 ++++- ...0825020000_add_senate_type_preferences.sql | 6 ++ 6 files changed, 80 insertions(+), 61 deletions(-) create mode 100644 supabase/migrations/20260825020000_add_senate_type_preferences.sql diff --git a/app/(dashboard)/my-rooms/calendar-view.tsx b/app/(dashboard)/my-rooms/calendar-view.tsx index 8c739ff..b2ea09b 100644 --- a/app/(dashboard)/my-rooms/calendar-view.tsx +++ b/app/(dashboard)/my-rooms/calendar-view.tsx @@ -126,7 +126,7 @@ export default function CalendarView({ bookings, onSelect }: CalendarViewProps) {dayBookings.slice(0, MAX_VISIBLE_PER_DAY).map(b => (
- {b.location} + {b.bodyName}
))} {dayBookings.length > MAX_VISIBLE_PER_DAY && ( @@ -151,8 +151,8 @@ export default function CalendarView({ bookings, onSelect }: CalendarViewProps)
onSelect(b)} className="flex items-center gap-4 px-5 py-3.5 hover:bg-[#1a4d8a] transition-colors cursor-pointer">
-

{b.location}

-

{b.bodyName} · {formatTime(b.startTime)} – {formatTime(b.endTime)}

+

{b.bodyName}

+

{b.location} · {formatTime(b.startTime)} – {formatTime(b.endTime)}

{b.status}
diff --git a/app/(dashboard)/my-rooms/page.tsx b/app/(dashboard)/my-rooms/page.tsx index 36db458..0bee047 100644 --- a/app/(dashboard)/my-rooms/page.tsx +++ b/app/(dashboard)/my-rooms/page.tsx @@ -9,7 +9,6 @@ import CalendarView from './calendar-view' import { Skeleton } from '@/app/_components/skeleton' import { type FlatBooking, - SENATE_TYPES, statusColors, statusBarColors, statusTextColors, @@ -71,8 +70,6 @@ function MyRoomsSkeleton() { type Filter = 1 | 3 | 7 type ViewMode = 'list' | 'calendar' -const SENATE_TYPE_FILTER_KEY = 'chambers-senate-type-filter' - function isWithinDays(dateStr: string, days: number) { const now = new Date() now.setHours(0, 0, 0, 0) @@ -87,10 +84,10 @@ export default function MyRoomsPage() { const [loading, setLoading] = useState(true) const [leadershipBodyIds, setLeadershipBodyIds] = useState([]) const [detailBooking, setDetailBooking] = useState(null) - const [viewMode, setViewMode] = useState('list') + const [viewMode, setViewMode] = useState('calendar') const [search, setSearch] = useState('') const [statusFilter, setStatusFilter] = useState('All') - const [senateTypeFilter, setSenateTypeFilter] = useState>(new Set(SENATE_TYPES)) + const [senateTypePreferences, setSenateTypePreferences] = useState>({}) const [cancellingBooking, setCancellingBooking] = useState<{ id: string type: 'One-Time Room' | 'Weekly Room' | 'Tabling' @@ -109,29 +106,6 @@ export default function MyRoomsPage() { location: string } | null>(null) - useEffect(() => { - try { - const stored = localStorage.getItem(SENATE_TYPE_FILTER_KEY) - if (stored) setSenateTypeFilter(new Set(JSON.parse(stored))) - } catch { - // Ignore malformed/unavailable storage — falls back to showing all types. - } - }, []) - - const toggleSenateType = (type: string) => { - setSenateTypeFilter(prev => { - const next = new Set(prev) - if (next.has(type)) next.delete(type) - else next.add(type) - try { - localStorage.setItem(SENATE_TYPE_FILTER_KEY, JSON.stringify([...next])) - } catch { - // Best-effort persistence only. - } - return next - }) - } - const fetchBookings = async () => { setLoading(true) // /api/my-rooms already resolves the caller's Leadership bodies, so this @@ -140,6 +114,7 @@ export default function MyRoomsPage() { const data = await res.json() setLeadershipBodyIds(data.leadershipBodyIds || []) + setSenateTypePreferences(data.senateTypePreferences || {}) const flat: FlatBooking[] = [] @@ -218,13 +193,14 @@ export default function MyRoomsPage() { useEffect(() => { fetchBookings() - // eslint-disable-next-line react-hooks/exhaustive-deps + // The Senate session-type preference lives in the Settings modal, which can + // be opened over this page; refetch so a change there is reflected here. + window.addEventListener('chambers:senate-prefs-updated', fetchBookings) + return () => window.removeEventListener('chambers:senate-prefs-updated', fetchBookings) }, []) - const hasSenateBookings = useMemo(() => all.some(b => b.bodyName === 'Senate'), [all]) - const passesSenateFilter = (b: FlatBooking) => - b.bodyName !== 'Senate' || !b.senateType || senateTypeFilter.has(b.senateType) + b.bodyName !== 'Senate' || !b.senateType || (senateTypePreferences[b.senateType] ?? true) const filteredUpcoming = all.filter(b => isWithinDays(b.date, filter) && passesSenateFilter(b)) @@ -242,7 +218,7 @@ export default function MyRoomsPage() { return true }) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [all, search, statusFilter, senateTypeFilter]) + }, [all, search, statusFilter, senateTypePreferences]) const filtersActive = search.trim() !== '' || statusFilter !== 'All' @@ -250,25 +226,6 @@ export default function MyRoomsPage() { return (
- {hasSenateBookings && ( -
- Senate Sessions - {SENATE_TYPES.map(t => ( - - ))} -
- )} - {/* My Upcoming Spaces */}
@@ -334,7 +291,7 @@ export default function MyRoomsPage() {

All Bookings

- {(['list', 'calendar'] as ViewMode[]).map(mode => ( + {(['calendar', 'list'] as ViewMode[]).map(mode => (