Add authentication #17
1 changed files with 388 additions and 394 deletions
|
@ -30,8 +30,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-base-100 opacity-0 group-hover:opacity-90 transition-opacity duration-300 flex items-center justify-center z-10"
|
class="absolute inset-0 bg-base-100 opacity-0 group-hover:opacity-90 transition-opacity duration-300 flex items-center justify-center z-10"
|
||||||
>
|
>
|
||||||
<span
|
<span class="text-base-content font-medium text-sm sm:text-base"
|
||||||
class="text-base-content font-medium text-sm sm:text-base"
|
|
||||||
>Coming Soon</span
|
>Coming Soon</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,12 +50,8 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
<option disabled selected>Pick an event</option>
|
<option disabled selected>Pick an event</option>
|
||||||
<option
|
<option>Technical Workshop - Web Development</option>
|
||||||
>Technical Workshop - Web Development</option
|
<option>Professional Development Workshop</option>
|
||||||
>
|
|
||||||
<option
|
|
||||||
>Professional Development Workshop</option
|
|
||||||
>
|
|
||||||
<option>Social Event - Game Night</option>
|
<option>Social Event - Game Night</option>
|
||||||
</select>
|
</select>
|
||||||
<button
|
<button
|
||||||
|
@ -86,10 +81,9 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
class="btn btn-primary btn-sm gap-1 text-xs sm:text-sm"
|
class="btn btn-primary btn-sm gap-1 text-xs sm:text-sm"
|
||||||
onclick="window.downloadAllFiles()"
|
onclick="window.downloadAllFiles()"
|
||||||
>
|
>
|
||||||
<Icon
|
<iconify-icon
|
||||||
icon="heroicons:arrow-down-tray-20-solid"
|
icon="heroicons:arrow-down-tray-20-solid"
|
||||||
className="h-3 w-3 sm:h-4 sm:w-4"
|
className="h-3 w-3 sm:h-4 sm:w-4"></iconify-icon>
|
||||||
/>
|
|
||||||
Download All
|
Download All
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -97,10 +91,8 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
class="btn btn-circle btn-ghost btn-sm sm:btn-md"
|
class="btn btn-circle btn-ghost btn-sm sm:btn-md"
|
||||||
onclick="window.closeEventDetailsModal()"
|
onclick="window.closeEventDetailsModal()"
|
||||||
>
|
>
|
||||||
<Icon
|
<iconify-icon icon="heroicons:x-mark" className="h-4 w-4 sm:h-6 sm:w-6"
|
||||||
icon="heroicons:x-mark"
|
></iconify-icon>
|
||||||
className="h-4 w-4 sm:h-6 sm:w-6"
|
|
||||||
/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -134,8 +126,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
id="previewLoadingSpinner"
|
id="previewLoadingSpinner"
|
||||||
class="absolute inset-0 flex items-center justify-center bg-base-200 bg-opacity-50 hidden"
|
class="absolute inset-0 flex items-center justify-center bg-base-200 bg-opacity-50 hidden"
|
||||||
>
|
>
|
||||||
<span class="loading loading-spinner loading-md sm:loading-lg"
|
<span class="loading loading-spinner loading-md sm:loading-lg"></span>
|
||||||
></span>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="previewContent" class="w-full">
|
<div id="previewContent" class="w-full">
|
||||||
<FilePreview client:load isModal={true} />
|
<FilePreview client:load isModal={true} />
|
||||||
|
@ -153,19 +144,16 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
// Toast management system
|
// Toast management system
|
||||||
const createToast = (
|
const createToast = (
|
||||||
message: string,
|
message: string,
|
||||||
type: "success" | "error" | "warning" = "success"
|
type: "success" | "error" | "warning" = "success",
|
||||||
) => {
|
) => {
|
||||||
let toastContainer = document.querySelector(".toast-container");
|
let toastContainer = document.querySelector(".toast-container");
|
||||||
if (!toastContainer) {
|
if (!toastContainer) {
|
||||||
toastContainer = document.createElement("div");
|
toastContainer = document.createElement("div");
|
||||||
toastContainer.className =
|
toastContainer.className = "toast-container fixed bottom-4 right-4 z-50";
|
||||||
"toast-container fixed bottom-4 right-4 z-50";
|
|
||||||
document.body.appendChild(toastContainer);
|
document.body.appendChild(toastContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingToasts = document.querySelectorAll(
|
const existingToasts = document.querySelectorAll(".toast-container .toast");
|
||||||
".toast-container .toast"
|
|
||||||
);
|
|
||||||
if (existingToasts.length >= 2) {
|
if (existingToasts.length >= 2) {
|
||||||
const oldestToast = existingToasts[0];
|
const oldestToast = existingToasts[0];
|
||||||
oldestToast.classList.add("toast-exit");
|
oldestToast.classList.add("toast-exit");
|
||||||
|
@ -175,9 +163,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
// Update positions of existing toasts
|
// Update positions of existing toasts
|
||||||
existingToasts.forEach((t) => {
|
existingToasts.forEach((t) => {
|
||||||
const toast = t as HTMLElement;
|
const toast = t as HTMLElement;
|
||||||
const currentIndex = parseInt(
|
const currentIndex = parseInt(toast.getAttribute("data-index") || "0");
|
||||||
toast.getAttribute("data-index") || "0"
|
|
||||||
);
|
|
||||||
toast.setAttribute("data-index", (currentIndex + 1).toString());
|
toast.setAttribute("data-index", (currentIndex + 1).toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -198,10 +184,10 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
${
|
${
|
||||||
type === "success"
|
type === "success"
|
||||||
? '<Icon icon="heroicons:check-circle" class="stroke-current shrink-0 h-6 w-6"></Icon>'
|
? '<iconify-icon icon="heroicons:check-circle" class="stroke-current shrink-0 h-6 w-6"></iconify-icon>'
|
||||||
: type === "error"
|
: type === "error"
|
||||||
? '<Icon icon="heroicons:x-circle" class="stroke-current shrink-0 h-6 w-6"></Icon>'
|
? '<iconify-icon icon="heroicons:x-circle" class="stroke-current shrink-0 h-6 w-6"></iconify-icon>'
|
||||||
: '<Icon icon="heroicons:exclamation-triangle" class="stroke-current shrink-0 h-6 w-6"></Icon>'
|
: '<iconify-icon icon="heroicons:exclamation-triangle" class="stroke-current shrink-0 w-6"></iconify-icon>'
|
||||||
}
|
}
|
||||||
<span>${message}</span>
|
<span>${message}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -285,7 +271,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
window.previewFileEvents = function (url: string, filename: string) {
|
window.previewFileEvents = function (url: string, filename: string) {
|
||||||
console.log("previewFileEvents called with:", { url, filename });
|
console.log("previewFileEvents called with:", { url, filename });
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"filePreviewModal"
|
"filePreviewModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const previewFileName = document.getElementById("previewFileName");
|
const previewFileName = document.getElementById("previewFileName");
|
||||||
const previewContent = document.getElementById("previewContent");
|
const previewContent = document.getElementById("previewContent");
|
||||||
|
@ -302,7 +288,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("filePreviewStateChange", {
|
new CustomEvent("filePreviewStateChange", {
|
||||||
detail: { url, filename },
|
detail: { url, filename },
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -311,7 +297,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
window.closeFilePreviewEvents = function () {
|
window.closeFilePreviewEvents = function () {
|
||||||
console.log("closeFilePreviewEvents called");
|
console.log("closeFilePreviewEvents called");
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"filePreviewModal"
|
"filePreviewModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const previewFileName = document.getElementById("previewFileName");
|
const previewFileName = document.getElementById("previewFileName");
|
||||||
const previewContent = document.getElementById("previewContent");
|
const previewContent = document.getElementById("previewContent");
|
||||||
|
@ -322,7 +308,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("filePreviewStateChange", {
|
new CustomEvent("filePreviewStateChange", {
|
||||||
detail: { url: "", filename: "" },
|
detail: { url: "", filename: "" },
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reset the UI
|
// Reset the UI
|
||||||
|
@ -345,22 +331,30 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
// Update the openDetailsModal function to use the events-specific preview
|
// Update the openDetailsModal function to use the events-specific preview
|
||||||
window.openDetailsModal = function (event: any) {
|
window.openDetailsModal = function (event: any) {
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"eventDetailsModal"
|
"eventDetailsModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const filesContent = document.getElementById(
|
const filesContent = document.getElementById(
|
||||||
"filesContent"
|
"filesContent",
|
||||||
) as HTMLDivElement;
|
) as HTMLDivElement;
|
||||||
|
|
||||||
|
// Check if event has ended
|
||||||
|
const eventEndDate = new Date(event.end_date);
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
if (eventEndDate > now) {
|
||||||
|
createToast(
|
||||||
|
"Files are only available after the event has ended.",
|
||||||
|
"warning",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset state
|
// Reset state
|
||||||
window.currentEventId = event.id;
|
window.currentEventId = event.id;
|
||||||
if (filesContent) filesContent.classList.remove("hidden");
|
if (filesContent) filesContent.classList.remove("hidden");
|
||||||
|
|
||||||
// Populate files content
|
// Populate files content
|
||||||
if (
|
if (event.files && Array.isArray(event.files) && event.files.length > 0) {
|
||||||
event.files &&
|
|
||||||
Array.isArray(event.files) &&
|
|
||||||
event.files.length > 0
|
|
||||||
) {
|
|
||||||
const baseUrl = "https://pocketbase.ieeeucsd.org";
|
const baseUrl = "https://pocketbase.ieeeucsd.org";
|
||||||
const collectionId = "events";
|
const collectionId = "events";
|
||||||
const recordId = event.id;
|
const recordId = event.id;
|
||||||
|
@ -388,10 +382,10 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
<td>${file}</td>
|
<td>${file}</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<button class="btn btn-ghost btn-sm" onclick='window.showFilePreviewEvents(${previewData})'>
|
<button class="btn btn-ghost btn-sm" onclick='window.showFilePreviewEvents(${previewData})'>
|
||||||
<Icon icon="heroicons:document" className="h-4 w-4" />
|
<iconify-icon icon="heroicons:document" className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
<a href="${fileUrl}" download="${file}" class="btn btn-ghost btn-sm">
|
<a href="${fileUrl}" download="${file}" class="btn btn-ghost btn-sm">
|
||||||
<Icon icon="heroicons:arrow-down-tray-20-solid" className="h-4 w-4" />
|
<iconify-icon icon="heroicons:arrow-down-tray-20-solid" className="h-4 w-4" />
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -405,7 +399,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
} else {
|
} else {
|
||||||
filesContent.innerHTML = `
|
filesContent.innerHTML = `
|
||||||
<div class="text-center py-8 text-base-content/70">
|
<div class="text-center py-8 text-base-content/70">
|
||||||
<Icon icon="heroicons:document-duplicate" className="h-12 w-12 mx-auto mb-4 opacity-50" />
|
<iconify-icon icon="heroicons:document-duplicate" className="h-12 w-12 mx-auto mb-4 opacity-50" />
|
||||||
<p>No files attached to this event</p>
|
<p>No files attached to this event</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -417,7 +411,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
// Add downloadAllFiles function
|
// Add downloadAllFiles function
|
||||||
window.downloadAllFiles = async function () {
|
window.downloadAllFiles = async function () {
|
||||||
const downloadBtn = document.getElementById(
|
const downloadBtn = document.getElementById(
|
||||||
"downloadAllBtn"
|
"downloadAllBtn",
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
if (!downloadBtn) return;
|
if (!downloadBtn) return;
|
||||||
const originalBtnContent = downloadBtn.innerHTML;
|
const originalBtnContent = downloadBtn.innerHTML;
|
||||||
|
@ -473,7 +467,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
console.error("Failed to download files:", error);
|
console.error("Failed to download files:", error);
|
||||||
createToast(
|
createToast(
|
||||||
error?.message || "Failed to download files. Please try again.",
|
error?.message || "Failed to download files. Please try again.",
|
||||||
"error"
|
"error",
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
// Reset button state
|
// Reset button state
|
||||||
|
@ -485,7 +479,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
// Close event details modal
|
// Close event details modal
|
||||||
window.closeEventDetailsModal = function () {
|
window.closeEventDetailsModal = function () {
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"eventDetailsModal"
|
"eventDetailsModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const filesContent = document.getElementById("filesContent");
|
const filesContent = document.getElementById("filesContent");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue