add daisyui buttons

This commit is contained in:
chark1es 2025-02-13 03:32:33 -08:00
parent 83324134b3
commit 09453c8755

View file

@ -214,13 +214,45 @@ declare global {
<label class="label"> <label class="label">
<span class="label-text font-medium">Year</span> <span class="label-text font-medium">Year</span>
</label> </label>
<select <div class="dropdown">
id="yearFilter" <label
class="select select-bordered select-sm" tabindex="0"
> class="btn btn-sm m-1 w-full justify-between"
<option value="all">All Years</option> >
<!-- Years will be populated dynamically --> <span id="yearFilterLabel">All Years</span>
</select> <svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</label>
<div
tabindex="0"
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52"
>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">All Years</span
>
<input
type="checkbox"
class="checkbox"
value="all"
checked
/>
</label>
</div>
<div id="yearCheckboxes" class="space-y-1">
<!-- Year checkboxes will be populated dynamically -->
</div>
</div>
</div>
</div> </div>
</div> </div>
@ -231,14 +263,64 @@ declare global {
<span class="label-text font-medium">Published</span <span class="label-text font-medium">Published</span
> >
</label> </label>
<select <div class="dropdown">
id="publishedFilter" <label
class="select select-bordered select-sm" tabindex="0"
> class="btn btn-sm m-1 w-full justify-between"
<option value="all">All</option> >
<option value="yes">Yes</option> <span id="publishedFilterLabel">All</span>
<option value="no">No</option> <svg
</select> xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</label>
<div
tabindex="0"
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52"
>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">All</span>
<input
type="radio"
name="publishedFilter"
class="radio"
value="all"
checked
/>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Yes</span>
<input
type="radio"
name="publishedFilter"
class="radio"
value="yes"
/>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">No</span>
<input
type="radio"
name="publishedFilter"
class="radio"
value="no"
/>
</label>
</div>
</div>
</div>
</div> </div>
<div class="form-control"> <div class="form-control">
@ -246,28 +328,128 @@ declare global {
<span class="label-text font-medium">Has Files</span <span class="label-text font-medium">Has Files</span
> >
</label> </label>
<select <div class="dropdown">
id="hasFilesFilter" <label
class="select select-bordered select-sm" tabindex="0"
> class="btn btn-sm m-1 w-full justify-between"
<option value="all">All</option> >
<option value="yes">Yes</option> <span id="hasFilesFilterLabel">All</span>
<option value="no">No</option> <svg
</select> xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</label>
<div
tabindex="0"
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52"
>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">All</span>
<input
type="radio"
name="hasFilesFilter"
class="radio"
value="all"
checked
/>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Yes</span>
<input
type="radio"
name="hasFilesFilter"
class="radio"
value="yes"
/>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">No</span>
<input
type="radio"
name="hasFilesFilter"
class="radio"
value="no"
/>
</label>
</div>
</div>
</div>
</div> </div>
<div class="form-control"> <div class="form-control">
<label class="label"> <label class="label">
<span class="label-text font-medium">Has Food</span> <span class="label-text font-medium">Has Food</span>
</label> </label>
<select <div class="dropdown">
id="hasFoodFilter" <label
class="select select-bordered select-sm" tabindex="0"
> class="btn btn-sm m-1 w-full justify-between"
<option value="all">All</option> >
<option value="yes">Yes</option> <span id="hasFoodFilterLabel">All</span>
<option value="no">No</option> <svg
</select> xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</label>
<div
tabindex="0"
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52"
>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">All</span>
<input
type="radio"
name="hasFoodFilter"
class="radio"
value="all"
checked
/>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Yes</span>
<input
type="radio"
name="hasFoodFilter"
class="radio"
value="yes"
/>
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">No</span>
<input
type="radio"
name="hasFoodFilter"
class="radio"
value="no"
/>
</label>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -681,7 +863,7 @@ declare global {
// Add filter state // Add filter state
let filterState = { let filterState = {
time: "all", time: "all",
year: "all", year: ["all"],
published: "all", published: "all",
hasFiles: "all", hasFiles: "all",
hasFood: "all", hasFood: "all",
@ -697,7 +879,6 @@ declare global {
try { try {
const now = Date.now(); const now = Date.now();
// Always refresh on page load (when lastCacheUpdate is 0)
if ( if (
lastCacheUpdate === 0 || lastCacheUpdate === 0 ||
now - lastCacheUpdate >= CACHE_DURATION || now - lastCacheUpdate >= CACHE_DURATION ||
@ -717,23 +898,74 @@ declare global {
years.add(year); years.add(year);
}); });
const yearFilter = document.getElementById( const yearCheckboxes =
"yearFilter" document.getElementById("yearCheckboxes");
) as HTMLSelectElement; if (yearCheckboxes) {
if (yearFilter) {
const sortedYears = Array.from(years).sort((a, b) => b - a); const sortedYears = Array.from(years).sort((a, b) => b - a);
yearFilter.innerHTML = yearCheckboxes.innerHTML = sortedYears
'<option value="all">All Years</option>' + .map(
sortedYears (year) => `
.map( <label class="label cursor-pointer">
(year) => <span class="label-text">${year}</span>
`<option value="${year}">${year}</option>` <input type="checkbox" class="checkbox" value="${year}" />
) </label>
.join(""); `
)
.join("");
if (filterState.year !== "all") { // Add event listeners to checkboxes
yearFilter.value = filterState.year; const allYearsCheckbox = document.querySelector(
'input[type="checkbox"][value="all"]'
) as HTMLInputElement;
const yearInputs = Array.from(
yearCheckboxes.querySelectorAll(
'input[type="checkbox"]'
)
) as HTMLInputElement[];
if (allYearsCheckbox) {
allYearsCheckbox.addEventListener("change", (e) => {
const target = e.target as HTMLInputElement;
yearInputs.forEach((input) => {
input.checked = false;
});
if (target.checked) {
filterState.year = ["all"];
document.getElementById(
"yearFilterLabel"
)!.textContent = "All Years";
}
currentPage = 1;
fetchEvents();
});
} }
yearInputs.forEach((input) => {
input.addEventListener("change", () => {
const checkedYears = yearInputs
.filter((inp) => inp.checked)
.map((inp) => inp.value);
if (checkedYears.length === 0) {
allYearsCheckbox.checked = true;
filterState.year = ["all"];
document.getElementById(
"yearFilterLabel"
)!.textContent = "All Years";
} else {
allYearsCheckbox.checked = false;
filterState.year = checkedYears;
document.getElementById(
"yearFilterLabel"
)!.textContent =
checkedYears.length === 1
? checkedYears[0]
: `${checkedYears.length} Years Selected`;
}
currentPage = 1;
fetchEvents();
});
});
} }
} }
} catch (error) { } catch (error) {
@ -821,15 +1053,18 @@ declare global {
return events.filter((event) => { return events.filter((event) => {
const now = new Date().toISOString(); const now = new Date().toISOString();
// Time and Year filters // Time filter
if (filterState.time === "upcoming" && event.start_date < now) if (filterState.time === "upcoming" && event.start_date < now)
return false; return false;
if (filterState.time === "past" && event.start_date >= now) if (filterState.time === "past" && event.start_date >= now)
return false; return false;
if (filterState.year !== "all") { // Year filter
const eventYear = new Date(event.start_date).getFullYear(); if (!filterState.year.includes("all")) {
if (eventYear.toString() !== filterState.year) return false; const eventYear = new Date(event.start_date)
.getFullYear()
.toString();
if (!filterState.year.includes(eventYear)) return false;
} }
// Published filter // Published filter
@ -1152,41 +1387,71 @@ declare global {
}); });
// Year filter // Year filter
document.getElementById("yearFilter")?.addEventListener("change", (e) => { document
const target = e.target as HTMLSelectElement; .getElementById("yearCheckboxes")
filterState.year = target.value; ?.addEventListener("change", () => {
currentPage = 1; const checkedYears = Array.from(
fetchEvents(); document.querySelectorAll('input[type="checkbox"]:checked')
}); ).map((inp) => (inp as HTMLInputElement).value);
if (checkedYears.length === 0) {
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
filterState.year = ["all"];
} else {
document.getElementById("yearFilterLabel")!.textContent =
checkedYears.length === 1
? checkedYears[0]
: `${checkedYears.length} Years Selected`;
filterState.year = checkedYears;
}
currentPage = 1;
fetchEvents();
});
// Published filter // Published filter
document document
.getElementById("publishedFilter") .querySelectorAll('input[name="publishedFilter"]')
?.addEventListener("change", (e) => { .forEach((radio: Element) => {
const target = e.target as HTMLSelectElement; (radio as HTMLInputElement).addEventListener("change", (e) => {
filterState.published = target.value; const target = e.target as HTMLInputElement;
currentPage = 1; filterState.published = target.value;
fetchEvents(); document.getElementById("publishedFilterLabel")!.textContent =
target.parentElement?.querySelector(".label-text")
?.textContent || "All";
currentPage = 1;
fetchEvents();
});
}); });
// Has Files filter // Has Files filter
document document
.getElementById("hasFilesFilter") .querySelectorAll('input[name="hasFilesFilter"]')
?.addEventListener("change", (e) => { .forEach((radio: Element) => {
const target = e.target as HTMLSelectElement; (radio as HTMLInputElement).addEventListener("change", (e) => {
filterState.hasFiles = target.value; const target = e.target as HTMLInputElement;
currentPage = 1; filterState.hasFiles = target.value;
fetchEvents(); document.getElementById("hasFilesFilterLabel")!.textContent =
target.parentElement?.querySelector(".label-text")
?.textContent || "All";
currentPage = 1;
fetchEvents();
});
}); });
// Has Food filter // Has Food filter
document document
.getElementById("hasFoodFilter") .querySelectorAll('input[name="hasFoodFilter"]')
?.addEventListener("change", (e) => { .forEach((radio: Element) => {
const target = e.target as HTMLSelectElement; (radio as HTMLInputElement).addEventListener("change", (e) => {
filterState.hasFood = target.value; const target = e.target as HTMLInputElement;
currentPage = 1; filterState.hasFood = target.value;
fetchEvents(); document.getElementById("hasFoodFilterLabel")!.textContent =
target.parentElement?.querySelector(".label-text")
?.textContent || "All";
currentPage = 1;
fetchEvents();
});
}); });
// Search input with instant search (no debounce needed for cached data) // Search input with instant search (no debounce needed for cached data)
@ -1235,9 +1500,19 @@ declare global {
} }
const yearFilter = document.getElementById( const yearFilter = document.getElementById(
"yearFilter" "yearCheckboxes"
) as HTMLSelectElement; ) as HTMLDivElement;
if (yearFilter) yearFilter.value = "all"; if (yearFilter) {
const yearInputs = yearFilter.querySelectorAll(
'input[type="checkbox"]'
);
yearInputs.forEach((input: HTMLInputElement) => {
input.checked = true;
});
filterState.year = ["all"];
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
}
const publishedFilter = document.getElementById( const publishedFilter = document.getElementById(
"publishedFilter" "publishedFilter"
@ -1272,7 +1547,7 @@ declare global {
// Reset filter state // Reset filter state
filterState = { filterState = {
time: "all", time: "all",
year: "all", year: ["all"],
published: "all", published: "all",
hasFiles: "all", hasFiles: "all",
hasFood: "all", hasFood: "all",