diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 850aa58..1c0f416 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -10,6 +10,8 @@ let selectedTags = $state([]); let tagFilter = $state(""); + let openingFilter = $state(""); + let closingFilter = $state(""); let tagFilterElem = $state(); function categorySelected(category: string[]) { @@ -32,19 +34,60 @@ }) ); - let filteredStudySpaces = $derived( - selectedTags.length === 0 - ? studySpaces - : studySpaces.filter((space) => { - const allTags = [ - ...(space.tags || []), - space.volume, - space.wifi, - space.power - ].filter(Boolean); + // Convert "HH:MM" or "HH:MM:SS" to minutes since midnight + function toMinutes(timeStr: string): number { + const [h, m] = timeStr.slice(0, 5).split(":").map(Number); + return h * 60 + m; + } - return selectedTags.every((tag) => allTags.includes(tag)); - }) + // Combine tag and time filtering + let filteredStudySpaces = $derived( + studySpaces + // tag filtering + .filter((space) => { + if (selectedTags.length === 0) return true; + const allTags = [ + ...(space.tags || []), + space.volume, + space.wifi, + space.power + ].filter(Boolean); + return selectedTags.every((tag) => allTags.includes(tag)); + }) + // opening time filter + .filter((space) => { + if (!openingFilter) return true; + const entry = space.study_space_hours?.find( + (h) => h.day_of_week === new Date().getDay() + ); + if (!entry) return false; + if (entry.is_24_7) return true; + const openMin = toMinutes(entry.opens_at); + let closeMin = toMinutes(entry.closes_at); + // Treat midnight as end of day and handle overnight spans + if (closeMin === 0) closeMin = 24 * 60; + if (closeMin <= openMin) closeMin += 24 * 60; + const filterMin = toMinutes(openingFilter); + // Include spaces open at the filter time + return filterMin >= openMin && filterMin < closeMin; + }) + // closing time filter + .filter((space) => { + if (!closingFilter) return true; + const entry = space.study_space_hours?.find( + (h) => h.day_of_week === new Date().getDay() + ); + if (!entry) return false; + if (entry.is_24_7) return true; + const openMin = toMinutes(entry.opens_at); + let closeMin = toMinutes(entry.closes_at); + if (closeMin === 0) closeMin = 24 * 60; + if (closeMin <= openMin) closeMin += 24 * 60; + const filterMin = + toMinutes(closingFilter) === 0 ? 24 * 60 : toMinutes(closingFilter); + // Include spaces still open at the filter time + return filterMin > openMin && filterMin <= closeMin; + }) ); let dropdownVisible = $state(false); @@ -73,6 +116,16 @@
Check Reports +
+ + +
@@ -162,7 +215,29 @@ grid-column: 1 / -1; display: flex; justify-content: center; - margin-bottom: 1rem; + margin-bottom: 0.5rem; + } + + .time-filter-container { + grid-column: 1 / -1; + display: flex; + gap: 1rem; + justify-content: center; + margin-bottom: 0.5rem; + } + .time-filter-container label { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 1rem; + color: #eaffeb; + } + .time-filter-container input[type="time"] { + background: none; + border: 2px solid #eaffeb; + border-radius: 0.5rem; + padding: 0.25rem 0.5rem; + color: #eaffeb; } form {