merge: merge feat/filter-by-time into master #46

Closed
ca422 wants to merge 4 commits from feat/filter-by-time into master
24 changed files with 826 additions and 1119 deletions
Showing only changes of commit 30f44b0ac6 - Show all commits

View File

@@ -10,6 +10,8 @@
let selectedTags = $state<string[]>([]); let selectedTags = $state<string[]>([]);
let tagFilter = $state(""); let tagFilter = $state("");
let openingFilter = $state("");
let closingFilter = $state("");
let tagFilterElem = $state<HTMLInputElement>(); let tagFilterElem = $state<HTMLInputElement>();
function categorySelected(category: string[]) { function categorySelected(category: string[]) {
@@ -32,19 +34,60 @@
}) })
); );
// 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;
}
// Combine tag and time filtering
let filteredStudySpaces = $derived( let filteredStudySpaces = $derived(
selectedTags.length === 0 studySpaces
? studySpaces // tag filtering
: studySpaces.filter((space) => { .filter((space) => {
if (selectedTags.length === 0) return true;
const allTags = [ const allTags = [
...(space.tags || []), ...(space.tags || []),
space.volume, space.volume,
space.wifi, space.wifi,
space.power space.power
].filter(Boolean); ].filter(Boolean);
return selectedTags.every((tag) => allTags.includes(tag)); 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); let dropdownVisible = $state(false);
@@ -73,6 +116,16 @@
<main> <main>
<a href="/space/reports" class="checkReports">Check Reports</a> <a href="/space/reports" class="checkReports">Check Reports</a>
<div class="time-filter-container">
<label>
Open from:
<input type="time" bind:value={openingFilter} />
</label>
<label>
Open until:
<input type="time" bind:value={closingFilter} />
</label>
</div>
<div class="tag-filter-container"> <div class="tag-filter-container">
<form> <form>
<div class="tagDisplay"> <div class="tagDisplay">
@@ -162,7 +215,29 @@
grid-column: 1 / -1; grid-column: 1 / -1;
display: flex; display: flex;
justify-content: center; 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 { form {