merge: Merged r-merge into master #47
@@ -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 @@
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
let filteredStudySpaces = $derived(
|
// Convert "HH:MM" or "HH:MM:SS" to minutes since midnight
|
||||||
selectedTags.length === 0
|
function toMinutes(timeStr: string): number {
|
||||||
? studySpaces
|
const [h, m] = timeStr.slice(0, 5).split(":").map(Number);
|
||||||
: studySpaces.filter((space) => {
|
return h * 60 + m;
|
||||||
const allTags = [
|
}
|
||||||
...(space.tags || []),
|
|
||||||
space.volume,
|
|
||||||
space.wifi,
|
|
||||||
space.power
|
|
||||||
].filter(Boolean);
|
|
||||||
|
|
||||||
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);
|
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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user