merge: Resolved merge conflicts

Co-Authored-By: Tadios Temesgen <tt2022@ic.ac.uk>
This commit is contained in:
Caspar Jojo Asaam
2025-06-12 16:21:20 +01:00
12 changed files with 397 additions and 21 deletions

View File

@@ -11,6 +11,8 @@
let selectedTags = $state<string[]>([]);
let tagFilter = $state("");
let openingFilter = $state("");
let closingFilter = $state("");
let tagFilterElem = $state<HTMLInputElement>();
function categorySelected(category: string[]) {
@@ -33,19 +35,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);
@@ -80,6 +123,16 @@
<Button href="/space/reports" type="link" style="red">Check Reports</Button>
</div>
{/if}
<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">
<form>
<div class="tagDisplay">
@@ -144,6 +197,7 @@
href="/space/{studySpace.id}"
imgSrc={imgUrl}
space={studySpace}
hours={studySpace.study_space_hours}
/>
{/each}
</main>
@@ -185,7 +239,29 @@
grid-column: 1 / -1;
display: flex;
justify-content: center;
padding: 0.5rem;
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 {