add daisyui buttons
This commit is contained in:
parent
83324134b3
commit
09453c8755
1 changed files with 354 additions and 79 deletions
|
@ -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",
|
||||||
|
|
Loading…
Reference in a new issue