no more console logs
This commit is contained in:
parent
16d9ec9e1d
commit
27bc2f4e70
32 changed files with 3752 additions and 4000 deletions
|
@ -1,18 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
const observer = new IntersectionObserver((entries) => {
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
entry.target.classList.add("in-view");
|
entry.target.classList.add("in-view");
|
||||||
entry.target.classList.remove("opacity-0");
|
entry.target.classList.remove("opacity-0");
|
||||||
console.log("Added 'in-view' class to:", entry.target);
|
// console.log("Added 'in-view' class to:", entry.target);
|
||||||
} else {
|
} else {
|
||||||
entry.target.classList.remove("in-view");
|
entry.target.classList.remove("in-view");
|
||||||
entry.target.classList.add("opacity-0");
|
entry.target.classList.add("opacity-0");
|
||||||
console.log("Removed 'in-view' class from:", entry.target);
|
// console.log("Removed 'in-view' class from:", entry.target);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, { threshold: 0.2 });
|
},
|
||||||
|
{ threshold: 0.2 },
|
||||||
|
);
|
||||||
|
|
||||||
document.querySelectorAll("[data-inview]").forEach((el) => observer.observe(el));
|
document
|
||||||
|
.querySelectorAll("[data-inview]")
|
||||||
|
.forEach((el) => observer.observe(el));
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -28,8 +28,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>
|
||||||
|
@ -49,12 +48,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
|
||||||
|
@ -94,9 +89,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()"
|
||||||
>
|
>
|
||||||
<iconify-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"></iconify-icon>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -130,8 +124,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} />
|
||||||
|
@ -191,14 +184,14 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
|
|
||||||
// Universal file preview function for events section
|
// Universal file preview function for events section
|
||||||
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 });
|
||||||
console.log("URL type:", typeof url, "URL length:", url?.length || 0);
|
// console.log("URL type:", typeof url, "URL length:", url?.length || 0);
|
||||||
console.log(
|
// console.log(
|
||||||
"Filename type:",
|
// "Filename type:",
|
||||||
typeof filename,
|
// typeof filename,
|
||||||
"Filename length:",
|
// "Filename length:",
|
||||||
filename?.length || 0
|
// filename?.length || 0
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Validate inputs
|
// Validate inputs
|
||||||
if (!url || typeof url !== "string") {
|
if (!url || typeof url !== "string") {
|
||||||
|
@ -210,7 +203,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
if (!filename || typeof filename !== "string") {
|
if (!filename || typeof filename !== "string") {
|
||||||
console.error(
|
console.error(
|
||||||
"Invalid filename provided to previewFileEvents:",
|
"Invalid filename provided to previewFileEvents:",
|
||||||
filename
|
filename,
|
||||||
);
|
);
|
||||||
toast.error("Cannot preview file: Invalid filename");
|
toast.error("Cannot preview file: Invalid filename");
|
||||||
return;
|
return;
|
||||||
|
@ -218,27 +211,24 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
|
|
||||||
// Ensure URL is properly formatted
|
// Ensure URL is properly formatted
|
||||||
if (!url.startsWith("http")) {
|
if (!url.startsWith("http")) {
|
||||||
console.warn(
|
console.warn("URL doesn't start with http, attempting to fix:", url);
|
||||||
"URL doesn't start with http, attempting to fix:",
|
|
||||||
url
|
|
||||||
);
|
|
||||||
if (url.startsWith("/")) {
|
if (url.startsWith("/")) {
|
||||||
url = `https://pocketbase.ieeeucsd.org${url}`;
|
url = `https://pocketbase.ieeeucsd.org${url}`;
|
||||||
} else {
|
} else {
|
||||||
url = `https://pocketbase.ieeeucsd.org/${url}`;
|
url = `https://pocketbase.ieeeucsd.org/${url}`;
|
||||||
}
|
}
|
||||||
console.log("Fixed URL:", url);
|
// console.log("Fixed URL:", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
const loadingSpinner = document.getElementById("previewLoadingSpinner");
|
const loadingSpinner = document.getElementById("previewLoadingSpinner");
|
||||||
|
|
||||||
if (modal && previewFileName && previewContent) {
|
if (modal && previewFileName && previewContent) {
|
||||||
console.log("Found all required elements");
|
// console.log("Found all required elements");
|
||||||
|
|
||||||
// Show loading spinner
|
// Show loading spinner
|
||||||
if (loadingSpinner) {
|
if (loadingSpinner) {
|
||||||
|
@ -254,11 +244,11 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
// Test the URL with a fetch before dispatching the event
|
// Test the URL with a fetch before dispatching the event
|
||||||
fetch(url, { method: "HEAD" })
|
fetch(url, { method: "HEAD" })
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
console.log(
|
// console.log(
|
||||||
"URL test response:",
|
// "URL test response:",
|
||||||
response.status,
|
// response.status,
|
||||||
response.ok
|
// response.ok
|
||||||
);
|
// );
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.warn("URL might not be accessible:", url);
|
console.warn("URL might not be accessible:", url);
|
||||||
toast(
|
toast(
|
||||||
|
@ -270,7 +260,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
background: "#FFC107",
|
background: "#FFC107",
|
||||||
color: "#000",
|
color: "#000",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -279,14 +269,14 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
// Dispatch state change event to update the FilePreview component
|
// Dispatch state change event to update the FilePreview component
|
||||||
console.log(
|
// console.log(
|
||||||
"Dispatching filePreviewStateChange event with:",
|
// "Dispatching filePreviewStateChange event with:",
|
||||||
{ url, filename }
|
// { url, filename }
|
||||||
);
|
// );
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("filePreviewStateChange", {
|
new CustomEvent("filePreviewStateChange", {
|
||||||
detail: { url, filename },
|
detail: { url, filename },
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -304,9 +294,9 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
|
|
||||||
// Close file preview for events section
|
// Close file preview for events section
|
||||||
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");
|
||||||
|
@ -317,14 +307,14 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modal && previewFileName && previewContent) {
|
if (modal && previewFileName && previewContent) {
|
||||||
console.log("Resetting preview and closing modal");
|
// console.log("Resetting preview and closing modal");
|
||||||
|
|
||||||
// First reset the preview state by dispatching an event with empty values
|
// First reset the preview state by dispatching an event with empty values
|
||||||
// This ensures the FilePreview component clears its internal state
|
// This ensures the FilePreview component clears its internal state
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("filePreviewStateChange", {
|
new CustomEvent("filePreviewStateChange", {
|
||||||
detail: { url: "", filename: "" },
|
detail: { url: "", filename: "" },
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reset the UI
|
// Reset the UI
|
||||||
|
@ -333,7 +323,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
// Close the modal
|
// Close the modal
|
||||||
modal.close();
|
modal.close();
|
||||||
|
|
||||||
console.log("File preview modal closed and state reset");
|
// console.log("File preview modal closed and state reset");
|
||||||
} else {
|
} else {
|
||||||
console.error("Could not find elements to close file preview");
|
console.error("Could not find elements to close file preview");
|
||||||
}
|
}
|
||||||
|
@ -344,7 +334,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
url: string;
|
url: string;
|
||||||
name: string;
|
name: string;
|
||||||
}) {
|
}) {
|
||||||
console.log("showFilePreviewEvents called with:", file);
|
// console.log("showFilePreviewEvents called with:", file);
|
||||||
if (!file || !file.url || !file.name) {
|
if (!file || !file.url || !file.name) {
|
||||||
console.error("Invalid file data:", file);
|
console.error("Invalid file data:", file);
|
||||||
toast.error("Could not preview file: missing file information");
|
toast.error("Could not preview file: missing file information");
|
||||||
|
@ -356,10 +346,10 @@ 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
|
// Check if event has ended
|
||||||
|
@ -383,11 +373,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
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;
|
||||||
|
@ -446,7 +432,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;
|
||||||
|
@ -501,7 +487,7 @@ import EventLoad from "./EventsSection/EventLoad";
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("Failed to download files:", error);
|
console.error("Failed to download files:", error);
|
||||||
toast.error(
|
toast.error(
|
||||||
error?.message || "Failed to download files. Please try again."
|
error?.message || "Failed to download files. Please try again.",
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
// Reset button state
|
// Reset button state
|
||||||
|
@ -513,7 +499,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");
|
||||||
|
|
||||||
|
|
|
@ -249,8 +249,6 @@ const EventCheckIn = () => {
|
||||||
// Create the attendee record in PocketBase
|
// Create the attendee record in PocketBase
|
||||||
const newAttendee = await update.create(Collections.EVENT_ATTENDEES, attendeeData);
|
const newAttendee = await update.create(Collections.EVENT_ATTENDEES, attendeeData);
|
||||||
|
|
||||||
console.log("Successfully created attendance record");
|
|
||||||
|
|
||||||
// Update user's total points
|
// Update user's total points
|
||||||
// First, get all the user's attendance records to calculate total points
|
// First, get all the user's attendance records to calculate total points
|
||||||
const userAttendance = await get.getList<EventAttendee>(
|
const userAttendance = await get.getList<EventAttendee>(
|
||||||
|
@ -267,7 +265,7 @@ const EventCheckIn = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Log the points update
|
// Log the points update
|
||||||
console.log(`Updating user points to: ${totalPoints}`);
|
// console.log(`Updating user points to: ${totalPoints}`);
|
||||||
|
|
||||||
// Update the user record with the new total points
|
// Update the user record with the new total points
|
||||||
await update.updateFields(Collections.USERS, userId, {
|
await update.updateFields(Collections.USERS, userId, {
|
||||||
|
|
|
@ -74,9 +74,9 @@ const EventLoad = () => {
|
||||||
|
|
||||||
// Clear events table
|
// Clear events table
|
||||||
if (db && db.events) {
|
if (db && db.events) {
|
||||||
console.log("Clearing events cache...");
|
// console.log("Clearing events cache...");
|
||||||
await db.events.clear();
|
await db.events.clear();
|
||||||
console.log("Events cache cleared successfully");
|
// console.log("Events cache cleared successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset sync timestamp for events by updating it to 0
|
// Reset sync timestamp for events by updating it to 0
|
||||||
|
@ -84,7 +84,7 @@ const EventLoad = () => {
|
||||||
const currentInfo = await dexieService.getLastSync(Collections.EVENTS);
|
const currentInfo = await dexieService.getLastSync(Collections.EVENTS);
|
||||||
// Then update it with a timestamp of 0 (forcing a fresh sync)
|
// Then update it with a timestamp of 0 (forcing a fresh sync)
|
||||||
await dexieService.updateLastSync(Collections.EVENTS);
|
await dexieService.updateLastSync(Collections.EVENTS);
|
||||||
console.log("Events sync timestamp reset");
|
// console.log("Events sync timestamp reset");
|
||||||
|
|
||||||
// Reload events
|
// Reload events
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
@ -245,7 +245,7 @@ const EventLoad = () => {
|
||||||
const dataSync = DataSyncService.getInstance();
|
const dataSync = DataSyncService.getInstance();
|
||||||
const auth = Authentication.getInstance();
|
const auth = Authentication.getInstance();
|
||||||
|
|
||||||
console.log("Starting to load events...");
|
// console.log("Starting to load events...");
|
||||||
|
|
||||||
// Check if user is authenticated
|
// Check if user is authenticated
|
||||||
if (!auth.isAuthenticated()) {
|
if (!auth.isAuthenticated()) {
|
||||||
|
@ -255,7 +255,7 @@ const EventLoad = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force sync to ensure we have the latest data
|
// Force sync to ensure we have the latest data
|
||||||
console.log("Syncing events collection...");
|
// console.log("Syncing events collection...");
|
||||||
let syncSuccess = false;
|
let syncSuccess = false;
|
||||||
let retryCount = 0;
|
let retryCount = 0;
|
||||||
const maxRetries = 3;
|
const maxRetries = 3;
|
||||||
|
@ -263,13 +263,13 @@ const EventLoad = () => {
|
||||||
while (!syncSuccess && retryCount < maxRetries) {
|
while (!syncSuccess && retryCount < maxRetries) {
|
||||||
try {
|
try {
|
||||||
if (retryCount > 0) {
|
if (retryCount > 0) {
|
||||||
console.log(`Retry attempt ${retryCount} of ${maxRetries}...`);
|
// console.log(`Retry attempt ${retryCount} of ${maxRetries}...`);
|
||||||
// Add a small delay between retries
|
// Add a small delay between retries
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
|
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
await dataSync.syncCollection(Collections.EVENTS, "published = true", "-start_date");
|
await dataSync.syncCollection(Collections.EVENTS, "published = true", "-start_date");
|
||||||
console.log("Events collection synced successfully");
|
// console.log("Events collection synced successfully");
|
||||||
syncSuccess = true;
|
syncSuccess = true;
|
||||||
} catch (syncError) {
|
} catch (syncError) {
|
||||||
retryCount++;
|
retryCount++;
|
||||||
|
@ -282,7 +282,7 @@ const EventLoad = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get events from IndexedDB
|
// Get events from IndexedDB
|
||||||
console.log("Fetching events from IndexedDB...");
|
// console.log("Fetching events from IndexedDB...");
|
||||||
const allEvents = await dataSync.getData<Event>(
|
const allEvents = await dataSync.getData<Event>(
|
||||||
Collections.EVENTS,
|
Collections.EVENTS,
|
||||||
false, // Don't force sync again
|
false, // Don't force sync again
|
||||||
|
@ -290,27 +290,27 @@ const EventLoad = () => {
|
||||||
"-start_date"
|
"-start_date"
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Retrieved ${allEvents.length} events from IndexedDB`);
|
// console.log(`Retrieved ${allEvents.length} events from IndexedDB`);
|
||||||
|
|
||||||
// Filter out invalid events
|
// Filter out invalid events
|
||||||
const validEvents = allEvents.filter(event => isValidEvent(event));
|
const validEvents = allEvents.filter(event => isValidEvent(event));
|
||||||
console.log(`Filtered out ${allEvents.length - validEvents.length} invalid events`);
|
// console.log(`Filtered out ${allEvents.length - validEvents.length} invalid events`);
|
||||||
|
|
||||||
// If no valid events found in IndexedDB, try fetching directly from PocketBase as fallback
|
// If no valid events found in IndexedDB, try fetching directly from PocketBase as fallback
|
||||||
let eventsToProcess = validEvents;
|
let eventsToProcess = validEvents;
|
||||||
if (allEvents.length === 0) {
|
if (allEvents.length === 0) {
|
||||||
console.log("No events found in IndexedDB, trying direct PocketBase fetch...");
|
// console.log("No events found in IndexedDB, trying direct PocketBase fetch...");
|
||||||
try {
|
try {
|
||||||
const pbEvents = await get.getAll<Event>(
|
const pbEvents = await get.getAll<Event>(
|
||||||
Collections.EVENTS,
|
Collections.EVENTS,
|
||||||
"published = true",
|
"published = true",
|
||||||
"-start_date"
|
"-start_date"
|
||||||
);
|
);
|
||||||
console.log(`Retrieved ${pbEvents.length} events directly from PocketBase`);
|
// console.log(`Retrieved ${pbEvents.length} events directly from PocketBase`);
|
||||||
|
|
||||||
// Filter out invalid events from PocketBase results
|
// Filter out invalid events from PocketBase results
|
||||||
const validPbEvents = pbEvents.filter(event => isValidEvent(event));
|
const validPbEvents = pbEvents.filter(event => isValidEvent(event));
|
||||||
console.log(`Filtered out ${pbEvents.length - validPbEvents.length} invalid events from PocketBase`);
|
// console.log(`Filtered out ${pbEvents.length - validPbEvents.length} invalid events from PocketBase`);
|
||||||
|
|
||||||
eventsToProcess = validPbEvents;
|
eventsToProcess = validPbEvents;
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ const EventLoad = () => {
|
||||||
const dexieService = DexieService.getInstance();
|
const dexieService = DexieService.getInstance();
|
||||||
const db = dexieService.getDB();
|
const db = dexieService.getDB();
|
||||||
if (db && db.events) {
|
if (db && db.events) {
|
||||||
console.log(`Storing ${validPbEvents.length} valid PocketBase events in IndexedDB...`);
|
// console.log(`Storing ${validPbEvents.length} valid PocketBase events in IndexedDB...`);
|
||||||
await db.events.bulkPut(validPbEvents);
|
await db.events.bulkPut(validPbEvents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ const EventLoad = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split events into upcoming, ongoing, and past based on start and end dates
|
// Split events into upcoming, ongoing, and past based on start and end dates
|
||||||
console.log("Categorizing events...");
|
// console.log("Categorizing events...");
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const { upcoming, ongoing, past } = eventsToProcess.reduce(
|
const { upcoming, ongoing, past } = eventsToProcess.reduce(
|
||||||
(acc, event) => {
|
(acc, event) => {
|
||||||
|
@ -382,7 +382,7 @@ const EventLoad = () => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Categorized events: ${upcoming.length} upcoming, ${ongoing.length} ongoing, ${past.length} past`);
|
// console.log(`Categorized events: ${upcoming.length} upcoming, ${ongoing.length} ongoing, ${past.length} past`);
|
||||||
|
|
||||||
// Sort events
|
// Sort events
|
||||||
upcoming.sort((a, b) => new Date(a.start_date).getTime() - new Date(b.start_date).getTime());
|
upcoming.sort((a, b) => new Date(a.start_date).getTime() - new Date(b.start_date).getTime());
|
||||||
|
@ -409,16 +409,16 @@ const EventLoad = () => {
|
||||||
|
|
||||||
// Try to load from IndexedDB only as a last resort
|
// Try to load from IndexedDB only as a last resort
|
||||||
try {
|
try {
|
||||||
console.log("Attempting to load events from IndexedDB only...");
|
// console.log("Attempting to load events from IndexedDB only...");
|
||||||
const dexieService = DexieService.getInstance();
|
const dexieService = DexieService.getInstance();
|
||||||
const db = dexieService.getDB();
|
const db = dexieService.getDB();
|
||||||
if (db && db.events) {
|
if (db && db.events) {
|
||||||
const allCachedEvents = await db.events.filter(event => event.published === true).toArray();
|
const allCachedEvents = await db.events.filter(event => event.published === true).toArray();
|
||||||
console.log(`Found ${allCachedEvents.length} cached events in IndexedDB`);
|
// console.log(`Found ${allCachedEvents.length} cached events in IndexedDB`);
|
||||||
|
|
||||||
// Filter out invalid events
|
// Filter out invalid events
|
||||||
const cachedEvents = allCachedEvents.filter(event => isValidEvent(event));
|
const cachedEvents = allCachedEvents.filter(event => isValidEvent(event));
|
||||||
console.log(`Filtered out ${allCachedEvents.length - cachedEvents.length} invalid cached events`);
|
// console.log(`Filtered out ${allCachedEvents.length - cachedEvents.length} invalid cached events`);
|
||||||
|
|
||||||
if (cachedEvents.length > 0) {
|
if (cachedEvents.length > 0) {
|
||||||
// Process these events
|
// Process these events
|
||||||
|
@ -458,7 +458,7 @@ const EventLoad = () => {
|
||||||
ongoing: ongoing.slice(0, 50),
|
ongoing: ongoing.slice(0, 50),
|
||||||
past: past.slice(0, 50)
|
past: past.slice(0, 50)
|
||||||
});
|
});
|
||||||
console.log("Successfully loaded events from cache");
|
// console.log("Successfully loaded events from cache");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (cacheError) {
|
} catch (cacheError) {
|
||||||
|
|
|
@ -34,13 +34,7 @@ let upcomingEvents: Event[] = [];
|
||||||
// Fetch events
|
// Fetch events
|
||||||
try {
|
try {
|
||||||
if (auth.isAuthenticated()) {
|
if (auth.isAuthenticated()) {
|
||||||
eventResponse = await get.getList<Event>(
|
eventResponse = await get.getList<Event>("events", 1, 5, "", "-start_date");
|
||||||
"events",
|
|
||||||
1,
|
|
||||||
5,
|
|
||||||
"",
|
|
||||||
"-start_date"
|
|
||||||
);
|
|
||||||
upcomingEvents = eventResponse.items;
|
upcomingEvents = eventResponse.items;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -72,9 +66,7 @@ const currentPage = eventResponse.page;
|
||||||
class="stats shadow-lg bg-base-100 rounded-2xl border border-base-200 hover:border-primary transition-all duration-300 hover:-translate-y-1 transform"
|
class="stats shadow-lg bg-base-100 rounded-2xl border border-base-200 hover:border-primary transition-all duration-300 hover:-translate-y-1 transform"
|
||||||
>
|
>
|
||||||
<div class="stat p-4 md:p-6">
|
<div class="stat p-4 md:p-6">
|
||||||
<div
|
<div class="stat-title text-sm md:text-base font-medium opacity-80">
|
||||||
class="stat-title text-sm md:text-base font-medium opacity-80"
|
|
||||||
>
|
|
||||||
Total Events
|
Total Events
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -94,9 +86,7 @@ const currentPage = eventResponse.page;
|
||||||
class="stats shadow-lg bg-base-100 rounded-2xl border border-base-200 hover:border-secondary transition-all duration-300 hover:-translate-y-1 transform"
|
class="stats shadow-lg bg-base-100 rounded-2xl border border-base-200 hover:border-secondary transition-all duration-300 hover:-translate-y-1 transform"
|
||||||
>
|
>
|
||||||
<div class="stat p-4 md:p-6">
|
<div class="stat p-4 md:p-6">
|
||||||
<div
|
<div class="stat-title text-sm md:text-base font-medium opacity-80">
|
||||||
class="stat-title text-sm md:text-base font-medium opacity-80"
|
|
||||||
>
|
|
||||||
Unique Attendees
|
Unique Attendees
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -116,9 +106,7 @@ const currentPage = eventResponse.page;
|
||||||
class="stats shadow-lg bg-base-100 rounded-2xl border border-base-200 hover:border-accent transition-all duration-300 hover:-translate-y-1 transform sm:col-span-2 md:col-span-1"
|
class="stats shadow-lg bg-base-100 rounded-2xl border border-base-200 hover:border-accent transition-all duration-300 hover:-translate-y-1 transform sm:col-span-2 md:col-span-1"
|
||||||
>
|
>
|
||||||
<div class="stat p-4 md:p-6">
|
<div class="stat p-4 md:p-6">
|
||||||
<div
|
<div class="stat-title text-sm md:text-base font-medium opacity-80">
|
||||||
class="stat-title text-sm md:text-base font-medium opacity-80"
|
|
||||||
>
|
|
||||||
Recurring Attendees
|
Recurring Attendees
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -155,20 +143,14 @@ const currentPage = eventResponse.page;
|
||||||
class="btn btn-ghost btn-sm md:btn-md gap-2"
|
class="btn btn-ghost btn-sm md:btn-md gap-2"
|
||||||
onclick="window.refreshEvents()"
|
onclick="window.refreshEvents()"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon name="heroicons:arrow-path" class="h-4 w-4 md:h-5 md:w-5" />
|
||||||
name="heroicons:arrow-path"
|
|
||||||
class="h-4 w-4 md:h-5 md:w-5"
|
|
||||||
/>
|
|
||||||
Refresh
|
Refresh
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-primary btn-sm md:btn-md gap-2"
|
class="btn btn-primary btn-sm md:btn-md gap-2"
|
||||||
onclick="window.openEditModal()"
|
onclick="window.openEditModal()"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon name="heroicons:plus" class="h-4 w-4 md:h-5 md:w-5" />
|
||||||
name="heroicons:plus"
|
|
||||||
class="h-4 w-4 md:h-5 md:w-5"
|
|
||||||
/>
|
|
||||||
Add New Event
|
Add New Event
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -182,8 +164,7 @@ const currentPage = eventResponse.page;
|
||||||
<div class="flex flex-wrap gap-4">
|
<div class="flex flex-wrap gap-4">
|
||||||
<div class="form-control w-full sm:w-auto">
|
<div class="form-control w-full sm:w-auto">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span
|
<span class="label-text text-sm md:text-base font-medium"
|
||||||
class="label-text text-sm md:text-base font-medium"
|
|
||||||
>Time Filter</span
|
>Time Filter</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
@ -223,8 +204,7 @@ const currentPage = eventResponse.page;
|
||||||
<!-- Other filters with similar responsive adjustments -->
|
<!-- Other filters with similar responsive adjustments -->
|
||||||
<div class="form-control w-full sm:w-auto">
|
<div class="form-control w-full sm:w-auto">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span
|
<span class="label-text text-sm md:text-base font-medium"
|
||||||
class="label-text text-sm md:text-base font-medium"
|
|
||||||
>Year</span
|
>Year</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
@ -254,8 +234,7 @@ const currentPage = eventResponse.page;
|
||||||
>
|
>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label cursor-pointer">
|
<label class="label cursor-pointer">
|
||||||
<span class="label-text">All Years</span
|
<span class="label-text">All Years</span>
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="checkbox"
|
class="checkbox"
|
||||||
|
@ -273,8 +252,7 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
<div class="form-control w-full sm:w-auto">
|
<div class="form-control w-full sm:w-auto">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span
|
<span class="label-text text-sm md:text-base font-medium"
|
||||||
class="label-text text-sm md:text-base font-medium"
|
|
||||||
>Quarter</span
|
>Quarter</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
@ -284,9 +262,7 @@ const currentPage = eventResponse.page;
|
||||||
class="btn btn-sm m-1 w-[180px] justify-between items-center"
|
class="btn btn-sm m-1 w-[180px] justify-between items-center"
|
||||||
>
|
>
|
||||||
<div class="flex-1 text-left truncate">
|
<div class="flex-1 text-left truncate">
|
||||||
<span id="quarterFilterLabel"
|
<span id="quarterFilterLabel">All Quarters</span>
|
||||||
>All Quarters</span
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
@ -307,9 +283,7 @@ const currentPage = eventResponse.page;
|
||||||
>
|
>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label cursor-pointer">
|
<label class="label cursor-pointer">
|
||||||
<span class="label-text"
|
<span class="label-text">All Quarters</span>
|
||||||
>All Quarters</span
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="checkbox"
|
class="checkbox"
|
||||||
|
@ -321,41 +295,25 @@ const currentPage = eventResponse.page;
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label cursor-pointer">
|
<label class="label cursor-pointer">
|
||||||
<span class="label-text">Fall</span>
|
<span class="label-text">Fall</span>
|
||||||
<input
|
<input type="checkbox" class="checkbox" value="fall" />
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
value="fall"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label cursor-pointer">
|
<label class="label cursor-pointer">
|
||||||
<span class="label-text">Winter</span>
|
<span class="label-text">Winter</span>
|
||||||
<input
|
<input type="checkbox" class="checkbox" value="winter" />
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
value="winter"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label cursor-pointer">
|
<label class="label cursor-pointer">
|
||||||
<span class="label-text">Spring</span>
|
<span class="label-text">Spring</span>
|
||||||
<input
|
<input type="checkbox" class="checkbox" value="spring" />
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
value="spring"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label cursor-pointer">
|
<label class="label cursor-pointer">
|
||||||
<span class="label-text">Summer</span>
|
<span class="label-text">Summer</span>
|
||||||
<input
|
<input type="checkbox" class="checkbox" value="summer" />
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
value="summer"
|
|
||||||
/>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -364,8 +322,7 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
<div class="form-control w-full sm:w-auto">
|
<div class="form-control w-full sm:w-auto">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span
|
<span class="label-text text-sm md:text-base font-medium"
|
||||||
class="label-text text-sm md:text-base font-medium"
|
|
||||||
>Published</span
|
>Published</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
@ -431,8 +388,7 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
<div class="form-control w-full sm:w-auto">
|
<div class="form-control w-full sm:w-auto">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span
|
<span class="label-text text-sm md:text-base font-medium"
|
||||||
class="label-text text-sm md:text-base font-medium"
|
|
||||||
>Has Files</span
|
>Has Files</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
@ -498,8 +454,7 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
<div class="form-control w-full sm:w-auto">
|
<div class="form-control w-full sm:w-auto">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span
|
<span class="label-text text-sm md:text-base font-medium"
|
||||||
class="label-text text-sm md:text-base font-medium"
|
|
||||||
>Has Food</span
|
>Has Food</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
|
@ -569,9 +524,7 @@ const currentPage = eventResponse.page;
|
||||||
<div class="flex flex-col sm:flex-row gap-4 mb-4">
|
<div class="flex flex-col sm:flex-row gap-4 mb-4">
|
||||||
<div class="form-control flex-1">
|
<div class="form-control flex-1">
|
||||||
<div class="join w-full">
|
<div class="join w-full">
|
||||||
<div
|
<div class="join-item bg-base-200 flex items-center px-3">
|
||||||
class="join-item bg-base-200 flex items-center px-3"
|
|
||||||
>
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="h-4 w-4 md:h-5 md:w-5 opacity-70"
|
class="h-4 w-4 md:h-5 md:w-5 opacity-70"
|
||||||
|
@ -618,29 +571,22 @@ const currentPage = eventResponse.page;
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Pagination -->
|
<!-- Pagination -->
|
||||||
<div
|
<div class="flex justify-center mt-4 md:mt-6" id="paginationContainer">
|
||||||
class="flex justify-center mt-4 md:mt-6"
|
|
||||||
id="paginationContainer"
|
|
||||||
>
|
|
||||||
<div class="join">
|
<div class="join">
|
||||||
<button
|
<button class="join-item btn btn-xs md:btn-sm" id="firstPageBtn"
|
||||||
class="join-item btn btn-xs md:btn-sm"
|
>«</button
|
||||||
id="firstPageBtn">«</button
|
|
||||||
>
|
>
|
||||||
<button
|
<button class="join-item btn btn-xs md:btn-sm" id="prevPageBtn"
|
||||||
class="join-item btn btn-xs md:btn-sm"
|
>‹</button
|
||||||
id="prevPageBtn">‹</button
|
|
||||||
>
|
>
|
||||||
<button class="join-item btn btn-xs md:btn-sm"
|
<button class="join-item btn btn-xs md:btn-sm"
|
||||||
>Page <span id="currentPageNumber">1</span></button
|
>Page <span id="currentPageNumber">1</span></button
|
||||||
>
|
>
|
||||||
<button
|
<button class="join-item btn btn-xs md:btn-sm" id="nextPageBtn"
|
||||||
class="join-item btn btn-xs md:btn-sm"
|
>›</button
|
||||||
id="nextPageBtn">›</button
|
|
||||||
>
|
>
|
||||||
<button
|
<button class="join-item btn btn-xs md:btn-sm" id="lastPageBtn"
|
||||||
class="join-item btn btn-xs md:btn-sm"
|
>»</button
|
||||||
id="lastPageBtn">»</button
|
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -735,10 +681,7 @@ const currentPage = eventResponse.page;
|
||||||
<div class="modal-box max-w-4xl">
|
<div class="modal-box max-w-4xl">
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex justify-between items-center mb-4">
|
||||||
<h3 class="font-bold text-lg" id="attendeesModalTitle"></h3>
|
<h3 class="font-bold text-lg" id="attendeesModalTitle"></h3>
|
||||||
<button
|
<button class="btn btn-circle btn-ghost" onclick="attendeesModal.close()">
|
||||||
class="btn btn-circle btn-ghost"
|
|
||||||
onclick="attendeesModal.close()"
|
|
||||||
>
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="h-6 w-6"
|
class="h-6 w-6"
|
||||||
|
@ -840,9 +783,7 @@ const currentPage = eventResponse.page;
|
||||||
) {
|
) {
|
||||||
auth.setUpdating(true);
|
auth.setUpdating(true);
|
||||||
const response = await get.getAll<Event>("events");
|
const response = await get.getAll<Event>("events");
|
||||||
cachedEvents = response.map((event) =>
|
cachedEvents = response.map((event) => Get.convertUTCToLocal(event));
|
||||||
Get.convertUTCToLocal(event)
|
|
||||||
);
|
|
||||||
lastCacheUpdate = now;
|
lastCacheUpdate = now;
|
||||||
|
|
||||||
// Initialize year filter options from cache
|
// Initialize year filter options from cache
|
||||||
|
@ -852,8 +793,7 @@ const currentPage = eventResponse.page;
|
||||||
years.add(year);
|
years.add(year);
|
||||||
});
|
});
|
||||||
|
|
||||||
const yearCheckboxes =
|
const yearCheckboxes = document.getElementById("yearCheckboxes");
|
||||||
document.getElementById("yearCheckboxes");
|
|
||||||
if (yearCheckboxes) {
|
if (yearCheckboxes) {
|
||||||
const sortedYears = Array.from(years).sort((a, b) => b - a);
|
const sortedYears = Array.from(years).sort((a, b) => b - a);
|
||||||
yearCheckboxes.innerHTML = sortedYears
|
yearCheckboxes.innerHTML = sortedYears
|
||||||
|
@ -863,18 +803,16 @@ const currentPage = eventResponse.page;
|
||||||
<span class="label-text">${year}</span>
|
<span class="label-text">${year}</span>
|
||||||
<input type="checkbox" class="checkbox" value="${year}" />
|
<input type="checkbox" class="checkbox" value="${year}" />
|
||||||
</label>
|
</label>
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
// Add event listeners to checkboxes
|
// Add event listeners to checkboxes
|
||||||
const allYearsCheckbox = document.querySelector(
|
const allYearsCheckbox = document.querySelector(
|
||||||
'input[type="checkbox"][value="all"]'
|
'input[type="checkbox"][value="all"]',
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
const yearInputs = Array.from(
|
const yearInputs = Array.from(
|
||||||
yearCheckboxes.querySelectorAll(
|
yearCheckboxes.querySelectorAll('input[type="checkbox"]'),
|
||||||
'input[type="checkbox"]'
|
|
||||||
)
|
|
||||||
) as HTMLInputElement[];
|
) as HTMLInputElement[];
|
||||||
|
|
||||||
if (allYearsCheckbox) {
|
if (allYearsCheckbox) {
|
||||||
|
@ -885,9 +823,8 @@ const currentPage = eventResponse.page;
|
||||||
input.checked = false;
|
input.checked = false;
|
||||||
});
|
});
|
||||||
filterState.year = ["all"];
|
filterState.year = ["all"];
|
||||||
document.getElementById(
|
document.getElementById("yearFilterLabel")!.textContent =
|
||||||
"yearFilterLabel"
|
"All Years";
|
||||||
)!.textContent = "All Years";
|
|
||||||
}
|
}
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
fetchEvents();
|
fetchEvents();
|
||||||
|
@ -903,15 +840,12 @@ const currentPage = eventResponse.page;
|
||||||
if (checkedYears.length === 0) {
|
if (checkedYears.length === 0) {
|
||||||
allYearsCheckbox.checked = true;
|
allYearsCheckbox.checked = true;
|
||||||
filterState.year = ["all"];
|
filterState.year = ["all"];
|
||||||
document.getElementById(
|
document.getElementById("yearFilterLabel")!.textContent =
|
||||||
"yearFilterLabel"
|
"All Years";
|
||||||
)!.textContent = "All Years";
|
|
||||||
} else {
|
} else {
|
||||||
allYearsCheckbox.checked = false;
|
allYearsCheckbox.checked = false;
|
||||||
filterState.year = checkedYears;
|
filterState.year = checkedYears;
|
||||||
document.getElementById(
|
document.getElementById("yearFilterLabel")!.textContent =
|
||||||
"yearFilterLabel"
|
|
||||||
)!.textContent =
|
|
||||||
checkedYears.length === 1
|
checkedYears.length === 1
|
||||||
? checkedYears[0]
|
? checkedYears[0]
|
||||||
: `${checkedYears.length} Years Selected`;
|
: `${checkedYears.length} Years Selected`;
|
||||||
|
@ -1010,8 +944,7 @@ const currentPage = eventResponse.page;
|
||||||
const eventEnd = new Date(event.end_date).toISOString();
|
const eventEnd = new Date(event.end_date).toISOString();
|
||||||
|
|
||||||
// Time filter
|
// Time filter
|
||||||
if (filterState.time === "upcoming" && eventStart <= now)
|
if (filterState.time === "upcoming" && eventStart <= now) return false;
|
||||||
return false;
|
|
||||||
if (filterState.time === "past" && eventEnd >= now) return false;
|
if (filterState.time === "past" && eventEnd >= now) return false;
|
||||||
if (
|
if (
|
||||||
filterState.time === "ongoing" &&
|
filterState.time === "ongoing" &&
|
||||||
|
@ -1028,7 +961,7 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Check if either the start year or end year matches any selected year
|
// Check if either the start year or end year matches any selected year
|
||||||
const yearMatches = filterState.year.some(
|
const yearMatches = filterState.year.some(
|
||||||
(year) => year === eventStartYear || year === eventEndYear
|
(year) => year === eventStartYear || year === eventEndYear,
|
||||||
);
|
);
|
||||||
if (!yearMatches) return false;
|
if (!yearMatches) return false;
|
||||||
}
|
}
|
||||||
|
@ -1065,8 +998,7 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Published filter
|
// Published filter
|
||||||
if (filterState.published !== "all") {
|
if (filterState.published !== "all") {
|
||||||
if ((filterState.published === "yes") !== event.published)
|
if ((filterState.published === "yes") !== event.published) return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has Files filter
|
// Has Files filter
|
||||||
|
@ -1077,8 +1009,7 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Has Food filter
|
// Has Food filter
|
||||||
if (filterState.hasFood !== "all") {
|
if (filterState.hasFood !== "all") {
|
||||||
if ((filterState.hasFood === "yes") !== event.has_food)
|
if ((filterState.hasFood === "yes") !== event.has_food) return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search query
|
// Search query
|
||||||
|
@ -1093,7 +1024,7 @@ const currentPage = eventResponse.page;
|
||||||
event.event_name.toLowerCase().includes(term) ||
|
event.event_name.toLowerCase().includes(term) ||
|
||||||
event.event_code.toLowerCase().includes(term) ||
|
event.event_code.toLowerCase().includes(term) ||
|
||||||
event.location.toLowerCase().includes(term) ||
|
event.location.toLowerCase().includes(term) ||
|
||||||
event.event_description.toLowerCase().includes(term)
|
event.event_description.toLowerCase().includes(term),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1105,9 +1036,7 @@ const currentPage = eventResponse.page;
|
||||||
// Fetch and display events using cached data
|
// Fetch and display events using cached data
|
||||||
async function fetchEvents() {
|
async function fetchEvents() {
|
||||||
const eventsList = document.getElementById("eventsList");
|
const eventsList = document.getElementById("eventsList");
|
||||||
const paginationContainer = document.getElementById(
|
const paginationContainer = document.getElementById("paginationContainer");
|
||||||
"paginationContainer"
|
|
||||||
);
|
|
||||||
if (!eventsList || !paginationContainer) return;
|
if (!eventsList || !paginationContainer) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1133,8 +1062,7 @@ const currentPage = eventResponse.page;
|
||||||
// Sort events by start date (newest first)
|
// Sort events by start date (newest first)
|
||||||
filteredEvents.sort(
|
filteredEvents.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
new Date(b.start_date).getTime() -
|
new Date(b.start_date).getTime() - new Date(a.start_date).getTime(),
|
||||||
new Date(a.start_date).getTime()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Calculate pagination
|
// Calculate pagination
|
||||||
|
@ -1146,19 +1074,18 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Update pagination UI
|
// Update pagination UI
|
||||||
const firstPageBtn = document.getElementById(
|
const firstPageBtn = document.getElementById(
|
||||||
"firstPageBtn"
|
"firstPageBtn",
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
const prevPageBtn = document.getElementById(
|
const prevPageBtn = document.getElementById(
|
||||||
"prevPageBtn"
|
"prevPageBtn",
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
const nextPageBtn = document.getElementById(
|
const nextPageBtn = document.getElementById(
|
||||||
"nextPageBtn"
|
"nextPageBtn",
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
const lastPageBtn = document.getElementById(
|
const lastPageBtn = document.getElementById(
|
||||||
"lastPageBtn"
|
"lastPageBtn",
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
const currentPageNumber =
|
const currentPageNumber = document.getElementById("currentPageNumber");
|
||||||
document.getElementById("currentPageNumber");
|
|
||||||
|
|
||||||
if (firstPageBtn) firstPageBtn.disabled = currentPage <= 1;
|
if (firstPageBtn) firstPageBtn.disabled = currentPage <= 1;
|
||||||
if (prevPageBtn) prevPageBtn.disabled = currentPage <= 1;
|
if (prevPageBtn) prevPageBtn.disabled = currentPage <= 1;
|
||||||
|
@ -1206,12 +1133,8 @@ const currentPage = eventResponse.page;
|
||||||
console.error("Error formatting date:", e);
|
console.error("Error formatting date:", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
const locationStr = event.location
|
const locationStr = event.location ? `${event.location}` : "";
|
||||||
? `${event.location}`
|
const codeStr = event.event_code ? `${event.event_code}` : "";
|
||||||
: "";
|
|
||||||
const codeStr = event.event_code
|
|
||||||
? `${event.event_code}`
|
|
||||||
: "";
|
|
||||||
const detailsStr = [locationStr, codeStr]
|
const detailsStr = [locationStr, codeStr]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(" | code: ");
|
.join(" | code: ");
|
||||||
|
@ -1276,8 +1199,7 @@ const currentPage = eventResponse.page;
|
||||||
async function calculateQuarterlyStats() {
|
async function calculateQuarterlyStats() {
|
||||||
try {
|
try {
|
||||||
const { start: termStart, end: termEnd } = getCurrentTerm();
|
const { start: termStart, end: termEnd } = getCurrentTerm();
|
||||||
const { start: quarterStart, end: quarterEnd } =
|
const { start: quarterStart, end: quarterEnd } = getCurrentQuarter();
|
||||||
getCurrentQuarter();
|
|
||||||
|
|
||||||
// Update quarter name in UI
|
// Update quarter name in UI
|
||||||
const quarterNameEl = document.getElementById("quarterName");
|
const quarterNameEl = document.getElementById("quarterName");
|
||||||
|
@ -1318,19 +1240,17 @@ const currentPage = eventResponse.page;
|
||||||
});
|
});
|
||||||
|
|
||||||
quarterlyStats.recurringAttendees = Array.from(
|
quarterlyStats.recurringAttendees = Array.from(
|
||||||
quarterAttendees.values()
|
quarterAttendees.values(),
|
||||||
).filter((count) => count > 1).length;
|
).filter((count) => count > 1).length;
|
||||||
|
|
||||||
// Update the UI
|
// Update the UI
|
||||||
const totalEventsEl = document.getElementById("totalEvents");
|
const totalEventsEl = document.getElementById("totalEvents");
|
||||||
const uniqueAttendeesEl =
|
const uniqueAttendeesEl = document.getElementById("uniqueAttendees");
|
||||||
document.getElementById("uniqueAttendees");
|
|
||||||
const recurringAttendeesEl =
|
const recurringAttendeesEl =
|
||||||
document.getElementById("recurringAttendees");
|
document.getElementById("recurringAttendees");
|
||||||
|
|
||||||
if (totalEventsEl)
|
if (totalEventsEl)
|
||||||
totalEventsEl.textContent =
|
totalEventsEl.textContent = quarterlyStats.totalEvents.toString();
|
||||||
quarterlyStats.totalEvents.toString();
|
|
||||||
if (uniqueAttendeesEl)
|
if (uniqueAttendeesEl)
|
||||||
uniqueAttendeesEl.textContent =
|
uniqueAttendeesEl.textContent =
|
||||||
quarterlyStats.uniqueAttendees.toString();
|
quarterlyStats.uniqueAttendees.toString();
|
||||||
|
@ -1383,24 +1303,20 @@ const currentPage = eventResponse.page;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Year filter
|
// Year filter
|
||||||
document
|
document.getElementById("yearCheckboxes")?.addEventListener("change", (e) => {
|
||||||
.getElementById("yearCheckboxes")
|
|
||||||
?.addEventListener("change", (e) => {
|
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
if (!target.matches('input[type="checkbox"]')) return;
|
if (!target.matches('input[type="checkbox"]')) return;
|
||||||
|
|
||||||
const allYearsCheckbox = target
|
const allYearsCheckbox = target
|
||||||
.closest(".dropdown-content")
|
.closest(".dropdown-content")
|
||||||
?.querySelector(
|
?.querySelector(
|
||||||
'input[type="checkbox"][value="all"]'
|
'input[type="checkbox"][value="all"]',
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
|
|
||||||
const yearInputs = Array.from(
|
const yearInputs = Array.from(
|
||||||
target
|
target
|
||||||
.closest(".dropdown-content")
|
.closest(".dropdown-content")
|
||||||
?.querySelectorAll(
|
?.querySelectorAll('#yearCheckboxes input[type="checkbox"]') || [],
|
||||||
'#yearCheckboxes input[type="checkbox"]'
|
|
||||||
) || []
|
|
||||||
) as HTMLInputElement[];
|
) as HTMLInputElement[];
|
||||||
|
|
||||||
if (target.value === "all" && target.checked) {
|
if (target.value === "all" && target.checked) {
|
||||||
|
@ -1408,8 +1324,7 @@ const currentPage = eventResponse.page;
|
||||||
input.checked = false;
|
input.checked = false;
|
||||||
});
|
});
|
||||||
filterState.year = ["all"];
|
filterState.year = ["all"];
|
||||||
document.getElementById("yearFilterLabel")!.textContent =
|
document.getElementById("yearFilterLabel")!.textContent = "All Years";
|
||||||
"All Years";
|
|
||||||
} else {
|
} else {
|
||||||
const checkedYears = yearInputs
|
const checkedYears = yearInputs
|
||||||
.filter((inp) => inp.checked)
|
.filter((inp) => inp.checked)
|
||||||
|
@ -1418,8 +1333,7 @@ const currentPage = eventResponse.page;
|
||||||
if (checkedYears.length === 0) {
|
if (checkedYears.length === 0) {
|
||||||
allYearsCheckbox.checked = true;
|
allYearsCheckbox.checked = true;
|
||||||
filterState.year = ["all"];
|
filterState.year = ["all"];
|
||||||
document.getElementById("yearFilterLabel")!.textContent =
|
document.getElementById("yearFilterLabel")!.textContent = "All Years";
|
||||||
"All Years";
|
|
||||||
} else {
|
} else {
|
||||||
allYearsCheckbox.checked = false;
|
allYearsCheckbox.checked = false;
|
||||||
filterState.year = checkedYears;
|
filterState.year = checkedYears;
|
||||||
|
@ -1439,9 +1353,7 @@ const currentPage = eventResponse.page;
|
||||||
?.addEventListener("change", (e) => {
|
?.addEventListener("change", (e) => {
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
const yearInputs = Array.from(
|
const yearInputs = Array.from(
|
||||||
document.querySelectorAll(
|
document.querySelectorAll('#yearCheckboxes input[type="checkbox"]'),
|
||||||
'#yearCheckboxes input[type="checkbox"]'
|
|
||||||
)
|
|
||||||
) as HTMLInputElement[];
|
) as HTMLInputElement[];
|
||||||
|
|
||||||
if (target.checked) {
|
if (target.checked) {
|
||||||
|
@ -1449,8 +1361,7 @@ const currentPage = eventResponse.page;
|
||||||
input.checked = false;
|
input.checked = false;
|
||||||
});
|
});
|
||||||
filterState.year = ["all"];
|
filterState.year = ["all"];
|
||||||
document.getElementById("yearFilterLabel")!.textContent =
|
document.getElementById("yearFilterLabel")!.textContent = "All Years";
|
||||||
"All Years";
|
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
fetchEvents();
|
fetchEvents();
|
||||||
}
|
}
|
||||||
|
@ -1466,15 +1377,15 @@ const currentPage = eventResponse.page;
|
||||||
const allQuartersCheckbox = target
|
const allQuartersCheckbox = target
|
||||||
.closest("#quarterDropdownContent")
|
.closest("#quarterDropdownContent")
|
||||||
?.querySelector(
|
?.querySelector(
|
||||||
'input[type="checkbox"][value="all"]'
|
'input[type="checkbox"][value="all"]',
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
|
|
||||||
const quarterInputs = Array.from(
|
const quarterInputs = Array.from(
|
||||||
target
|
target
|
||||||
.closest("#quarterDropdownContent")
|
.closest("#quarterDropdownContent")
|
||||||
?.querySelectorAll('input[type="checkbox"]') || []
|
?.querySelectorAll('input[type="checkbox"]') || [],
|
||||||
).filter(
|
).filter(
|
||||||
(inp) => (inp as HTMLInputElement).value !== "all"
|
(inp) => (inp as HTMLInputElement).value !== "all",
|
||||||
) as HTMLInputElement[];
|
) as HTMLInputElement[];
|
||||||
|
|
||||||
if (target.value === "all" && target.checked) {
|
if (target.value === "all" && target.checked) {
|
||||||
|
@ -1516,8 +1427,8 @@ const currentPage = eventResponse.page;
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
filterState.published = target.value;
|
filterState.published = target.value;
|
||||||
document.getElementById("publishedFilterLabel")!.textContent =
|
document.getElementById("publishedFilterLabel")!.textContent =
|
||||||
target.parentElement?.querySelector(".label-text")
|
target.parentElement?.querySelector(".label-text")?.textContent ||
|
||||||
?.textContent || "All";
|
"All";
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
fetchEvents();
|
fetchEvents();
|
||||||
});
|
});
|
||||||
|
@ -1531,8 +1442,8 @@ const currentPage = eventResponse.page;
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
filterState.hasFiles = target.value;
|
filterState.hasFiles = target.value;
|
||||||
document.getElementById("hasFilesFilterLabel")!.textContent =
|
document.getElementById("hasFilesFilterLabel")!.textContent =
|
||||||
target.parentElement?.querySelector(".label-text")
|
target.parentElement?.querySelector(".label-text")?.textContent ||
|
||||||
?.textContent || "All";
|
"All";
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
fetchEvents();
|
fetchEvents();
|
||||||
});
|
});
|
||||||
|
@ -1546,8 +1457,8 @@ const currentPage = eventResponse.page;
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
filterState.hasFood = target.value;
|
filterState.hasFood = target.value;
|
||||||
document.getElementById("hasFoodFilterLabel")!.textContent =
|
document.getElementById("hasFoodFilterLabel")!.textContent =
|
||||||
target.parentElement?.querySelector(".label-text")
|
target.parentElement?.querySelector(".label-text")?.textContent ||
|
||||||
?.textContent || "All";
|
"All";
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
fetchEvents();
|
fetchEvents();
|
||||||
});
|
});
|
||||||
|
@ -1576,9 +1487,7 @@ const currentPage = eventResponse.page;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per page select
|
// Per page select
|
||||||
document
|
document.getElementById("perPageSelect")?.addEventListener("change", (e) => {
|
||||||
.getElementById("perPageSelect")
|
|
||||||
?.addEventListener("change", (e) => {
|
|
||||||
const target = e.target as HTMLSelectElement;
|
const target = e.target as HTMLSelectElement;
|
||||||
perPage = parseInt(target.value);
|
perPage = parseInt(target.value);
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
|
@ -1590,7 +1499,7 @@ const currentPage = eventResponse.page;
|
||||||
window.addEventListener("DOMContentLoaded", () => {
|
window.addEventListener("DOMContentLoaded", () => {
|
||||||
// Reset all filters to defaults
|
// Reset all filters to defaults
|
||||||
const timeFilterAll = document.querySelector(
|
const timeFilterAll = document.querySelector(
|
||||||
'input[name="timeFilter"][value="all"]'
|
'input[name="timeFilter"][value="all"]',
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
if (timeFilterAll) {
|
if (timeFilterAll) {
|
||||||
// Ensure the radio button is properly checked
|
// Ensure the radio button is properly checked
|
||||||
|
@ -1600,10 +1509,10 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Reset year filter
|
// Reset year filter
|
||||||
const yearAllCheckbox = document.querySelector(
|
const yearAllCheckbox = document.querySelector(
|
||||||
'input[type="checkbox"][value="all"]'
|
'input[type="checkbox"][value="all"]',
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
const yearCheckboxes = document.querySelectorAll(
|
const yearCheckboxes = document.querySelectorAll(
|
||||||
'#yearCheckboxes input[type="checkbox"]'
|
'#yearCheckboxes input[type="checkbox"]',
|
||||||
);
|
);
|
||||||
if (yearAllCheckbox && yearCheckboxes) {
|
if (yearAllCheckbox && yearCheckboxes) {
|
||||||
yearAllCheckbox.checked = true;
|
yearAllCheckbox.checked = true;
|
||||||
|
@ -1611,16 +1520,15 @@ const currentPage = eventResponse.page;
|
||||||
(checkbox as HTMLInputElement).checked = false;
|
(checkbox as HTMLInputElement).checked = false;
|
||||||
});
|
});
|
||||||
filterState.year = ["all"];
|
filterState.year = ["all"];
|
||||||
document.getElementById("yearFilterLabel")!.textContent =
|
document.getElementById("yearFilterLabel")!.textContent = "All Years";
|
||||||
"All Years";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset quarter filter
|
// Reset quarter filter
|
||||||
const quarterAllCheckbox = document.querySelector(
|
const quarterAllCheckbox = document.querySelector(
|
||||||
'#quarterDropdownContent input[type="checkbox"][value="all"]'
|
'#quarterDropdownContent input[type="checkbox"][value="all"]',
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
const quarterCheckboxes = document.querySelectorAll(
|
const quarterCheckboxes = document.querySelectorAll(
|
||||||
'#quarterDropdownContent input[type="checkbox"]:not([value="all"])'
|
'#quarterDropdownContent input[type="checkbox"]:not([value="all"])',
|
||||||
);
|
);
|
||||||
if (quarterAllCheckbox && quarterCheckboxes) {
|
if (quarterAllCheckbox && quarterCheckboxes) {
|
||||||
quarterAllCheckbox.checked = true;
|
quarterAllCheckbox.checked = true;
|
||||||
|
@ -1633,27 +1541,27 @@ const currentPage = eventResponse.page;
|
||||||
}
|
}
|
||||||
|
|
||||||
const publishedFilter = document.getElementById(
|
const publishedFilter = document.getElementById(
|
||||||
"publishedFilter"
|
"publishedFilter",
|
||||||
) as HTMLSelectElement;
|
) as HTMLSelectElement;
|
||||||
if (publishedFilter) publishedFilter.value = "all";
|
if (publishedFilter) publishedFilter.value = "all";
|
||||||
|
|
||||||
const hasFilesFilter = document.getElementById(
|
const hasFilesFilter = document.getElementById(
|
||||||
"hasFilesFilter"
|
"hasFilesFilter",
|
||||||
) as HTMLSelectElement;
|
) as HTMLSelectElement;
|
||||||
if (hasFilesFilter) hasFilesFilter.value = "all";
|
if (hasFilesFilter) hasFilesFilter.value = "all";
|
||||||
|
|
||||||
const hasFoodFilter = document.getElementById(
|
const hasFoodFilter = document.getElementById(
|
||||||
"hasFoodFilter"
|
"hasFoodFilter",
|
||||||
) as HTMLSelectElement;
|
) as HTMLSelectElement;
|
||||||
if (hasFoodFilter) hasFoodFilter.value = "all";
|
if (hasFoodFilter) hasFoodFilter.value = "all";
|
||||||
|
|
||||||
const searchInput = document.getElementById(
|
const searchInput = document.getElementById(
|
||||||
"searchInput"
|
"searchInput",
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
if (searchInput) searchInput.value = "";
|
if (searchInput) searchInput.value = "";
|
||||||
|
|
||||||
const perPageSelect = document.getElementById(
|
const perPageSelect = document.getElementById(
|
||||||
"perPageSelect"
|
"perPageSelect",
|
||||||
) as HTMLSelectElement;
|
) as HTMLSelectElement;
|
||||||
if (perPageSelect) perPageSelect.value = "5";
|
if (perPageSelect) perPageSelect.value = "5";
|
||||||
|
|
||||||
|
@ -1683,12 +1591,10 @@ const currentPage = eventResponse.page;
|
||||||
// Update the previewFileInEditModal function
|
// Update the previewFileInEditModal function
|
||||||
window.previewFileInEditModal = async function (
|
window.previewFileInEditModal = async function (
|
||||||
url: string,
|
url: string,
|
||||||
filename: string
|
filename: string,
|
||||||
) {
|
) {
|
||||||
const editFormSection = document.getElementById("editFormSection");
|
const editFormSection = document.getElementById("editFormSection");
|
||||||
const previewSection = document.getElementById(
|
const previewSection = document.getElementById("editModalPreviewSection");
|
||||||
"editModalPreviewSection"
|
|
||||||
);
|
|
||||||
const editFilePreview = document.getElementById("editFilePreview");
|
const editFilePreview = document.getElementById("editFilePreview");
|
||||||
const previewFileName = document.getElementById("editPreviewFileName");
|
const previewFileName = document.getElementById("editPreviewFileName");
|
||||||
const loadingSpinner = document.getElementById("editLoadingSpinner");
|
const loadingSpinner = document.getElementById("editLoadingSpinner");
|
||||||
|
@ -1724,16 +1630,14 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Update the showFilePreview function
|
// Update the showFilePreview function
|
||||||
window.showFilePreview = function (file: { url: string; name: string }) {
|
window.showFilePreview = function (file: { url: string; name: string }) {
|
||||||
console.log("showFilePreview called with:", file);
|
// console.log("showFilePreview called with:", file);
|
||||||
window.previewFile(file.url, file.name);
|
window.previewFile(file.url, file.name);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add backToEditForm function
|
// Add backToEditForm function
|
||||||
window.backToEditForm = function () {
|
window.backToEditForm = function () {
|
||||||
const editFormSection = document.getElementById("editFormSection");
|
const editFormSection = document.getElementById("editFormSection");
|
||||||
const previewSection = document.getElementById(
|
const previewSection = document.getElementById("editModalPreviewSection");
|
||||||
"editModalPreviewSection"
|
|
||||||
);
|
|
||||||
const editFilePreview = document.getElementById("editFilePreview");
|
const editFilePreview = document.getElementById("editFilePreview");
|
||||||
const previewFileName = document.getElementById("editPreviewFileName");
|
const previewFileName = document.getElementById("editPreviewFileName");
|
||||||
|
|
||||||
|
@ -1756,17 +1660,15 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Universal file preview function
|
// Universal file preview function
|
||||||
window.previewFile = function (url: string, filename: string) {
|
window.previewFile = function (url: string, filename: string) {
|
||||||
console.log("previewFile called with:", { url, filename });
|
// console.log("previewFile called with:", { url, filename });
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"filePreviewModal"
|
"filePreviewModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const filePreview = document.getElementById(
|
const filePreview = document.getElementById("officerFilePreview") as any;
|
||||||
"officerFilePreview"
|
|
||||||
) as any;
|
|
||||||
const previewFileName = document.getElementById("previewFileName");
|
const previewFileName = document.getElementById("previewFileName");
|
||||||
|
|
||||||
if (filePreview && modal && previewFileName) {
|
if (filePreview && modal && previewFileName) {
|
||||||
console.log("Found all required elements");
|
// console.log("Found all required elements");
|
||||||
// Update the filename display
|
// Update the filename display
|
||||||
previewFileName.textContent = filename;
|
previewFileName.textContent = filename;
|
||||||
|
|
||||||
|
@ -1774,7 +1676,7 @@ const currentPage = eventResponse.page;
|
||||||
modal.showModal();
|
modal.showModal();
|
||||||
|
|
||||||
// Update the preview component
|
// Update the preview component
|
||||||
console.log("Dispatching updateFilePreview event");
|
// console.log("Dispatching updateFilePreview event");
|
||||||
const event = new CustomEvent("updateFilePreview", {
|
const event = new CustomEvent("updateFilePreview", {
|
||||||
detail: { url, filename },
|
detail: { url, filename },
|
||||||
});
|
});
|
||||||
|
@ -1790,17 +1692,15 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Close file preview
|
// Close file preview
|
||||||
window.closeFilePreview = function () {
|
window.closeFilePreview = function () {
|
||||||
console.log("closeFilePreview called");
|
// console.log("closeFilePreview called");
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"filePreviewModal"
|
"filePreviewModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const filePreview = document.getElementById(
|
const filePreview = document.getElementById("officerFilePreview") as any;
|
||||||
"officerFilePreview"
|
|
||||||
) as any;
|
|
||||||
const previewFileName = document.getElementById("previewFileName");
|
const previewFileName = document.getElementById("previewFileName");
|
||||||
|
|
||||||
if (modal && filePreview && previewFileName) {
|
if (modal && filePreview && previewFileName) {
|
||||||
console.log("Resetting preview and closing modal");
|
// console.log("Resetting preview and closing modal");
|
||||||
// Reset the preview
|
// Reset the preview
|
||||||
const event = new CustomEvent("updateFilePreview", {
|
const event = new CustomEvent("updateFilePreview", {
|
||||||
detail: { url: "", filename: "" },
|
detail: { url: "", filename: "" },
|
||||||
|
@ -1814,7 +1714,7 @@ const currentPage = eventResponse.page;
|
||||||
// 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");
|
||||||
const attendeesContent = document.getElementById("attendeesContent");
|
const attendeesContent = document.getElementById("attendeesContent");
|
||||||
|
@ -1835,11 +1735,7 @@ const currentPage = eventResponse.page;
|
||||||
function updateFilePreviewButtons(files: string[], eventId: string) {
|
function updateFilePreviewButtons(files: string[], eventId: string) {
|
||||||
return files
|
return files
|
||||||
.map((filename) => {
|
.map((filename) => {
|
||||||
const fileUrl = fileManager.getFileUrl(
|
const fileUrl = fileManager.getFileUrl("events", eventId, filename);
|
||||||
"events",
|
|
||||||
eventId,
|
|
||||||
filename
|
|
||||||
);
|
|
||||||
const previewData = JSON.stringify({
|
const previewData = JSON.stringify({
|
||||||
url: fileUrl,
|
url: fileUrl,
|
||||||
name: filename,
|
name: filename,
|
||||||
|
@ -1884,12 +1780,10 @@ const currentPage = eventResponse.page;
|
||||||
if (newFiles && fileInput.files) {
|
if (newFiles && fileInput.files) {
|
||||||
// Get existing files if any
|
// Get existing files if any
|
||||||
const existingFiles = newFiles.querySelectorAll(".file-item");
|
const existingFiles = newFiles.querySelectorAll(".file-item");
|
||||||
const existingFilesArray = Array.from(existingFiles).map(
|
const existingFilesArray = Array.from(existingFiles).map((item) => {
|
||||||
(item) => {
|
|
||||||
const nameSpan = item.querySelector(".file-name");
|
const nameSpan = item.querySelector(".file-name");
|
||||||
return nameSpan ? nameSpan.textContent : "";
|
return nameSpan ? nameSpan.textContent : "";
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
// Store new files in the storage and update UI
|
// Store new files in the storage and update UI
|
||||||
Array.from(fileInput.files)
|
Array.from(fileInput.files)
|
||||||
|
@ -1936,12 +1830,11 @@ const currentPage = eventResponse.page;
|
||||||
const currentFiles = document.getElementById("currentFiles");
|
const currentFiles = document.getElementById("currentFiles");
|
||||||
if (currentFiles) {
|
if (currentFiles) {
|
||||||
const fileElement = currentFiles.querySelector(
|
const fileElement = currentFiles.querySelector(
|
||||||
`[data-filename="${filename}"]`
|
`[data-filename="${filename}"]`,
|
||||||
);
|
);
|
||||||
if (fileElement) {
|
if (fileElement) {
|
||||||
fileElement.classList.add("opacity-50");
|
fileElement.classList.add("opacity-50");
|
||||||
const deleteButton =
|
const deleteButton = fileElement.querySelector(".text-error");
|
||||||
fileElement.querySelector(".text-error");
|
|
||||||
if (deleteButton) {
|
if (deleteButton) {
|
||||||
deleteButton.innerHTML = `
|
deleteButton.innerHTML = `
|
||||||
<button type="button" class="btn btn-ghost btn-xs" onclick="window.undoDeleteFile('${eventId}', '${filename}')">
|
<button type="button" class="btn btn-ghost btn-xs" onclick="window.undoDeleteFile('${eventId}', '${filename}')">
|
||||||
|
@ -1957,7 +1850,7 @@ const currentPage = eventResponse.page;
|
||||||
`File "${filename}" marked for deletion. Save changes to confirm.`,
|
`File "${filename}" marked for deletion. Save changes to confirm.`,
|
||||||
{
|
{
|
||||||
icon: "🗑️",
|
icon: "🗑️",
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to stage file deletion:", error);
|
console.error("Failed to stage file deletion:", error);
|
||||||
|
@ -1973,7 +1866,7 @@ const currentPage = eventResponse.page;
|
||||||
const currentFiles = document.getElementById("currentFiles");
|
const currentFiles = document.getElementById("currentFiles");
|
||||||
if (currentFiles) {
|
if (currentFiles) {
|
||||||
const fileElement = currentFiles.querySelector(
|
const fileElement = currentFiles.querySelector(
|
||||||
`[data-filename="${filename}"]`
|
`[data-filename="${filename}"]`,
|
||||||
);
|
);
|
||||||
if (fileElement) {
|
if (fileElement) {
|
||||||
fileElement.classList.remove("opacity-50");
|
fileElement.classList.remove("opacity-50");
|
||||||
|
@ -2002,7 +1895,7 @@ const currentPage = eventResponse.page;
|
||||||
// Universal file preview function for officer section
|
// Universal file preview function for officer section
|
||||||
window.previewFileOfficer = function (url: string, filename: string) {
|
window.previewFileOfficer = function (url: string, filename: string) {
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"filePreviewModal"
|
"filePreviewModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
|
|
||||||
if (!modal) {
|
if (!modal) {
|
||||||
|
@ -2014,7 +1907,7 @@ const currentPage = eventResponse.page;
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent(FILE_PREVIEW_STATE_CHANGE, {
|
new CustomEvent(FILE_PREVIEW_STATE_CHANGE, {
|
||||||
detail: { url, filename },
|
detail: { url, filename },
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Show modal after event dispatch
|
// Show modal after event dispatch
|
||||||
|
@ -2026,7 +1919,7 @@ const currentPage = eventResponse.page;
|
||||||
// Close file preview for officer section
|
// Close file preview for officer section
|
||||||
window.closeFilePreviewOfficer = function () {
|
window.closeFilePreviewOfficer = function () {
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"filePreviewModal"
|
"filePreviewModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const previewContent = document.getElementById("previewContent");
|
const previewContent = document.getElementById("previewContent");
|
||||||
|
|
||||||
|
@ -2049,7 +1942,7 @@ const currentPage = eventResponse.page;
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent(FILE_PREVIEW_STATE_CHANGE, {
|
new CustomEvent(FILE_PREVIEW_STATE_CHANGE, {
|
||||||
detail: { url: "", filename: "" },
|
detail: { url: "", filename: "" },
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Close modal after cleanup
|
// Close modal after cleanup
|
||||||
|
@ -2083,18 +1976,14 @@ const currentPage = eventResponse.page;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get fresh URL from FileManager to ensure we have the latest
|
// Get fresh URL from FileManager to ensure we have the latest
|
||||||
const freshUrl = fileManager.getFileUrl(
|
const freshUrl = fileManager.getFileUrl("events", eventId, file.name);
|
||||||
"events",
|
|
||||||
eventId,
|
|
||||||
file.name
|
|
||||||
);
|
|
||||||
|
|
||||||
// Show the preview with fresh URL
|
// Show the preview with fresh URL
|
||||||
window.previewFileOfficer(freshUrl, file.name);
|
window.previewFileOfficer(freshUrl, file.name);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch fresh file data:", error);
|
console.error("Failed to fetch fresh file data:", error);
|
||||||
toast.error(
|
toast.error(
|
||||||
"Failed to load file preview. The file may have been deleted or modified."
|
"Failed to load file preview. The file may have been deleted or modified.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2104,10 +1993,10 @@ const currentPage = eventResponse.page;
|
||||||
|
|
||||||
// Add openAttendeesModal function
|
// Add openAttendeesModal function
|
||||||
window.openAttendeesModal = function (event: Event) {
|
window.openAttendeesModal = function (event: Event) {
|
||||||
console.log("Opening attendees modal for event:", event.id);
|
// console.log("Opening attendees modal for event:", event.id);
|
||||||
|
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"attendeesModal"
|
"attendeesModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
const modalTitle = document.getElementById("attendeesModalTitle");
|
const modalTitle = document.getElementById("attendeesModalTitle");
|
||||||
|
|
||||||
|
@ -2126,7 +2015,7 @@ const currentPage = eventResponse.page;
|
||||||
eventId: event.id,
|
eventId: event.id,
|
||||||
eventName: event.event_name,
|
eventName: event.event_name,
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Show modal
|
// Show modal
|
||||||
|
@ -2136,7 +2025,7 @@ const currentPage = eventResponse.page;
|
||||||
// Add event listeners when the document loads
|
// Add event listeners when the document loads
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const modal = document.getElementById(
|
const modal = document.getElementById(
|
||||||
"filePreviewModal"
|
"filePreviewModal",
|
||||||
) as HTMLDialogElement;
|
) as HTMLDialogElement;
|
||||||
if (modal) {
|
if (modal) {
|
||||||
// Handle modal close via backdrop
|
// Handle modal close via backdrop
|
||||||
|
|
|
@ -287,7 +287,7 @@ export default function Attendees() {
|
||||||
const fetchEventData = async () => {
|
const fetchEventData = async () => {
|
||||||
if (!eventId || !auth.isAuthenticated()) {
|
if (!eventId || !auth.isAuthenticated()) {
|
||||||
if (!auth.isAuthenticated()) {
|
if (!auth.isAuthenticated()) {
|
||||||
console.log('User not authenticated');
|
// console.log('User not authenticated');
|
||||||
setError('Authentication required');
|
setError('Authentication required');
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -631,7 +631,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) {
|
||||||
has_food: eventData.has_food || false
|
has_food: eventData.has_food || false
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Event data loaded successfully:", eventData);
|
// console.log("Event data loaded successfully:", eventData);
|
||||||
} else {
|
} else {
|
||||||
setEvent({
|
setEvent({
|
||||||
id: '',
|
id: '',
|
||||||
|
@ -784,7 +784,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) {
|
||||||
|
|
||||||
// 1. Remove files marked for deletion
|
// 1. Remove files marked for deletion
|
||||||
if (filesToDelete.size > 0) {
|
if (filesToDelete.size > 0) {
|
||||||
console.log(`Removing ${filesToDelete.size} files from event ${event.id}`);
|
// console.log(`Removing ${filesToDelete.size} files from event ${event.id}`);
|
||||||
currentFiles = currentFiles.filter(file => !filesToDelete.has(file));
|
currentFiles = currentFiles.filter(file => !filesToDelete.has(file));
|
||||||
|
|
||||||
// Update the files field first to remove deleted files
|
// Update the files field first to remove deleted files
|
||||||
|
@ -797,7 +797,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) {
|
||||||
|
|
||||||
// 2. Add new files one by one to preserve existing ones
|
// 2. Add new files one by one to preserve existing ones
|
||||||
if (selectedFiles.size > 0) {
|
if (selectedFiles.size > 0) {
|
||||||
console.log(`Adding ${selectedFiles.size} new files to event ${event.id}`);
|
// console.log(`Adding ${selectedFiles.size} new files to event ${event.id}`);
|
||||||
|
|
||||||
// Convert Map to array of File objects
|
// Convert Map to array of File objects
|
||||||
const newFiles = Array.from(selectedFiles.values());
|
const newFiles = Array.from(selectedFiles.values());
|
||||||
|
@ -849,7 +849,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) {
|
||||||
|
|
||||||
// Then upload files if any
|
// Then upload files if any
|
||||||
if (selectedFiles.size > 0 && newEvent?.id) {
|
if (selectedFiles.size > 0 && newEvent?.id) {
|
||||||
console.log(`Adding ${selectedFiles.size} files to new event ${newEvent.id}`);
|
// console.log(`Adding ${selectedFiles.size} files to new event ${newEvent.id}`);
|
||||||
|
|
||||||
// Convert Map to array of File objects
|
// Convert Map to array of File objects
|
||||||
const newFiles = Array.from(selectedFiles.values());
|
const newFiles = Array.from(selectedFiles.values());
|
||||||
|
|
|
@ -31,7 +31,7 @@ if (auth.isAuthenticated()) {
|
||||||
userEventRequests = await get.getAll<EventRequest>(
|
userEventRequests = await get.getAll<EventRequest>(
|
||||||
Collections.EVENT_REQUESTS,
|
Collections.EVENT_REQUESTS,
|
||||||
`requested_user="${userId}"`,
|
`requested_user="${userId}"`,
|
||||||
"-created"
|
"-created",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -46,8 +46,8 @@ if (auth.isAuthenticated()) {
|
||||||
<h1 class="text-3xl font-bold text-white mb-2">Event Request Form</h1>
|
<h1 class="text-3xl font-bold text-white mb-2">Event Request Form</h1>
|
||||||
<p class="text-gray-300 mb-4">
|
<p class="text-gray-300 mb-4">
|
||||||
Submit your event request at least 6 weeks before your event. After
|
Submit your event request at least 6 weeks before your event. After
|
||||||
submitting, please notify PR and/or Coordinators in the #-events
|
submitting, please notify PR and/or Coordinators in the #-events Slack
|
||||||
Slack channel.
|
channel.
|
||||||
</p>
|
</p>
|
||||||
<div class="bg-base-300/50 p-4 rounded-lg text-sm text-gray-300">
|
<div class="bg-base-300/50 p-4 rounded-lg text-sm text-gray-300">
|
||||||
<p class="font-medium mb-2">This form includes sections for:</p>
|
<p class="font-medium mb-2">This form includes sections for:</p>
|
||||||
|
@ -109,10 +109,7 @@ if (auth.isAuthenticated()) {
|
||||||
|
|
||||||
{
|
{
|
||||||
!error && (
|
!error && (
|
||||||
<UserEventRequests
|
<UserEventRequests client:load eventRequests={userEventRequests} />
|
||||||
client:load
|
|
||||||
eventRequests={userEventRequests}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -171,10 +168,10 @@ if (auth.isAuthenticated()) {
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
// Define the global function immediately to ensure it's available
|
// Define the global function immediately to ensure it's available
|
||||||
window.showEventRequestFormPreview = function (formData) {
|
window.showEventRequestFormPreview = function (formData) {
|
||||||
console.log(
|
// console.log(
|
||||||
"Global showEventRequestFormPreview called with data",
|
// "Global showEventRequestFormPreview called with data",
|
||||||
formData
|
// formData
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Remove any elements that might be obstructing the view
|
// Remove any elements that might be obstructing the view
|
||||||
const removeObstructions = () => {
|
const removeObstructions = () => {
|
||||||
|
@ -204,12 +201,12 @@ if (auth.isAuthenticated()) {
|
||||||
|
|
||||||
// Dispatch event to show modal
|
// Dispatch event to show modal
|
||||||
document.dispatchEvent(event);
|
document.dispatchEvent(event);
|
||||||
console.log("showEventRequestPreviewModal event dispatched");
|
// console.log("showEventRequestPreviewModal event dispatched");
|
||||||
|
|
||||||
// Ensure modal container is visible
|
// Ensure modal container is visible
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const modalContainer = document.getElementById(
|
const modalContainer = document.getElementById(
|
||||||
"event-request-preview-modal-container"
|
"event-request-preview-modal-container",
|
||||||
);
|
);
|
||||||
if (modalContainer) {
|
if (modalContainer) {
|
||||||
modalContainer.style.zIndex = "99999";
|
modalContainer.style.zIndex = "99999";
|
||||||
|
@ -226,8 +223,7 @@ if (auth.isAuthenticated()) {
|
||||||
document.body.style.overflow = "auto";
|
document.body.style.overflow = "auto";
|
||||||
|
|
||||||
// Ensure the modal content is properly sized
|
// Ensure the modal content is properly sized
|
||||||
const modalContent =
|
const modalContent = modalContainer.querySelector("div > div > div");
|
||||||
modalContainer.querySelector("div > div > div");
|
|
||||||
if (modalContent) {
|
if (modalContent) {
|
||||||
modalContent.style.maxWidth = "90vw";
|
modalContent.style.maxWidth = "90vw";
|
||||||
modalContent.style.width = "100%";
|
modalContent.style.width = "100%";
|
||||||
|
@ -261,30 +257,26 @@ if (auth.isAuthenticated()) {
|
||||||
await dataSync.syncCollection(
|
await dataSync.syncCollection(
|
||||||
Collections.EVENT_REQUESTS,
|
Collections.EVENT_REQUESTS,
|
||||||
`requested_user="${userId}"`,
|
`requested_user="${userId}"`,
|
||||||
"-created"
|
"-created",
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
"Initial data sync complete for user event requests"
|
|
||||||
);
|
);
|
||||||
|
// console.log("Initial data sync complete for user event requests");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error during initial data sync:", err);
|
// console.error("Error during initial data sync:", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const formTab = document.getElementById("form-tab");
|
const formTab = document.getElementById("form-tab");
|
||||||
const submissionsTab = document.getElementById("submissions-tab");
|
const submissionsTab = document.getElementById("submissions-tab");
|
||||||
const formContent = document.getElementById("form-content");
|
const formContent = document.getElementById("form-content");
|
||||||
const submissionsContent = document.getElementById(
|
const submissionsContent = document.getElementById("submissions-content");
|
||||||
"submissions-content"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Function to switch tabs
|
// Function to switch tabs
|
||||||
const switchTab = (
|
const switchTab = (
|
||||||
activeTab: HTMLElement,
|
activeTab: HTMLElement,
|
||||||
activeContent: HTMLElement,
|
activeContent: HTMLElement,
|
||||||
inactiveTab: HTMLElement,
|
inactiveTab: HTMLElement,
|
||||||
inactiveContent: HTMLElement
|
inactiveContent: HTMLElement,
|
||||||
) => {
|
) => {
|
||||||
// Update tab classes
|
// Update tab classes
|
||||||
activeTab.classList.add("tab-active");
|
activeTab.classList.add("tab-active");
|
||||||
|
@ -305,24 +297,14 @@ if (auth.isAuthenticated()) {
|
||||||
formTab?.addEventListener("click", (e) => {
|
formTab?.addEventListener("click", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (formContent && submissionsContent && submissionsTab) {
|
if (formContent && submissionsContent && submissionsTab) {
|
||||||
switchTab(
|
switchTab(formTab, formContent, submissionsTab, submissionsContent);
|
||||||
formTab,
|
|
||||||
formContent,
|
|
||||||
submissionsTab,
|
|
||||||
submissionsContent
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
submissionsTab?.addEventListener("click", (e) => {
|
submissionsTab?.addEventListener("click", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (formContent && submissionsContent && formTab) {
|
if (formContent && submissionsContent && formTab) {
|
||||||
switchTab(
|
switchTab(submissionsTab, submissionsContent, formTab, formContent);
|
||||||
submissionsTab,
|
|
||||||
submissionsContent,
|
|
||||||
formTab,
|
|
||||||
formContent
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ export const EventRequestFormPreviewModal: React.FC = () => {
|
||||||
|
|
||||||
// Function to handle showing the modal
|
// Function to handle showing the modal
|
||||||
const showModal = (data: any) => {
|
const showModal = (data: any) => {
|
||||||
console.log('showModal called with data', data);
|
// console.log('showModal called with data', data);
|
||||||
setFormData(data);
|
setFormData(data);
|
||||||
setIsOpen(true);
|
setIsOpen(true);
|
||||||
};
|
};
|
||||||
|
@ -24,23 +24,23 @@ export const EventRequestFormPreviewModal: React.FC = () => {
|
||||||
|
|
||||||
// Define the global function
|
// Define the global function
|
||||||
window.showEventRequestFormPreview = (data: any) => {
|
window.showEventRequestFormPreview = (data: any) => {
|
||||||
console.log('Global showEventRequestFormPreview called with data', data);
|
// console.log('Global showEventRequestFormPreview called with data', data);
|
||||||
showModal(data);
|
showModal(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen for the custom event as a fallback
|
// Listen for the custom event as a fallback
|
||||||
const handleShowModal = (event: CustomEvent) => {
|
const handleShowModal = (event: CustomEvent) => {
|
||||||
console.log('Received showEventRequestPreviewModal event', event.detail);
|
// console.log('Received showEventRequestPreviewModal event', event.detail);
|
||||||
if (event.detail && event.detail.formData) {
|
if (event.detail && event.detail.formData) {
|
||||||
showModal(event.detail.formData);
|
showModal(event.detail.formData);
|
||||||
} else {
|
} else {
|
||||||
console.error('Event detail or formData is missing', event.detail);
|
// console.error('Event detail or formData is missing', event.detail);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add event listener
|
// Add event listener
|
||||||
document.addEventListener('showEventRequestPreviewModal', handleShowModal as EventListener);
|
document.addEventListener('showEventRequestPreviewModal', handleShowModal as EventListener);
|
||||||
console.log('Event listener for showEventRequestPreviewModal added');
|
// console.log('Event listener for showEventRequestPreviewModal added');
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -53,12 +53,12 @@ export const EventRequestFormPreviewModal: React.FC = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.removeEventListener('showEventRequestPreviewModal', handleShowModal as EventListener);
|
document.removeEventListener('showEventRequestPreviewModal', handleShowModal as EventListener);
|
||||||
console.log('Event listener for showEventRequestPreviewModal removed');
|
// console.log('Event listener for showEventRequestPreviewModal removed');
|
||||||
};
|
};
|
||||||
}, []); // Empty dependency array - only run once on mount
|
}, []); // Empty dependency array - only run once on mount
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
console.log('Modal closed');
|
// console.log('Modal closed');
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ const EventRequestFormPreview: React.FC<EventRequestFormPreviewProps> = ({
|
||||||
const parsedData = JSON.parse(savedData);
|
const parsedData = JSON.parse(savedData);
|
||||||
setFormData(parsedData);
|
setFormData(parsedData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error parsing saved form data:', e);
|
// console.error('Error parsing saved form data:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
|
@ -69,7 +69,7 @@ const UserEventRequests: React.FC<UserEventRequestsProps> = ({ eventRequests: in
|
||||||
// Listen for tab visibility changes and refresh data when tab becomes visible
|
// Listen for tab visibility changes and refresh data when tab becomes visible
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleTabVisible = () => {
|
const handleTabVisible = () => {
|
||||||
console.log("Tab became visible, refreshing event requests...");
|
// console.log("Tab became visible, refreshing event requests...");
|
||||||
refreshEventRequests();
|
refreshEventRequests();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -411,19 +411,19 @@ const UserEventRequests: React.FC<UserEventRequestsProps> = ({ eventRequests: in
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
console.log('Full Preview button clicked', selectedRequest);
|
// console.log('Full Preview button clicked', selectedRequest);
|
||||||
try {
|
try {
|
||||||
// Direct call to the global function
|
// Direct call to the global function
|
||||||
if (typeof window.showEventRequestFormPreview === 'function') {
|
if (typeof window.showEventRequestFormPreview === 'function') {
|
||||||
window.showEventRequestFormPreview(selectedRequest);
|
window.showEventRequestFormPreview(selectedRequest);
|
||||||
} else {
|
} else {
|
||||||
console.error('showEventRequestFormPreview is not a function', window.showEventRequestFormPreview);
|
// console.log('Fallback: showEventRequestPreviewModal event dispatched');
|
||||||
// Fallback to event dispatch if function is not available
|
// Fallback to event dispatch if function is not available
|
||||||
const event = new CustomEvent("showEventRequestPreviewModal", {
|
const event = new CustomEvent("showEventRequestPreviewModal", {
|
||||||
detail: { formData: selectedRequest }
|
detail: { formData: selectedRequest }
|
||||||
});
|
});
|
||||||
document.dispatchEvent(event);
|
document.dispatchEvent(event);
|
||||||
console.log('Fallback: showEventRequestPreviewModal event dispatched');
|
// console.log('Fallback: showEventRequestPreviewModal event dispatched');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error showing full preview:', error);
|
console.error('Error showing full preview:', error);
|
||||||
|
|
|
@ -37,7 +37,7 @@ try {
|
||||||
// Don't check authentication here - let the client component handle it
|
// Don't check authentication here - let the client component handle it
|
||||||
// The server-side check is causing issues when the token is valid client-side but not server-side
|
// The server-side check is causing issues when the token is valid client-side but not server-side
|
||||||
|
|
||||||
console.log("Fetching event requests in Astro component...");
|
// console.log("Fetching event requests in Astro component...");
|
||||||
// Expand the requested_user field to get user details
|
// Expand the requested_user field to get user details
|
||||||
allEventRequests = await get
|
allEventRequests = await get
|
||||||
.getAll<ExtendedEventRequest>(Collections.EVENT_REQUESTS, "", "-created", {
|
.getAll<ExtendedEventRequest>(Collections.EVENT_REQUESTS, "", "-created", {
|
||||||
|
@ -49,9 +49,9 @@ try {
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(
|
// console.log(
|
||||||
`Fetched ${allEventRequests.length} event requests in Astro component`,
|
// `Fetched ${allEventRequests.length} event requests in Astro component`,
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Process the event requests to add the requested_user_expand property
|
// Process the event requests to add the requested_user_expand property
|
||||||
allEventRequests = allEventRequests.map((request) => {
|
allEventRequests = allEventRequests.map((request) => {
|
||||||
|
@ -172,9 +172,9 @@ try {
|
||||||
"-created",
|
"-created",
|
||||||
{ expand: "requested_user" },
|
{ expand: "requested_user" },
|
||||||
);
|
);
|
||||||
console.log("Initial data sync complete");
|
// console.log("Initial data sync complete");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error during initial data sync:", err);
|
// console.error("Error during initial data sync:", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for error message in the UI
|
// Check for error message in the UI
|
||||||
|
@ -183,9 +183,9 @@ try {
|
||||||
errorElement &&
|
errorElement &&
|
||||||
errorElement.textContent?.includes("Authentication error")
|
errorElement.textContent?.includes("Authentication error")
|
||||||
) {
|
) {
|
||||||
console.log(
|
// console.log(
|
||||||
"Authentication error detected in UI, redirecting to login...",
|
// "Authentication error detected in UI, redirecting to login...",
|
||||||
);
|
// );
|
||||||
// Redirect to login page after a short delay
|
// Redirect to login page after a short delay
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = "/login";
|
window.location.href = "/login";
|
||||||
|
@ -196,13 +196,13 @@ try {
|
||||||
// Also check if we have any event requests
|
// Also check if we have any event requests
|
||||||
const tableContainer = document.querySelector(".event-table-container");
|
const tableContainer = document.querySelector(".event-table-container");
|
||||||
if (tableContainer) {
|
if (tableContainer) {
|
||||||
console.log(
|
// console.log(
|
||||||
"Event table container found, component should load normally",
|
// "Event table container found, component should load normally",
|
||||||
);
|
// );
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
// console.log(
|
||||||
"Event table container not found, might be an issue with rendering",
|
// "Event table container not found, might be an issue with rendering",
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -56,7 +56,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
|
||||||
// Don't check authentication here - try to fetch anyway
|
// Don't check authentication here - try to fetch anyway
|
||||||
// The token might be valid for the API even if isAuthenticated() returns false
|
// The token might be valid for the API even if isAuthenticated() returns false
|
||||||
|
|
||||||
console.log("Fetching event requests...");
|
// console.log("Fetching event requests...");
|
||||||
|
|
||||||
// Use DataSyncService to get data from IndexedDB with forced sync
|
// Use DataSyncService to get data from IndexedDB with forced sync
|
||||||
const updatedRequests = await dataSync.getData<ExtendedEventRequest>(
|
const updatedRequests = await dataSync.getData<ExtendedEventRequest>(
|
||||||
|
@ -67,12 +67,12 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
|
||||||
'requested_user'
|
'requested_user'
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Fetched ${updatedRequests.length} event requests`);
|
// console.log(`Fetched ${updatedRequests.length} event requests`);
|
||||||
|
|
||||||
setEventRequests(updatedRequests);
|
setEventRequests(updatedRequests);
|
||||||
applyFilters(updatedRequests);
|
applyFilters(updatedRequests);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error refreshing event requests:', error);
|
// console.error('Error refreshing event requests:', error);
|
||||||
toast.error('Failed to refresh event requests');
|
toast.error('Failed to refresh event requests');
|
||||||
} finally {
|
} finally {
|
||||||
setIsRefreshing(false);
|
setIsRefreshing(false);
|
||||||
|
@ -169,7 +169,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
|
||||||
const eventRequest = eventRequests.find(req => req.id === id);
|
const eventRequest = eventRequests.find(req => req.id === id);
|
||||||
const eventName = eventRequest?.name || 'Event';
|
const eventName = eventRequest?.name || 'Event';
|
||||||
|
|
||||||
console.error('Error updating status:', error);
|
// console.error('Error updating status:', error);
|
||||||
toast.error(`Failed to update status for "${eventName}"`);
|
toast.error(`Failed to update status for "${eventName}"`);
|
||||||
throw error; // Re-throw the error to be caught by the caller
|
throw error; // Re-throw the error to be caught by the caller
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
|
||||||
// Toast is now shown in updateEventRequestStatus
|
// Toast is now shown in updateEventRequestStatus
|
||||||
closeUpdateModal();
|
closeUpdateModal();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in handleUpdateStatus:', error);
|
// console.error('Error in handleUpdateStatus:', error);
|
||||||
// Toast is now shown in updateEventRequestStatus
|
// Toast is now shown in updateEventRequestStatus
|
||||||
// Keep modal open so user can try again
|
// Keep modal open so user can try again
|
||||||
}
|
}
|
||||||
|
@ -273,14 +273,14 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
|
||||||
|
|
||||||
// Check if we're authenticated
|
// Check if we're authenticated
|
||||||
if (!auth.isAuthenticated()) {
|
if (!auth.isAuthenticated()) {
|
||||||
console.log("Authentication check failed - attempting to continue anyway");
|
// console.log("Authentication check failed - attempting to continue anyway");
|
||||||
|
|
||||||
// Don't show error or redirect immediately - try to refresh first
|
// Don't show error or redirect immediately - try to refresh first
|
||||||
try {
|
try {
|
||||||
// Try to refresh event requests anyway - the token might be valid
|
// Try to refresh event requests anyway - the token might be valid
|
||||||
await refreshEventRequests();
|
await refreshEventRequests();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to refresh after auth check:", err);
|
// console.error("Failed to refresh after auth check:", err);
|
||||||
toast.error("Authentication error. Please log in again.");
|
toast.error("Authentication error. Please log in again.");
|
||||||
|
|
||||||
// Only redirect if refresh fails
|
// Only redirect if refresh fails
|
||||||
|
@ -289,7 +289,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("Authentication check passed");
|
// console.log("Authentication check passed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
|
||||||
// Listen for tab visibility changes and refresh data when tab becomes visible
|
// Listen for tab visibility changes and refresh data when tab becomes visible
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleTabVisible = () => {
|
const handleTabVisible = () => {
|
||||||
console.log("Tab became visible, refreshing event requests...");
|
// console.log("Tab became visible, refreshing event requests...");
|
||||||
refreshEventRequests();
|
refreshEventRequests();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default function ShowProfileLogs() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsFetchingAll(true);
|
setIsFetchingAll(true);
|
||||||
console.log("Fetching logs for user:", userId);
|
// console.log("Fetching logs for user:", userId);
|
||||||
|
|
||||||
// Use DataSyncService to fetch logs
|
// Use DataSyncService to fetch logs
|
||||||
const dataSync = DataSyncService.getInstance();
|
const dataSync = DataSyncService.getInstance();
|
||||||
|
@ -70,15 +70,15 @@ export default function ShowProfileLogs() {
|
||||||
"-created"
|
"-created"
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("Fetched logs:", fetchedLogs.length);
|
// console.log("Fetched logs:", fetchedLogs.length);
|
||||||
|
|
||||||
if (fetchedLogs.length === 0) {
|
if (fetchedLogs.length === 0) {
|
||||||
// If no logs found, try to fetch directly from PocketBase
|
// If no logs found, try to fetch directly from PocketBase
|
||||||
console.log("No logs found in IndexedDB, trying direct fetch from PocketBase");
|
// console.log("No logs found in IndexedDB, trying direct fetch from PocketBase");
|
||||||
try {
|
try {
|
||||||
const sendLog = SendLog.getInstance();
|
const sendLog = SendLog.getInstance();
|
||||||
const directLogs = await sendLog.getUserLogs(userId);
|
const directLogs = await sendLog.getUserLogs(userId);
|
||||||
console.log("Direct fetch logs:", directLogs.length);
|
// console.log("Direct fetch logs:", directLogs.length);
|
||||||
|
|
||||||
if (directLogs.length > 0) {
|
if (directLogs.length > 0) {
|
||||||
setAllLogs(directLogs);
|
setAllLogs(directLogs);
|
||||||
|
@ -90,7 +90,7 @@ export default function ShowProfileLogs() {
|
||||||
setTotalLogs(fetchedLogs.length);
|
setTotalLogs(fetchedLogs.length);
|
||||||
}
|
}
|
||||||
} catch (directError) {
|
} catch (directError) {
|
||||||
console.error("Failed to fetch logs directly:", directError);
|
// console.error("Failed to fetch logs directly:", directError);
|
||||||
setAllLogs(fetchedLogs);
|
setAllLogs(fetchedLogs);
|
||||||
setTotalPages(Math.ceil(fetchedLogs.length / LOGS_PER_PAGE));
|
setTotalPages(Math.ceil(fetchedLogs.length / LOGS_PER_PAGE));
|
||||||
setTotalLogs(fetchedLogs.length);
|
setTotalLogs(fetchedLogs.length);
|
||||||
|
@ -101,7 +101,7 @@ export default function ShowProfileLogs() {
|
||||||
setTotalLogs(fetchedLogs.length);
|
setTotalLogs(fetchedLogs.length);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch logs:", error);
|
// console.error("Failed to fetch logs:", error);
|
||||||
setError("Error loading activity");
|
setError("Error loading activity");
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -134,7 +134,7 @@ export default function ShowProfileLogs() {
|
||||||
// Update displayed logs whenever filtered results change
|
// Update displayed logs whenever filtered results change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLogs(filteredLogs);
|
setLogs(filteredLogs);
|
||||||
console.log("Filtered logs updated:", filteredLogs.length, "logs");
|
// console.log("Filtered logs updated:", filteredLogs.length, "logs");
|
||||||
}, [filteredLogs]);
|
}, [filteredLogs]);
|
||||||
|
|
||||||
// Debounced search handler
|
// Debounced search handler
|
||||||
|
@ -178,12 +178,12 @@ export default function ShowProfileLogs() {
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
// Check if logs were loaded
|
// Check if logs were loaded
|
||||||
if (allLogs.length === 0) {
|
if (allLogs.length === 0) {
|
||||||
console.log("No logs found after initial fetch, trying direct fetch");
|
// console.log("No logs found after initial fetch, trying direct fetch");
|
||||||
await directFetchLogs();
|
await directFetchLogs();
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load logs with retry:", error);
|
// console.error("Failed to load logs with retry:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,14 +200,14 @@ export default function ShowProfileLogs() {
|
||||||
|
|
||||||
// Check if the logs collection exists and has any records
|
// Check if the logs collection exists and has any records
|
||||||
const result = await pb.collection(Collections.LOGS).getList(1, 1);
|
const result = await pb.collection(Collections.LOGS).getList(1, 1);
|
||||||
console.log("Logs collection check:", {
|
// console.log("Logs collection check:", {
|
||||||
totalItems: result.totalItems,
|
// totalItems: result.totalItems,
|
||||||
page: result.page,
|
// page: result.page,
|
||||||
perPage: result.perPage,
|
// perPage: result.perPage,
|
||||||
totalPages: result.totalPages
|
// totalPages: result.totalPages
|
||||||
});
|
// });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to check logs collection:", error);
|
// console.error("Failed to check logs collection:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ export default function ShowProfileLogs() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Direct fetching logs for user:", userId);
|
// console.log("Direct fetching logs for user:", userId);
|
||||||
|
|
||||||
// Fetch logs directly from PocketBase
|
// Fetch logs directly from PocketBase
|
||||||
const result = await pb.collection(Collections.LOGS).getList<Log>(1, 100, {
|
const result = await pb.collection(Collections.LOGS).getList<Log>(1, 100, {
|
||||||
|
@ -264,10 +264,10 @@ export default function ShowProfileLogs() {
|
||||||
expand: "user"
|
expand: "user"
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Direct fetch result:", {
|
// console.log("Direct fetch result:", {
|
||||||
totalItems: result.totalItems,
|
// totalItems: result.totalItems,
|
||||||
items: result.items.length
|
// items: result.items.length
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (result.items.length > 0) {
|
if (result.items.length > 0) {
|
||||||
setAllLogs(result.items);
|
setAllLogs(result.items);
|
||||||
|
@ -275,7 +275,7 @@ export default function ShowProfileLogs() {
|
||||||
setTotalLogs(result.items.length);
|
setTotalLogs(result.items.length);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to direct fetch logs:", error);
|
// console.error("Failed to direct fetch logs:", error);
|
||||||
setError("Error loading activity");
|
setError("Error loading activity");
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -315,13 +315,13 @@ export default function ShowProfileLogs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug logs
|
// Debug logs
|
||||||
console.log("Render state:", {
|
// console.log("Render state:", {
|
||||||
logsLength: logs.length,
|
// logsLength: logs.length,
|
||||||
allLogsLength: allLogs.length,
|
// allLogsLength: allLogs.length,
|
||||||
searchQuery,
|
// searchQuery,
|
||||||
loading,
|
// loading,
|
||||||
currentPage
|
// currentPage
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (allLogs.length === 0 && !searchQuery && !loading) {
|
if (allLogs.length === 0 && !searchQuery && !loading) {
|
||||||
return (
|
return (
|
||||||
|
@ -348,10 +348,10 @@ export default function ShowProfileLogs() {
|
||||||
"Test log created for debugging",
|
"Test log created for debugging",
|
||||||
userId
|
userId
|
||||||
);
|
);
|
||||||
console.log("Created test log");
|
// console.log("Created test log");
|
||||||
setTimeout(() => fetchLogs(true), 1000);
|
setTimeout(() => fetchLogs(true), 1000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to create test log:", error);
|
// console.error("Failed to create test log:", error);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -13,14 +13,6 @@ const logtoEndpoint = import.meta.env.LOGTO_ENDPOINT;
|
||||||
const logtoTokenEndpoint = import.meta.env.LOGTO_TOKEN_ENDPOINT;
|
const logtoTokenEndpoint = import.meta.env.LOGTO_TOKEN_ENDPOINT;
|
||||||
const logtoApiEndpoint = import.meta.env.LOGTO_API_ENDPOINT;
|
const logtoApiEndpoint = import.meta.env.LOGTO_API_ENDPOINT;
|
||||||
|
|
||||||
// Log environment variables for debugging
|
|
||||||
console.log("Environment variables in Astro file:");
|
|
||||||
console.log("LOGTO_APP_ID:", logtoAppId);
|
|
||||||
console.log("LOGTO_APP_SECRET:", logtoAppSecret);
|
|
||||||
console.log("LOGTO_ENDPOINT:", logtoEndpoint);
|
|
||||||
console.log("LOGTO_TOKEN_ENDPOINT:", logtoTokenEndpoint);
|
|
||||||
console.log("LOGTO_API_ENDPOINT:", logtoApiEndpoint);
|
|
||||||
|
|
||||||
// Define fallback values if environment variables are not set
|
// Define fallback values if environment variables are not set
|
||||||
const safeLogtoAppId = logtoAppId || "missing_app_id";
|
const safeLogtoAppId = logtoAppId || "missing_app_id";
|
||||||
const safeLogtoAppSecret = logtoAppSecret || "missing_app_secret";
|
const safeLogtoAppSecret = logtoAppSecret || "missing_app_secret";
|
||||||
|
|
|
@ -162,7 +162,7 @@ export default function DisplaySettings() {
|
||||||
|
|
||||||
if (Object.keys(updateData).length > 0) {
|
if (Object.keys(updateData).length > 0) {
|
||||||
await update.updateFields(Collections.USERS, userId, updateData);
|
await update.updateFields(Collections.USERS, userId, updateData);
|
||||||
console.log('Initialized default display and accessibility settings');
|
// console.log('Initialized default display and accessibility settings');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initializing default settings:', error);
|
console.error('Error initializing default settings:', error);
|
||||||
|
|
|
@ -67,7 +67,7 @@ export default function NotificationSettings() {
|
||||||
{ notification_preferences: JSON.stringify(DEFAULT_NOTIFICATION_PREFERENCES) }
|
{ notification_preferences: JSON.stringify(DEFAULT_NOTIFICATION_PREFERENCES) }
|
||||||
);
|
);
|
||||||
setPreferences(DEFAULT_NOTIFICATION_PREFERENCES);
|
setPreferences(DEFAULT_NOTIFICATION_PREFERENCES);
|
||||||
console.log('Initialized default notification preferences');
|
// console.log('Initialized default notification preferences');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initializing default notification preferences:', error);
|
console.error('Error initializing default notification preferences:', error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,29 +45,7 @@ export default function PasswordChangeSettings({
|
||||||
const logtoTokenEndpoint = envLogtoTokenEndpoint || propLogtoTokenEndpoint;
|
const logtoTokenEndpoint = envLogtoTokenEndpoint || propLogtoTokenEndpoint;
|
||||||
const logtoApiEndpoint = envLogtoApiEndpoint || propLogtoApiEndpoint;
|
const logtoApiEndpoint = envLogtoApiEndpoint || propLogtoApiEndpoint;
|
||||||
|
|
||||||
// Log props and environment variables for debugging
|
|
||||||
useEffect(() => {
|
|
||||||
console.log("PasswordChangeSettings props and env vars:");
|
|
||||||
console.log("Props - logtoAppId:", propLogtoAppId);
|
|
||||||
console.log("Props - logtoAppSecret:", propLogtoAppSecret);
|
|
||||||
console.log("Props - logtoEndpoint:", propLogtoEndpoint);
|
|
||||||
console.log("Props - logtoTokenEndpoint:", propLogtoTokenEndpoint);
|
|
||||||
console.log("Props - logtoApiEndpoint:", propLogtoApiEndpoint);
|
|
||||||
console.log("Env - LOGTO_APP_ID:", envLogtoAppId);
|
|
||||||
console.log("Env - LOGTO_APP_SECRET:", envLogtoAppSecret);
|
|
||||||
console.log("Env - LOGTO_ENDPOINT:", envLogtoEndpoint);
|
|
||||||
console.log("Env - LOGTO_TOKEN_ENDPOINT:", envLogtoTokenEndpoint);
|
|
||||||
console.log("Env - LOGTO_API_ENDPOINT:", envLogtoApiEndpoint);
|
|
||||||
console.log("Using - logtoAppId:", logtoAppId);
|
|
||||||
console.log("Using - logtoAppSecret:", logtoAppSecret);
|
|
||||||
console.log("Using - logtoEndpoint:", logtoEndpoint);
|
|
||||||
console.log("Using - logtoTokenEndpoint:", logtoTokenEndpoint);
|
|
||||||
console.log("Using - logtoApiEndpoint:", logtoApiEndpoint);
|
|
||||||
}, [
|
|
||||||
propLogtoAppId, propLogtoAppSecret, propLogtoEndpoint, propLogtoTokenEndpoint, propLogtoApiEndpoint,
|
|
||||||
envLogtoAppId, envLogtoAppSecret, envLogtoEndpoint, envLogtoTokenEndpoint, envLogtoApiEndpoint,
|
|
||||||
logtoAppId, logtoAppSecret, logtoEndpoint, logtoTokenEndpoint, logtoApiEndpoint
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Get the user's Logto ID on component mount
|
// Get the user's Logto ID on component mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -80,17 +58,17 @@ export default function PasswordChangeSettings({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Current user:", user);
|
// console.log("Current user:", user);
|
||||||
const pb = auth.getPocketBase();
|
const pb = auth.getPocketBase();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const externalAuthRecord = await pb.collection('_externalAuths').getFirstListItem(`recordRef="${user.id}" && provider="oidc"`);
|
const externalAuthRecord = await pb.collection('_externalAuths').getFirstListItem(`recordRef="${user.id}" && provider="oidc"`);
|
||||||
console.log("Found external auth record:", externalAuthRecord);
|
// console.log("Found external auth record:", externalAuthRecord);
|
||||||
|
|
||||||
const userId = externalAuthRecord.providerId;
|
const userId = externalAuthRecord.providerId;
|
||||||
if (userId) {
|
if (userId) {
|
||||||
setLogtoUserId(userId);
|
setLogtoUserId(userId);
|
||||||
console.log("Set Logto user ID:", userId);
|
// console.log("Set Logto user ID:", userId);
|
||||||
} else {
|
} else {
|
||||||
console.error("No providerId found in external auth record");
|
console.error("No providerId found in external auth record");
|
||||||
toast.error("Could not determine your user ID. Please try again later or contact support.");
|
toast.error("Could not determine your user ID. Please try again later or contact support.");
|
||||||
|
@ -153,7 +131,7 @@ export default function PasswordChangeSettings({
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/check-env');
|
const response = await fetch('/api/check-env');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log("Environment variables status:", data);
|
// console.log("Environment variables status:", data);
|
||||||
|
|
||||||
// Check if all required environment variables are set
|
// Check if all required environment variables are set
|
||||||
const { envStatus } = data;
|
const { envStatus } = data;
|
||||||
|
@ -244,7 +222,7 @@ export default function PasswordChangeSettings({
|
||||||
const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
|
const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
|
||||||
if (iframeDocument) {
|
if (iframeDocument) {
|
||||||
const responseText = iframeDocument.body.innerText;
|
const responseText = iframeDocument.body.innerText;
|
||||||
console.log("Response from iframe:", responseText);
|
// console.log("Response from iframe:", responseText);
|
||||||
|
|
||||||
if (responseText) {
|
if (responseText) {
|
||||||
try {
|
try {
|
||||||
|
@ -308,7 +286,7 @@ export default function PasswordChangeSettings({
|
||||||
} else {
|
} else {
|
||||||
// Use the fetch API with JSON
|
// Use the fetch API with JSON
|
||||||
const endpoint = '/api/change-password';
|
const endpoint = '/api/change-password';
|
||||||
console.log(`Calling server-side API endpoint: ${endpoint}`);
|
// console.log(`Calling server-side API endpoint: ${endpoint}`);
|
||||||
|
|
||||||
// Ensure we have the Logto user ID
|
// Ensure we have the Logto user ID
|
||||||
if (!logtoUserId) {
|
if (!logtoUserId) {
|
||||||
|
@ -317,13 +295,13 @@ export default function PasswordChangeSettings({
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the values we're about to use
|
// Log the values we're about to use
|
||||||
console.log("Values being used for API call:");
|
// console.log("Values being used for API call:");
|
||||||
console.log("- logtoUserId:", logtoUserId);
|
// console.log("- logtoUserId:", logtoUserId);
|
||||||
console.log("- newPassword:", formData.newPassword ? "[PRESENT]" : "[MISSING]");
|
// console.log("- newPassword:", formData.newPassword ? "[PRESENT]" : "[MISSING]");
|
||||||
console.log("- logtoAppId:", logtoAppId);
|
// console.log("- logtoAppId:", logtoAppId);
|
||||||
console.log("- logtoAppSecret:", logtoAppSecret ? "[PRESENT]" : "[MISSING]");
|
// console.log("- logtoAppSecret:", logtoAppSecret ? "[PRESENT]" : "[MISSING]");
|
||||||
console.log("- logtoTokenEndpoint:", logtoTokenEndpoint);
|
// console.log("- logtoTokenEndpoint:", logtoTokenEndpoint);
|
||||||
console.log("- logtoApiEndpoint:", logtoApiEndpoint);
|
// console.log("- logtoApiEndpoint:", logtoApiEndpoint);
|
||||||
|
|
||||||
// Prepare request data with explicit values (not relying on variable references that might be undefined)
|
// Prepare request data with explicit values (not relying on variable references that might be undefined)
|
||||||
const requestData = {
|
const requestData = {
|
||||||
|
@ -336,12 +314,12 @@ export default function PasswordChangeSettings({
|
||||||
logtoApiEndpoint: logtoApiEndpoint || logtoEndpoint
|
logtoApiEndpoint: logtoApiEndpoint || logtoEndpoint
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("Request data:", {
|
// console.log("Request data:", {
|
||||||
...requestData,
|
// ...requestData,
|
||||||
currentPassword: "[REDACTED]",
|
// currentPassword: "[REDACTED]",
|
||||||
newPassword: "[REDACTED]",
|
// newPassword: "[REDACTED]",
|
||||||
logtoAppSecret: "[REDACTED]"
|
// logtoAppSecret: "[REDACTED]"
|
||||||
});
|
// });
|
||||||
|
|
||||||
// Validate request data before sending
|
// Validate request data before sending
|
||||||
if (!requestData.userId) {
|
if (!requestData.userId) {
|
||||||
|
@ -368,7 +346,7 @@ export default function PasswordChangeSettings({
|
||||||
|
|
||||||
// Stringify the request data to ensure it's valid JSON
|
// Stringify the request data to ensure it's valid JSON
|
||||||
const requestBody = JSON.stringify(requestData);
|
const requestBody = JSON.stringify(requestData);
|
||||||
console.log("Request body (stringified):", requestBody);
|
// console.log("Request body (stringified):", requestBody);
|
||||||
|
|
||||||
// Create a debug object to display in the UI
|
// Create a debug object to display in the UI
|
||||||
const debugObj = {
|
const debugObj = {
|
||||||
|
@ -394,13 +372,13 @@ export default function PasswordChangeSettings({
|
||||||
body: requestBody
|
body: requestBody
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Response status:", response.status);
|
// console.log("Response status:", response.status);
|
||||||
|
|
||||||
// Process the response
|
// Process the response
|
||||||
let result: any;
|
let result: any;
|
||||||
try {
|
try {
|
||||||
const responseText = await response.text();
|
const responseText = await response.text();
|
||||||
console.log("Raw response:", responseText);
|
// console.log("Raw response:", responseText);
|
||||||
|
|
||||||
if (responseText) {
|
if (responseText) {
|
||||||
result = JSON.parse(responseText);
|
result = JSON.parse(responseText);
|
||||||
|
@ -408,7 +386,7 @@ export default function PasswordChangeSettings({
|
||||||
result = { success: false, message: 'Empty response from server' };
|
result = { success: false, message: 'Empty response from server' };
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("API response:", result);
|
// console.log("API response:", result);
|
||||||
|
|
||||||
// Add response to debug info
|
// Add response to debug info
|
||||||
setDebugInfo((prev: any) => ({
|
setDebugInfo((prev: any) => ({
|
||||||
|
@ -470,13 +448,13 @@ export default function PasswordChangeSettings({
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-sm btn-warning"
|
className="btn btn-sm btn-warning"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log("Debug Info:");
|
// console.log("Debug Info:");
|
||||||
console.log("- logtoUserId:", logtoUserId);
|
// console.log("- logtoUserId:", logtoUserId);
|
||||||
console.log("- Environment Variables:");
|
// console.log("- Environment Variables:");
|
||||||
console.log(" - LOGTO_APP_ID:", import.meta.env.LOGTO_APP_ID);
|
// console.log(" - LOGTO_APP_ID:", import.meta.env.LOGTO_APP_ID);
|
||||||
console.log(" - LOGTO_ENDPOINT:", import.meta.env.LOGTO_ENDPOINT);
|
// console.log(" - LOGTO_ENDPOINT:", import.meta.env.LOGTO_ENDPOINT);
|
||||||
console.log(" - LOGTO_TOKEN_ENDPOINT:", import.meta.env.LOGTO_TOKEN_ENDPOINT);
|
// console.log(" - LOGTO_TOKEN_ENDPOINT:", import.meta.env.LOGTO_TOKEN_ENDPOINT);
|
||||||
console.log(" - LOGTO_API_ENDPOINT:", import.meta.env.LOGTO_API_ENDPOINT);
|
// console.log(" - LOGTO_API_ENDPOINT:", import.meta.env.LOGTO_API_ENDPOINT);
|
||||||
|
|
||||||
toast.success("Debug info logged to console");
|
toast.success("Debug info logged to console");
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -104,17 +104,17 @@ export default function ResumeSettings() {
|
||||||
const loadingToast = toast.loading('Uploading resume...');
|
const loadingToast = toast.loading('Uploading resume...');
|
||||||
|
|
||||||
// Log the file being uploaded for debugging
|
// Log the file being uploaded for debugging
|
||||||
console.log('Uploading file:', {
|
// console.log('Uploading file:', {
|
||||||
name: resumeFile.name,
|
// name: resumeFile.name,
|
||||||
size: resumeFile.size,
|
// size: resumeFile.size,
|
||||||
type: resumeFile.type
|
// type: resumeFile.type
|
||||||
});
|
// });
|
||||||
|
|
||||||
let updatedUserData: User;
|
let updatedUserData: User;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use the FileManager to upload the file directly
|
// Use the FileManager to upload the file directly
|
||||||
console.log('Using FileManager to upload resume file');
|
// console.log('Using FileManager to upload resume file');
|
||||||
|
|
||||||
// Upload the file using the FileManager's uploadFile method
|
// Upload the file using the FileManager's uploadFile method
|
||||||
const result = await fileManager.uploadFile<User>(
|
const result = await fileManager.uploadFile<User>(
|
||||||
|
@ -130,18 +130,18 @@ export default function ResumeSettings() {
|
||||||
throw new Error('Resume was not properly saved to the user record');
|
throw new Error('Resume was not properly saved to the user record');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Resume upload successful:', result.resume);
|
// console.log('Resume upload successful:', result.resume);
|
||||||
|
|
||||||
// Store the updated user data
|
// Store the updated user data
|
||||||
updatedUserData = result;
|
updatedUserData = result;
|
||||||
|
|
||||||
// Fetch the updated user record to ensure we have the latest data
|
// Fetch the updated user record to ensure we have the latest data
|
||||||
const refreshedUser = await get.getOne<User>(Collections.USERS, user.id);
|
const refreshedUser = await get.getOne<User>(Collections.USERS, user.id);
|
||||||
console.log('Refreshed user data:', refreshedUser);
|
// console.log('Refreshed user data:', refreshedUser);
|
||||||
|
|
||||||
// Double check that the resume field is populated
|
// Double check that the resume field is populated
|
||||||
if (!refreshedUser.resume) {
|
if (!refreshedUser.resume) {
|
||||||
console.warn('Resume field is missing in the refreshed user data');
|
// console.warn('Resume field is missing in the refreshed user data');
|
||||||
}
|
}
|
||||||
} catch (uploadError) {
|
} catch (uploadError) {
|
||||||
console.error('Error in file upload process:', uploadError);
|
console.error('Error in file upload process:', uploadError);
|
||||||
|
@ -173,7 +173,7 @@ export default function ResumeSettings() {
|
||||||
toast.success('Resume uploaded successfully');
|
toast.success('Resume uploaded successfully');
|
||||||
|
|
||||||
// Log the successful upload
|
// Log the successful upload
|
||||||
console.log('Resume uploaded successfully:', updatedUserData.resume);
|
// console.log('Resume uploaded successfully:', updatedUserData.resume);
|
||||||
|
|
||||||
// Dispatch a custom event to notify the dashboard about the resume upload
|
// Dispatch a custom event to notify the dashboard about the resume upload
|
||||||
const event = new CustomEvent('resumeUploaded', {
|
const event = new CustomEvent('resumeUploaded', {
|
||||||
|
@ -223,14 +223,14 @@ export default function ResumeSettings() {
|
||||||
const loadingToast = toast.loading('Deleting resume...');
|
const loadingToast = toast.loading('Deleting resume...');
|
||||||
|
|
||||||
// Log the deletion attempt
|
// Log the deletion attempt
|
||||||
console.log('Attempting to delete resume for user:', user.id);
|
// console.log('Attempting to delete resume for user:', user.id);
|
||||||
|
|
||||||
// Create a FormData with empty resume field to remove the file
|
// Create a FormData with empty resume field to remove the file
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('resume', '');
|
formData.append('resume', '');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('Using FileManager to delete resume file');
|
// console.log('Using FileManager to delete resume file');
|
||||||
|
|
||||||
// Use the FileManager's deleteFile method to remove the file
|
// Use the FileManager's deleteFile method to remove the file
|
||||||
const result = await fileManager.deleteFile<User>(
|
const result = await fileManager.deleteFile<User>(
|
||||||
|
@ -241,22 +241,22 @@ export default function ResumeSettings() {
|
||||||
|
|
||||||
// Verify the file was deleted
|
// Verify the file was deleted
|
||||||
if (result.resume) {
|
if (result.resume) {
|
||||||
console.warn('Resume field still exists after deletion attempt:', result.resume);
|
// console.warn('Resume field still exists after deletion attempt:', result.resume);
|
||||||
toast.dismiss(loadingToast);
|
toast.dismiss(loadingToast);
|
||||||
toast.error('Failed to completely remove the resume. Please try again.');
|
toast.error('Failed to completely remove the resume. Please try again.');
|
||||||
setUploading(false);
|
setUploading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Resume deletion successful for user:', user.id);
|
// console.log('Resume deletion successful for user:', user.id);
|
||||||
|
|
||||||
// Fetch the updated user record to ensure we have the latest data
|
// Fetch the updated user record to ensure we have the latest data
|
||||||
const refreshedUser = await get.getOne<User>(Collections.USERS, user.id);
|
const refreshedUser = await get.getOne<User>(Collections.USERS, user.id);
|
||||||
console.log('Refreshed user data after deletion:', refreshedUser);
|
// console.log('Refreshed user data after deletion:', refreshedUser);
|
||||||
|
|
||||||
// Double check that the resume field is empty
|
// Double check that the resume field is empty
|
||||||
if (refreshedUser.resume) {
|
if (refreshedUser.resume) {
|
||||||
console.warn('Resume field is still present in the refreshed user data:', refreshedUser.resume);
|
// console.warn('Resume field is still present in the refreshed user data:', refreshedUser.resume);
|
||||||
}
|
}
|
||||||
} catch (deleteError) {
|
} catch (deleteError) {
|
||||||
console.error('Error in file deletion process:', deleteError);
|
console.error('Error in file deletion process:', deleteError);
|
||||||
|
@ -275,7 +275,7 @@ export default function ResumeSettings() {
|
||||||
toast.success('Resume deleted successfully');
|
toast.success('Resume deleted successfully');
|
||||||
|
|
||||||
// Log the successful deletion
|
// Log the successful deletion
|
||||||
console.log('Resume deleted successfully for user:', user.id);
|
// console.log('Resume deleted successfully for user:', user.id);
|
||||||
|
|
||||||
// Dispatch a custom event to notify the dashboard about the resume deletion
|
// Dispatch a custom event to notify the dashboard about the resume deletion
|
||||||
const event = new CustomEvent('resumeUploaded', {
|
const event = new CustomEvent('resumeUploaded', {
|
||||||
|
@ -356,11 +356,11 @@ export default function ResumeSettings() {
|
||||||
const loadingToast = toast.loading('Replacing resume...');
|
const loadingToast = toast.loading('Replacing resume...');
|
||||||
|
|
||||||
// Log the file being uploaded for debugging
|
// Log the file being uploaded for debugging
|
||||||
console.log('Replacing resume with file:', {
|
// console.log('Replacing resume with file:', {
|
||||||
name: file.name,
|
// name: file.name,
|
||||||
size: file.size,
|
// size: file.size,
|
||||||
type: file.type
|
// type: file.type
|
||||||
});
|
// });
|
||||||
|
|
||||||
// Create a FormData object for the file upload
|
// Create a FormData object for the file upload
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
|
@ -112,27 +112,27 @@ export default function ReimbursementList() {
|
||||||
const fileManager = FileManager.getInstance();
|
const fileManager = FileManager.getInstance();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Component mounted');
|
// console.log('Component mounted');
|
||||||
fetchReimbursements();
|
fetchReimbursements();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Add effect to monitor requests state
|
// Add effect to monitor requests state
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Requests state updated:', requests);
|
// console.log('Requests state updated:', requests);
|
||||||
console.log('Number of requests:', requests.length);
|
// console.log('Number of requests:', requests.length);
|
||||||
}, [requests]);
|
}, [requests]);
|
||||||
|
|
||||||
// Add a useEffect to log preview URL and filename changes
|
// Add a useEffect to log preview URL and filename changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Preview URL changed:', previewUrl);
|
// console.log('Preview URL changed:', previewUrl);
|
||||||
console.log('Preview filename changed:', previewFilename);
|
// console.log('Preview filename changed:', previewFilename);
|
||||||
}, [previewUrl, previewFilename]);
|
}, [previewUrl, previewFilename]);
|
||||||
|
|
||||||
// Add a useEffect to log when the preview modal is shown/hidden
|
// Add a useEffect to log when the preview modal is shown/hidden
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Show preview changed:', showPreview);
|
// console.log('Show preview changed:', showPreview);
|
||||||
if (showPreview) {
|
if (showPreview) {
|
||||||
console.log('Selected receipt:', selectedReceipt);
|
// console.log('Selected receipt:', selectedReceipt);
|
||||||
}
|
}
|
||||||
}, [showPreview, selectedReceipt]);
|
}, [showPreview, selectedReceipt]);
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ export default function ReimbursementList() {
|
||||||
'-created'
|
'-created'
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Reimbursement records from IndexedDB:', reimbursementRecords);
|
// console.log('Reimbursement records from IndexedDB:', reimbursementRecords);
|
||||||
|
|
||||||
// Process the records
|
// Process the records
|
||||||
const processedRecords = reimbursementRecords.map(record => {
|
const processedRecords = reimbursementRecords.map(record => {
|
||||||
|
@ -183,7 +183,7 @@ export default function ReimbursementList() {
|
||||||
auditNotes = record.audit_notes;
|
auditNotes = record.audit_notes;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error parsing audit notes:', e);
|
// console.error('Error parsing audit notes:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ export default function ReimbursementList() {
|
||||||
itemizedExpenses = receiptRecord.itemized_expenses as ItemizedExpense[];
|
itemizedExpenses = receiptRecord.itemized_expenses as ItemizedExpense[];
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error parsing itemized expenses:', e);
|
// console.error('Error parsing itemized expenses:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,13 +241,13 @@ export default function ReimbursementList() {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error fetching receipt ${receiptId}:`, e);
|
// console.error(`Error fetching receipt ${receiptId}:`, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error fetching reimbursements:', err);
|
// console.error('Error fetching reimbursements:', err);
|
||||||
setError('Failed to load reimbursements. Please try again.');
|
setError('Failed to load reimbursements. Please try again.');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -256,7 +256,7 @@ export default function ReimbursementList() {
|
||||||
|
|
||||||
const handlePreviewFile = async (request: ReimbursementRequest, receiptId: string) => {
|
const handlePreviewFile = async (request: ReimbursementRequest, receiptId: string) => {
|
||||||
try {
|
try {
|
||||||
console.log('Previewing file for receipt ID:', receiptId);
|
// console.log('Previewing file for receipt ID:', receiptId);
|
||||||
const pb = auth.getPocketBase();
|
const pb = auth.getPocketBase();
|
||||||
const fileManager = FileManager.getInstance();
|
const fileManager = FileManager.getInstance();
|
||||||
|
|
||||||
|
@ -265,13 +265,13 @@ export default function ReimbursementList() {
|
||||||
|
|
||||||
// Check if we already have the receipt details in our map
|
// Check if we already have the receipt details in our map
|
||||||
if (receiptDetailsMap[receiptId]) {
|
if (receiptDetailsMap[receiptId]) {
|
||||||
console.log('Using cached receipt details');
|
// console.log('Using cached receipt details');
|
||||||
// Use the cached receipt details
|
// Use the cached receipt details
|
||||||
setSelectedReceipt(receiptDetailsMap[receiptId]);
|
setSelectedReceipt(receiptDetailsMap[receiptId]);
|
||||||
|
|
||||||
// Check if the receipt has a file
|
// Check if the receipt has a file
|
||||||
if (!receiptDetailsMap[receiptId].file) {
|
if (!receiptDetailsMap[receiptId].file) {
|
||||||
console.error('Receipt has no file attached');
|
// console.error('Receipt has no file attached');
|
||||||
toast.error('This receipt has no file attached');
|
toast.error('This receipt has no file attached');
|
||||||
setPreviewUrl('');
|
setPreviewUrl('');
|
||||||
setPreviewFilename('');
|
setPreviewFilename('');
|
||||||
|
@ -280,7 +280,7 @@ export default function ReimbursementList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the file URL with token for protected files
|
// Get the file URL with token for protected files
|
||||||
console.log('Getting file URL with token');
|
// console.log('Getting file URL with token');
|
||||||
const url = await fileManager.getFileUrlWithToken(
|
const url = await fileManager.getFileUrlWithToken(
|
||||||
'receipts',
|
'receipts',
|
||||||
receiptId,
|
receiptId,
|
||||||
|
@ -290,7 +290,7 @@ export default function ReimbursementList() {
|
||||||
|
|
||||||
// Check if the URL is empty
|
// Check if the URL is empty
|
||||||
if (!url) {
|
if (!url) {
|
||||||
console.error('Failed to get file URL: Empty URL returned');
|
// console.error('Failed to get file URL: Empty URL returned');
|
||||||
toast.error('Failed to load receipt: Could not generate file URL');
|
toast.error('Failed to load receipt: Could not generate file URL');
|
||||||
// Still show the preview modal but with empty URL to display the error message
|
// Still show the preview modal but with empty URL to display the error message
|
||||||
setPreviewUrl('');
|
setPreviewUrl('');
|
||||||
|
@ -299,7 +299,7 @@ export default function ReimbursementList() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Got URL:', url.substring(0, 50) + '...');
|
// console.log('Got URL:', url.substring(0, 50) + '...');
|
||||||
|
|
||||||
// Set the preview URL and filename
|
// Set the preview URL and filename
|
||||||
setPreviewUrl(url);
|
setPreviewUrl(url);
|
||||||
|
@ -309,28 +309,28 @@ export default function ReimbursementList() {
|
||||||
setShowPreview(true);
|
setShowPreview(true);
|
||||||
|
|
||||||
// Log the current state
|
// Log the current state
|
||||||
console.log('Current state after setting:', {
|
// console.log('Current state after setting:', {
|
||||||
previewUrl: url,
|
// previewUrl: url,
|
||||||
previewFilename: receiptDetailsMap[receiptId].file,
|
// previewFilename: receiptDetailsMap[receiptId].file,
|
||||||
showPreview: true
|
// showPreview: true
|
||||||
});
|
// });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not in the map, get the receipt record using its ID
|
// If not in the map, get the receipt record using its ID
|
||||||
console.log('Fetching receipt details from server');
|
// console.log('Fetching receipt details from server');
|
||||||
const receiptRecord = await pb.collection('receipts').getOne(receiptId, {
|
const receiptRecord = await pb.collection('receipts').getOne(receiptId, {
|
||||||
$autoCancel: false
|
$autoCancel: false
|
||||||
});
|
});
|
||||||
|
|
||||||
if (receiptRecord) {
|
if (receiptRecord) {
|
||||||
console.log('Receipt record found:', receiptRecord.id);
|
// console.log('Receipt record found:', receiptRecord.id);
|
||||||
console.log('Receipt file:', receiptRecord.file);
|
// console.log('Receipt file:', receiptRecord.file);
|
||||||
|
|
||||||
// Check if the receipt has a file
|
// Check if the receipt has a file
|
||||||
if (!receiptRecord.file) {
|
if (!receiptRecord.file) {
|
||||||
console.error('Receipt has no file attached');
|
// console.error('Receipt has no file attached');
|
||||||
toast.error('This receipt has no file attached');
|
toast.error('This receipt has no file attached');
|
||||||
setPreviewUrl('');
|
setPreviewUrl('');
|
||||||
setPreviewFilename('');
|
setPreviewFilename('');
|
||||||
|
@ -367,7 +367,7 @@ export default function ReimbursementList() {
|
||||||
setSelectedReceipt(receiptDetails);
|
setSelectedReceipt(receiptDetails);
|
||||||
|
|
||||||
// Get the file URL with token for protected files
|
// Get the file URL with token for protected files
|
||||||
console.log('Getting file URL with token for new receipt');
|
// console.log('Getting file URL with token for new receipt');
|
||||||
const url = await fileManager.getFileUrlWithToken(
|
const url = await fileManager.getFileUrlWithToken(
|
||||||
'receipts',
|
'receipts',
|
||||||
receiptRecord.id,
|
receiptRecord.id,
|
||||||
|
@ -377,7 +377,7 @@ export default function ReimbursementList() {
|
||||||
|
|
||||||
// Check if the URL is empty
|
// Check if the URL is empty
|
||||||
if (!url) {
|
if (!url) {
|
||||||
console.error('Failed to get file URL: Empty URL returned');
|
// console.error('Failed to get file URL: Empty URL returned');
|
||||||
toast.error('Failed to load receipt: Could not generate file URL');
|
toast.error('Failed to load receipt: Could not generate file URL');
|
||||||
// Still show the preview modal but with empty URL to display the error message
|
// Still show the preview modal but with empty URL to display the error message
|
||||||
setPreviewUrl('');
|
setPreviewUrl('');
|
||||||
|
@ -386,7 +386,7 @@ export default function ReimbursementList() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Got URL:', url.substring(0, 50) + '...');
|
// console.log('Got URL:', url.substring(0, 50) + '...');
|
||||||
|
|
||||||
// Set the preview URL and filename
|
// Set the preview URL and filename
|
||||||
setPreviewUrl(url);
|
setPreviewUrl(url);
|
||||||
|
@ -396,16 +396,16 @@ export default function ReimbursementList() {
|
||||||
setShowPreview(true);
|
setShowPreview(true);
|
||||||
|
|
||||||
// Log the current state
|
// Log the current state
|
||||||
console.log('Current state after setting:', {
|
// console.log('Current state after setting:', {
|
||||||
previewUrl: url,
|
// previewUrl: url,
|
||||||
previewFilename: receiptRecord.file,
|
// previewFilename: receiptRecord.file,
|
||||||
showPreview: true
|
// showPreview: true
|
||||||
});
|
// });
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Receipt not found');
|
throw new Error('Receipt not found');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading receipt:', error);
|
// console.error('Error loading receipt:', error);
|
||||||
toast.error('Failed to load receipt. Please try again.');
|
toast.error('Failed to load receipt. Please try again.');
|
||||||
// Show the preview modal with empty URL to display the error message
|
// Show the preview modal with empty URL to display the error message
|
||||||
setPreviewUrl('');
|
setPreviewUrl('');
|
||||||
|
@ -423,7 +423,7 @@ export default function ReimbursementList() {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
console.log('Rendering loading state');
|
// console.log('Rendering loading state');
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
|
@ -437,7 +437,7 @@ export default function ReimbursementList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.log('Rendering error state:', error);
|
// console.log('Rendering error state:', error);
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: -20 }}
|
initial={{ opacity: 0, y: -20 }}
|
||||||
|
@ -450,8 +450,8 @@ export default function ReimbursementList() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Rendering main component. Requests:', requests);
|
// console.log('Rendering main component. Requests:', requests);
|
||||||
console.log('Requests length:', requests.length);
|
// console.log('Requests length:', requests.length);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -482,7 +482,7 @@ export default function ReimbursementList() {
|
||||||
>
|
>
|
||||||
<AnimatePresence mode="popLayout">
|
<AnimatePresence mode="popLayout">
|
||||||
{requests.map((request, index) => {
|
{requests.map((request, index) => {
|
||||||
console.log('Rendering request:', request);
|
// console.log('Rendering request:', request);
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={request.id}
|
key={request.id}
|
||||||
|
|
|
@ -134,7 +134,6 @@ export default function ReimbursementManagementPortal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const records = await get.getAll<ExtendedReimbursement>('reimbursement', filter, sort);
|
const records = await get.getAll<ExtendedReimbursement>('reimbursement', filter, sort);
|
||||||
console.log('Loaded reimbursements:', records);
|
|
||||||
|
|
||||||
// Load user data for submitters
|
// Load user data for submitters
|
||||||
const userIds = new Set(records.map(r => r.submitted_by));
|
const userIds = new Set(records.map(r => r.submitted_by));
|
||||||
|
@ -165,11 +164,9 @@ export default function ReimbursementManagementPortal() {
|
||||||
|
|
||||||
// Load associated receipts
|
// Load associated receipts
|
||||||
const receiptIds = enrichedRecords.flatMap(r => r.receipts || []);
|
const receiptIds = enrichedRecords.flatMap(r => r.receipts || []);
|
||||||
console.log('Extracted receipt IDs:', receiptIds, 'from reimbursements:', enrichedRecords.map(r => ({ id: r.id, receipts: r.receipts })));
|
|
||||||
|
|
||||||
if (receiptIds.length > 0) {
|
if (receiptIds.length > 0) {
|
||||||
try {
|
try {
|
||||||
console.log('Attempting to load receipts with IDs:', receiptIds);
|
|
||||||
const receiptRecords = await Promise.all(
|
const receiptRecords = await Promise.all(
|
||||||
receiptIds.map(async id => {
|
receiptIds.map(async id => {
|
||||||
try {
|
try {
|
||||||
|
@ -202,12 +199,10 @@ export default function ReimbursementManagementPortal() {
|
||||||
);
|
);
|
||||||
|
|
||||||
const validReceipts = receiptRecords.filter((r): r is ExtendedReceipt => r !== null);
|
const validReceipts = receiptRecords.filter((r): r is ExtendedReceipt => r !== null);
|
||||||
console.log('Successfully loaded receipt records:', validReceipts);
|
|
||||||
|
|
||||||
const receiptMap = Object.fromEntries(
|
const receiptMap = Object.fromEntries(
|
||||||
validReceipts.map(receipt => [receipt.id, receipt])
|
validReceipts.map(receipt => [receipt.id, receipt])
|
||||||
);
|
);
|
||||||
console.log('Created receipt map:', receiptMap);
|
|
||||||
setReceipts(receiptMap);
|
setReceipts(receiptMap);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Error loading receipts:', error);
|
console.error('Error loading receipts:', error);
|
||||||
|
@ -219,7 +214,7 @@ export default function ReimbursementManagementPortal() {
|
||||||
toast.error('Failed to load receipts: ' + (error?.message || 'Unknown error'));
|
toast.error('Failed to load receipts: ' + (error?.message || 'Unknown error'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('No receipt IDs found in reimbursements');
|
// console.log('No receipt IDs found in reimbursements');
|
||||||
setReceipts({});
|
setReceipts({});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ const ImageWithFallback = ({ url, filename, onError }: ImageWithFallbackProps) =
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Try to fetch the image as a blob and create an object URL
|
// Try to fetch the image as a blob and create an object URL
|
||||||
console.log('Trying to fetch image as blob:', url);
|
// console.log('Trying to fetch image as blob:', url);
|
||||||
const response = await fetch(url, { mode: 'cors' });
|
const response = await fetch(url, { mode: 'cors' });
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
@ -38,7 +38,7 @@ const ImageWithFallback = ({ url, filename, onError }: ImageWithFallbackProps) =
|
||||||
|
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
const objectUrl = URL.createObjectURL(blob);
|
const objectUrl = URL.createObjectURL(blob);
|
||||||
console.log('Created object URL:', objectUrl);
|
// console.log('Created object URL:', objectUrl);
|
||||||
|
|
||||||
// Update the image source with the object URL
|
// Update the image source with the object URL
|
||||||
setImgSrc(objectUrl);
|
setImgSrc(objectUrl);
|
||||||
|
@ -48,10 +48,10 @@ const ImageWithFallback = ({ url, filename, onError }: ImageWithFallbackProps) =
|
||||||
onError('Failed to load image. This might be due to permission issues or the file may not exist.');
|
onError('Failed to load image. This might be due to permission issues or the file may not exist.');
|
||||||
|
|
||||||
// Log additional details
|
// Log additional details
|
||||||
console.log('Image URL that failed:', url);
|
// console.log('Image URL that failed:', url);
|
||||||
console.log('Current auth status:',
|
// console.log('Current auth status:',
|
||||||
Authentication.getInstance().isAuthenticated() ? 'Authenticated' : 'Not authenticated'
|
// Authentication.getInstance().isAuthenticated() ? 'Authenticated' : 'Not authenticated'
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -76,26 +76,26 @@ const Calendar = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
|
||||||
|
|
||||||
const loadGapiAndListEvents = async () => {
|
const loadGapiAndListEvents = async () => {
|
||||||
try {
|
try {
|
||||||
console.log("Starting to load events...");
|
// console.log("Starting to load events...");
|
||||||
|
|
||||||
if (typeof window.gapi === "undefined") {
|
if (typeof window.gapi === "undefined") {
|
||||||
console.log("Loading GAPI script...");
|
// console.log("Loading GAPI script...");
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
script.src = "https://apis.google.com/js/api.js";
|
script.src = "https://apis.google.com/js/api.js";
|
||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
script.onload = () => {
|
script.onload = () => {
|
||||||
console.log("GAPI script loaded");
|
// console.log("GAPI script loaded");
|
||||||
window.gapi.load("client", resolve);
|
window.gapi.load("client", resolve);
|
||||||
};
|
};
|
||||||
script.onerror = () => {
|
script.onerror = () => {
|
||||||
console.error("Failed to load GAPI script");
|
// console.error("Failed to load GAPI script");
|
||||||
reject(new Error("Failed to load the Google API script."));
|
reject(new Error("Failed to load the Google API script."));
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Initializing GAPI client...");
|
// console.log("Initializing GAPI client...");
|
||||||
await window.gapi.client.init({
|
await window.gapi.client.init({
|
||||||
apiKey: CALENDAR_API_KEY,
|
apiKey: CALENDAR_API_KEY,
|
||||||
discoveryDocs: [
|
discoveryDocs: [
|
||||||
|
@ -115,7 +115,7 @@ const Calendar = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("Fetching events...");
|
// console.log("Fetching events...");
|
||||||
const response = await window.gapi.client.calendar.events.list({
|
const response = await window.gapi.client.calendar.events.list({
|
||||||
calendarId: calendarId,
|
calendarId: calendarId,
|
||||||
timeZone: userTimeZone,
|
timeZone: userTimeZone,
|
||||||
|
@ -125,13 +125,13 @@ const Calendar = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
|
||||||
orderBy: "startTime",
|
orderBy: "startTime",
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Response received:", response);
|
// console.log("Response received:", response);
|
||||||
|
|
||||||
if (response.result.items) {
|
if (response.result.items) {
|
||||||
setEvents(response.result.items);
|
setEvents(response.result.items);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Detailed Error: ", error);
|
// console.error("Detailed Error: ", error);
|
||||||
setError(error.message || "Failed to load events");
|
setError(error.message || "Failed to load events");
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
|
@ -48,16 +48,16 @@ const EventList = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
|
||||||
|
|
||||||
const loadGapiAndListEvents = async () => {
|
const loadGapiAndListEvents = async () => {
|
||||||
try {
|
try {
|
||||||
console.log("Starting to load events...");
|
// console.log("Starting to load events...");
|
||||||
|
|
||||||
if (typeof window.gapi === "undefined") {
|
if (typeof window.gapi === "undefined") {
|
||||||
console.log("Loading GAPI script...");
|
// console.log("Loading GAPI script...");
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
script.src = "https://apis.google.com/js/api.js";
|
script.src = "https://apis.google.com/js/api.js";
|
||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
script.onload = () => {
|
script.onload = () => {
|
||||||
console.log("GAPI script loaded");
|
// console.log("GAPI script loaded");
|
||||||
window.gapi.load("client", resolve);
|
window.gapi.load("client", resolve);
|
||||||
};
|
};
|
||||||
script.onerror = () => {
|
script.onerror = () => {
|
||||||
|
@ -67,7 +67,7 @@ const EventList = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Initializing GAPI client...");
|
// console.log("Initializing GAPI client...");
|
||||||
await window.gapi.client.init({
|
await window.gapi.client.init({
|
||||||
apiKey: apiKey,
|
apiKey: apiKey,
|
||||||
discoveryDocs: [
|
discoveryDocs: [
|
||||||
|
@ -75,7 +75,7 @@ const EventList = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Fetching events...");
|
// console.log("Fetching events...");
|
||||||
const response = await window.gapi.client.calendar.events.list({
|
const response = await window.gapi.client.calendar.events.list({
|
||||||
calendarId: calendarId,
|
calendarId: calendarId,
|
||||||
timeZone: userTimeZone,
|
timeZone: userTimeZone,
|
||||||
|
@ -85,7 +85,7 @@ const EventList = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
|
||||||
orderBy: "startTime",
|
orderBy: "startTime",
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Response received:", response);
|
// console.log("Response received:", response);
|
||||||
|
|
||||||
if (response.result.items) {
|
if (response.result.items) {
|
||||||
setEvents(response.result.items);
|
setEvents(response.result.items);
|
||||||
|
|
|
@ -11,8 +11,6 @@ async function getLogtoAccessToken(
|
||||||
scope: string = "all",
|
scope: string = "all",
|
||||||
): Promise<string | null> {
|
): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
console.log("Attempting to get access token from Logto");
|
|
||||||
|
|
||||||
// Create Basic auth string
|
// Create Basic auth string
|
||||||
const authString = Buffer.from(`${clientId}:${clientSecret}`).toString(
|
const authString = Buffer.from(`${clientId}:${clientSecret}`).toString(
|
||||||
"base64",
|
"base64",
|
||||||
|
@ -59,8 +57,6 @@ async function verifyUserPassword(
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
console.log("Verifying current password");
|
|
||||||
|
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${logtoApiEndpoint}/api/users/${userId}/password/verify`,
|
`${logtoApiEndpoint}/api/users/${userId}/password/verify`,
|
||||||
{
|
{
|
||||||
|
@ -75,7 +71,6 @@ async function verifyUserPassword(
|
||||||
|
|
||||||
// 204 means password matches, 422 means it doesn't match
|
// 204 means password matches, 422 means it doesn't match
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
console.log("Current password verified successfully");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +96,6 @@ async function verifyUserPassword(
|
||||||
|
|
||||||
export const POST: APIRoute = async ({ request }) => {
|
export const POST: APIRoute = async ({ request }) => {
|
||||||
try {
|
try {
|
||||||
console.log("Received change password request");
|
|
||||||
|
|
||||||
// Parse request body
|
// Parse request body
|
||||||
const contentType = request.headers.get("content-type");
|
const contentType = request.headers.get("content-type");
|
||||||
const rawBody = await request.text();
|
const rawBody = await request.text();
|
||||||
|
@ -161,6 +154,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get access token
|
// Get access token
|
||||||
|
// console.log("Attempting to get access token from Logto");
|
||||||
const accessToken = await getLogtoAccessToken(
|
const accessToken = await getLogtoAccessToken(
|
||||||
logtoTokenEndpoint,
|
logtoTokenEndpoint,
|
||||||
logtoAppId,
|
logtoAppId,
|
||||||
|
@ -181,6 +175,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify current password before proceeding
|
// Verify current password before proceeding
|
||||||
|
// console.log("Verifying current password");
|
||||||
const isPasswordValid = await verifyUserPassword(
|
const isPasswordValid = await verifyUserPassword(
|
||||||
logtoApiEndpoint,
|
logtoApiEndpoint,
|
||||||
userId,
|
userId,
|
||||||
|
@ -202,6 +197,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change password using Logto Management API
|
// Change password using Logto Management API
|
||||||
|
// console.log("Current password verified successfully");
|
||||||
const changePasswordResponse = await fetch(
|
const changePasswordResponse = await fetch(
|
||||||
`${logtoApiEndpoint}/api/users/${userId}/password`,
|
`${logtoApiEndpoint}/api/users/${userId}/password`,
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,13 +26,13 @@ const components = Object.fromEntries(
|
||||||
const component = await import(
|
const component = await import(
|
||||||
`../components/dashboard/${section.component}.astro`
|
`../components/dashboard/${section.component}.astro`
|
||||||
);
|
);
|
||||||
console.log(`Loaded component: ${section.component}`); // Debug log
|
// console.log(`Loaded component: ${section.component}`); // Debug log
|
||||||
return [section.component, component.default];
|
return [section.component, component.default];
|
||||||
})
|
}),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("Available components:", Object.keys(components)); // Debug log
|
// console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
|
@ -65,33 +65,19 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
<!-- User Profile -->
|
<!-- User Profile -->
|
||||||
<div class="p-6 border-b border-base-200">
|
<div class="p-6 border-b border-base-200">
|
||||||
<!-- Loading State -->
|
<!-- Loading State -->
|
||||||
<div
|
<div id="userProfileSkeleton" class="flex items-center gap-4">
|
||||||
id="userProfileSkeleton"
|
|
||||||
class="flex items-center gap-4"
|
|
||||||
>
|
|
||||||
<div class="avatar flex items-center justify-center">
|
<div class="avatar flex items-center justify-center">
|
||||||
<div
|
<div class="w-12 h-12 rounded-xl bg-base-300 animate-pulse"></div>
|
||||||
class="w-12 h-12 rounded-xl bg-base-300 animate-pulse"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<div
|
<div class="h-6 w-32 bg-base-300 animate-pulse rounded mb-2">
|
||||||
class="h-6 w-32 bg-base-300 animate-pulse rounded mb-2"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="h-5 w-20 bg-base-300 animate-pulse rounded"
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="h-5 w-20 bg-base-300 animate-pulse rounded"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Signed Out State -->
|
<!-- Signed Out State -->
|
||||||
<div
|
<div id="userProfileSignedOut" class="flex items-center gap-4 hidden">
|
||||||
id="userProfileSignedOut"
|
|
||||||
class="flex items-center gap-4 hidden"
|
|
||||||
>
|
|
||||||
<div class="avatar flex items-center justify-center">
|
<div class="avatar flex items-center justify-center">
|
||||||
<div
|
<div
|
||||||
class="w-12 h-12 rounded-xl bg-base-300 text-base-content/30 flex items-center justify-center"
|
class="w-12 h-12 rounded-xl bg-base-300 text-base-content/30 flex items-center justify-center"
|
||||||
|
@ -100,22 +86,15 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3
|
<h3 class="font-medium text-lg text-base-content/70">
|
||||||
class="font-medium text-lg text-base-content/70"
|
|
||||||
>
|
|
||||||
Signed Out
|
Signed Out
|
||||||
</h3>
|
</h3>
|
||||||
<div class="badge badge-outline mt-1 opacity-50">
|
<div class="badge badge-outline mt-1 opacity-50">Guest</div>
|
||||||
Guest
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Actual Profile -->
|
<!-- Actual Profile -->
|
||||||
<div
|
<div id="userProfileSummary" class="flex items-center gap-4 hidden">
|
||||||
id="userProfileSummary"
|
|
||||||
class="flex items-center gap-4 hidden"
|
|
||||||
>
|
|
||||||
<div class="avatar flex items-center justify-center">
|
<div class="avatar flex items-center justify-center">
|
||||||
<div
|
<div
|
||||||
class="w-12 h-12 rounded-xl bg-[#06659d] text-white ring ring-base-200 ring-offset-base-100 ring-offset-2 inline-flex items-center justify-center"
|
class="w-12 h-12 rounded-xl bg-[#06659d] text-white ring ring-base-200 ring-offset-base-100 ring-offset-2 inline-flex items-center justify-center"
|
||||||
|
@ -127,9 +106,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="font-medium text-lg" id="userName">
|
<h3 class="font-medium text-lg" id="userName">Loading...</h3>
|
||||||
Loading...
|
|
||||||
</h3>
|
|
||||||
<div
|
<div
|
||||||
class="badge badge-outline mt-1 border-[#06659d] text-[#06659d]"
|
class="badge badge-outline mt-1 border-[#06659d] text-[#06659d]"
|
||||||
id="userRole"
|
id="userRole"
|
||||||
|
@ -168,64 +145,41 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
<div id="actualMenu" class="hidden">
|
<div id="actualMenu" class="hidden">
|
||||||
{
|
{
|
||||||
Object.entries(dashboardConfig.categories).map(
|
Object.entries(dashboardConfig.categories).map(
|
||||||
([categoryKey, category]: [
|
([categoryKey, category]: [string, any]) => (
|
||||||
string,
|
|
||||||
any,
|
|
||||||
]) => (
|
|
||||||
<>
|
<>
|
||||||
<li
|
<li
|
||||||
class={`menu-title font-medium opacity-70 ${
|
class={`menu-title font-medium opacity-70 ${
|
||||||
category.role &&
|
category.role && category.role !== "none"
|
||||||
category.role !== "none"
|
|
||||||
? "hidden"
|
? "hidden"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
data-role-required={
|
data-role-required={category.role || "none"}
|
||||||
category.role || "none"
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<span>{category.title}</span>
|
<span>{category.title}</span>
|
||||||
</li>
|
</li>
|
||||||
{category.sections.map(
|
{category.sections.map((sectionKey: string) => {
|
||||||
(sectionKey: string) => {
|
const section = dashboardConfig.sections[sectionKey];
|
||||||
const section =
|
|
||||||
dashboardConfig
|
|
||||||
.sections[
|
|
||||||
sectionKey
|
|
||||||
];
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
class={
|
class={
|
||||||
section.role &&
|
section.role && section.role !== "none"
|
||||||
section.role !==
|
|
||||||
"none"
|
|
||||||
? "hidden"
|
? "hidden"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
data-role-required={
|
data-role-required={section.role}
|
||||||
section.role
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class={`dashboard-nav-btn gap-4 transition-all duration-200 outline-none focus:outline-none hover:bg-opacity-5 ${section.class || ""}`}
|
class={`dashboard-nav-btn gap-4 transition-all duration-200 outline-none focus:outline-none hover:bg-opacity-5 ${section.class || ""}`}
|
||||||
data-section={
|
data-section={sectionKey}
|
||||||
sectionKey
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon name={section.icon} class="h-5 w-5" />
|
||||||
name={
|
|
||||||
section.icon
|
|
||||||
}
|
|
||||||
class="h-5 w-5"
|
|
||||||
/>
|
|
||||||
{section.title}
|
{section.title}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
})}
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -238,15 +192,10 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
class="flex-1 overflow-x-hidden overflow-y-auto bg-base-200 w-full xl:w-[calc(100%-20rem)]"
|
class="flex-1 overflow-x-hidden overflow-y-auto bg-base-200 w-full xl:w-[calc(100%-20rem)]"
|
||||||
>
|
>
|
||||||
<!-- Mobile Header -->
|
<!-- Mobile Header -->
|
||||||
<header
|
<header class="bg-base-100 p-4 shadow-md xl:hidden sticky top-0 z-40">
|
||||||
class="bg-base-100 p-4 shadow-md xl:hidden sticky top-0 z-40"
|
|
||||||
>
|
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button
|
<button id="mobileSidebarToggle" class="btn btn-square btn-ghost">
|
||||||
id="mobileSidebarToggle"
|
|
||||||
class="btn btn-square btn-ghost"
|
|
||||||
>
|
|
||||||
<Icon name="heroicons:bars-3" class="h-6 w-6" />
|
<Icon name="heroicons:bars-3" class="h-6 w-6" />
|
||||||
</button>
|
</button>
|
||||||
<h1 class="text-xl font-bold">IEEE UCSD</h1>
|
<h1 class="text-xl font-bold">IEEE UCSD</h1>
|
||||||
|
@ -258,11 +207,8 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
<div class="p-4 md:p-6 max-w-[1600px] mx-auto">
|
<div class="p-4 md:p-6 max-w-[1600px] mx-auto">
|
||||||
<!-- Loading State -->
|
<!-- Loading State -->
|
||||||
<div id="pageLoadingState" class="w-full">
|
<div id="pageLoadingState" class="w-full">
|
||||||
<div
|
<div class="flex flex-col items-center justify-center p-4 sm:p-8">
|
||||||
class="flex flex-col items-center justify-center p-4 sm:p-8"
|
<div class="loading loading-spinner loading-lg"></div>
|
||||||
>
|
|
||||||
<div class="loading loading-spinner loading-lg">
|
|
||||||
</div>
|
|
||||||
<p class="mt-4 opacity-70">Loading dashboard...</p>
|
<p class="mt-4 opacity-70">Loading dashboard...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -288,9 +234,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
<!-- Not Authenticated State -->
|
<!-- Not Authenticated State -->
|
||||||
<div id="notAuthenticatedState" class="hidden w-full">
|
<div id="notAuthenticatedState" class="hidden w-full">
|
||||||
<div class="card bg-base-100 shadow-xl mx-2 sm:mx-0">
|
<div class="card bg-base-100 shadow-xl mx-2 sm:mx-0">
|
||||||
<div
|
<div class="card-body items-center text-center p-4 sm:p-8">
|
||||||
class="card-body items-center text-center p-4 sm:p-8"
|
|
||||||
>
|
|
||||||
<div class="mb-4 sm:mb-6">
|
<div class="mb-4 sm:mb-6">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
@ -307,11 +251,9 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
<h2 class="card-title text-xl sm:text-2xl mb-2">
|
<h2 class="card-title text-xl sm:text-2xl mb-2">
|
||||||
Sign in to Access Dashboard
|
Sign in to Access Dashboard
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p class="opacity-70 mb-4 sm:mb-6 text-sm sm:text-base">
|
||||||
class="opacity-70 mb-4 sm:mb-6 text-sm sm:text-base"
|
Please sign in with your IEEE UCSD account to access the
|
||||||
>
|
dashboard.
|
||||||
Please sign in with your IEEE UCSD account
|
|
||||||
to access the dashboard.
|
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
class="login-button btn btn-primary btn-lg gap-2 w-full sm:w-auto"
|
class="login-button btn btn-primary btn-lg gap-2 w-full sm:w-auto"
|
||||||
|
@ -343,14 +285,12 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
// Skip if no component is defined
|
// Skip if no component is defined
|
||||||
if (!section.component) return null;
|
if (!section.component) return null;
|
||||||
|
|
||||||
const Component =
|
const Component = components[section.component];
|
||||||
components[section.component];
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={`${sectionKey}Section`}
|
id={`${sectionKey}Section`}
|
||||||
class={`dashboard-section hidden ${
|
class={`dashboard-section hidden ${
|
||||||
section.role &&
|
section.role && section.role !== "none"
|
||||||
section.role !== "none"
|
|
||||||
? "role-restricted"
|
? "role-restricted"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
|
@ -359,7 +299,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
<Component />
|
<Component />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -383,11 +323,10 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
const logger = SendLog.getInstance();
|
const logger = SendLog.getInstance();
|
||||||
|
|
||||||
// Initialize page state
|
// Initialize page state
|
||||||
const pageLoadingState =
|
const pageLoadingState = document.getElementById("pageLoadingState");
|
||||||
document.getElementById("pageLoadingState");
|
|
||||||
const pageErrorState = document.getElementById("pageErrorState");
|
const pageErrorState = document.getElementById("pageErrorState");
|
||||||
const notAuthenticatedState = document.getElementById(
|
const notAuthenticatedState = document.getElementById(
|
||||||
"notAuthenticatedState"
|
"notAuthenticatedState",
|
||||||
);
|
);
|
||||||
const mainContent = document.getElementById("mainContent");
|
const mainContent = document.getElementById("mainContent");
|
||||||
const sidebar = document.querySelector("aside");
|
const sidebar = document.querySelector("aside");
|
||||||
|
@ -418,11 +357,9 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
}
|
}
|
||||||
|
|
||||||
// For non-sponsor roles, handle normally
|
// For non-sponsor roles, handle normally
|
||||||
document
|
document.querySelectorAll("[data-role-required]").forEach((element) => {
|
||||||
.querySelectorAll("[data-role-required]")
|
|
||||||
.forEach((element) => {
|
|
||||||
const requiredRole = element.getAttribute(
|
const requiredRole = element.getAttribute(
|
||||||
"data-role-required"
|
"data-role-required",
|
||||||
) as OfficerStatus;
|
) as OfficerStatus;
|
||||||
|
|
||||||
// Skip elements that don't have a role requirement
|
// Skip elements that don't have a role requirement
|
||||||
|
@ -432,10 +369,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user has permission for this role
|
// Check if user has permission for this role
|
||||||
const hasPermission = hasAccess(
|
const hasPermission = hasAccess(officerStatus, requiredRole);
|
||||||
officerStatus,
|
|
||||||
requiredRole
|
|
||||||
);
|
|
||||||
|
|
||||||
// Only show elements if user has permission
|
// Only show elements if user has permission
|
||||||
element.classList.toggle("hidden", !hasPermission);
|
element.classList.toggle("hidden", !hasPermission);
|
||||||
|
@ -444,10 +378,8 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
|
|
||||||
// Handle navigation
|
// Handle navigation
|
||||||
const handleNavigation = () => {
|
const handleNavigation = () => {
|
||||||
const navButtons =
|
const navButtons = document.querySelectorAll(".dashboard-nav-btn");
|
||||||
document.querySelectorAll(".dashboard-nav-btn");
|
const sections = document.querySelectorAll(".dashboard-section");
|
||||||
const sections =
|
|
||||||
document.querySelectorAll(".dashboard-section");
|
|
||||||
const mainContentDiv = document.getElementById("mainContent");
|
const mainContentDiv = document.getElementById("mainContent");
|
||||||
|
|
||||||
// Ensure mainContent is visible
|
// Ensure mainContent is visible
|
||||||
|
@ -481,19 +413,17 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
|
|
||||||
// Show selected section
|
// Show selected section
|
||||||
const sectionId = `${sectionKey}Section`;
|
const sectionId = `${sectionKey}Section`;
|
||||||
const targetSection =
|
const targetSection = document.getElementById(sectionId);
|
||||||
document.getElementById(sectionId);
|
|
||||||
if (targetSection) {
|
if (targetSection) {
|
||||||
targetSection.classList.remove("hidden");
|
targetSection.classList.remove("hidden");
|
||||||
console.log(`Showing section: ${sectionId}`); // Debug log
|
// console.log(`Showing section: ${sectionId}`); // Debug log
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close mobile sidebar if needed
|
// Close mobile sidebar if needed
|
||||||
if (window.innerWidth < 1024 && sidebar) {
|
if (window.innerWidth < 1024 && sidebar) {
|
||||||
sidebar.classList.add("-translate-x-full");
|
sidebar.classList.add("-translate-x-full");
|
||||||
document.body.classList.remove("overflow-hidden");
|
document.body.classList.remove("overflow-hidden");
|
||||||
const overlay =
|
const overlay = document.getElementById("sidebarOverlay");
|
||||||
document.getElementById("sidebarOverlay");
|
|
||||||
overlay?.remove();
|
overlay?.remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -537,7 +467,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
"",
|
"",
|
||||||
{
|
{
|
||||||
fields: ["id", "type", "role"],
|
fields: ["id", "type", "role"],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (officerRecords && officerRecords.items.length > 0) {
|
if (officerRecords && officerRecords.items.length > 0) {
|
||||||
|
@ -579,7 +509,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
"",
|
"",
|
||||||
{
|
{
|
||||||
fields: ["id", "company"],
|
fields: ["id", "company"],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (sponsorRecords && sponsorRecords.items.length > 0) {
|
if (sponsorRecords && sponsorRecords.items.length > 0) {
|
||||||
|
@ -613,8 +543,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
|
|
||||||
if (userName) userName.textContent = fallbackValues.name;
|
if (userName) userName.textContent = fallbackValues.name;
|
||||||
if (userRole) userRole.textContent = fallbackValues.role;
|
if (userRole) userRole.textContent = fallbackValues.role;
|
||||||
if (userInitials)
|
if (userInitials) userInitials.textContent = fallbackValues.initials;
|
||||||
userInitials.textContent = fallbackValues.initials;
|
|
||||||
|
|
||||||
updateSectionVisibility("" as OfficerStatus);
|
updateSectionVisibility("" as OfficerStatus);
|
||||||
}
|
}
|
||||||
|
@ -622,18 +551,16 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
|
|
||||||
// Mobile sidebar toggle
|
// Mobile sidebar toggle
|
||||||
const mobileSidebarToggle = document.getElementById(
|
const mobileSidebarToggle = document.getElementById(
|
||||||
"mobileSidebarToggle"
|
"mobileSidebarToggle",
|
||||||
);
|
);
|
||||||
if (mobileSidebarToggle && sidebar) {
|
if (mobileSidebarToggle && sidebar) {
|
||||||
const toggleSidebar = () => {
|
const toggleSidebar = () => {
|
||||||
const isOpen =
|
const isOpen = !sidebar.classList.contains("-translate-x-full");
|
||||||
!sidebar.classList.contains("-translate-x-full");
|
|
||||||
|
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
sidebar.classList.add("-translate-x-full");
|
sidebar.classList.add("-translate-x-full");
|
||||||
document.body.classList.remove("overflow-hidden");
|
document.body.classList.remove("overflow-hidden");
|
||||||
const overlay =
|
const overlay = document.getElementById("sidebarOverlay");
|
||||||
document.getElementById("sidebarOverlay");
|
|
||||||
overlay?.remove();
|
overlay?.remove();
|
||||||
} else {
|
} else {
|
||||||
sidebar.classList.remove("-translate-x-full");
|
sidebar.classList.remove("-translate-x-full");
|
||||||
|
@ -658,38 +585,35 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
|
|
||||||
// Check if user is authenticated
|
// Check if user is authenticated
|
||||||
if (!auth.isAuthenticated()) {
|
if (!auth.isAuthenticated()) {
|
||||||
console.log("User not authenticated");
|
// console.log("User not authenticated");
|
||||||
if (pageLoadingState)
|
if (pageLoadingState) pageLoadingState.classList.add("hidden");
|
||||||
pageLoadingState.classList.add("hidden");
|
|
||||||
if (notAuthenticatedState)
|
if (notAuthenticatedState)
|
||||||
notAuthenticatedState.classList.remove("hidden");
|
notAuthenticatedState.classList.remove("hidden");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageLoadingState)
|
if (pageLoadingState) pageLoadingState.classList.remove("hidden");
|
||||||
pageLoadingState.classList.remove("hidden");
|
|
||||||
if (pageErrorState) pageErrorState.classList.add("hidden");
|
if (pageErrorState) pageErrorState.classList.add("hidden");
|
||||||
if (notAuthenticatedState)
|
if (notAuthenticatedState)
|
||||||
notAuthenticatedState.classList.add("hidden");
|
notAuthenticatedState.classList.add("hidden");
|
||||||
|
|
||||||
// Show loading states
|
// Show loading states
|
||||||
const userProfileSkeleton = document.getElementById(
|
const userProfileSkeleton = document.getElementById(
|
||||||
"userProfileSkeleton"
|
"userProfileSkeleton",
|
||||||
);
|
);
|
||||||
const userProfileSignedOut = document.getElementById(
|
const userProfileSignedOut = document.getElementById(
|
||||||
"userProfileSignedOut"
|
"userProfileSignedOut",
|
||||||
);
|
);
|
||||||
const userProfileSummary =
|
const userProfileSummary =
|
||||||
document.getElementById("userProfileSummary");
|
document.getElementById("userProfileSummary");
|
||||||
const menuLoadingSkeleton = document.getElementById(
|
const menuLoadingSkeleton = document.getElementById(
|
||||||
"menuLoadingSkeleton"
|
"menuLoadingSkeleton",
|
||||||
);
|
);
|
||||||
const actualMenu = document.getElementById("actualMenu");
|
const actualMenu = document.getElementById("actualMenu");
|
||||||
|
|
||||||
if (userProfileSkeleton)
|
if (userProfileSkeleton)
|
||||||
userProfileSkeleton.classList.remove("hidden");
|
userProfileSkeleton.classList.remove("hidden");
|
||||||
if (userProfileSummary)
|
if (userProfileSummary) userProfileSummary.classList.add("hidden");
|
||||||
userProfileSummary.classList.add("hidden");
|
|
||||||
if (userProfileSignedOut)
|
if (userProfileSignedOut)
|
||||||
userProfileSignedOut.classList.add("hidden");
|
userProfileSignedOut.classList.add("hidden");
|
||||||
if (menuLoadingSkeleton)
|
if (menuLoadingSkeleton)
|
||||||
|
@ -700,15 +624,11 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
await updateUserProfile(user);
|
await updateUserProfile(user);
|
||||||
|
|
||||||
// Show actual profile and hide skeleton
|
// Show actual profile and hide skeleton
|
||||||
if (userProfileSkeleton)
|
if (userProfileSkeleton) userProfileSkeleton.classList.add("hidden");
|
||||||
userProfileSkeleton.classList.add("hidden");
|
if (userProfileSummary) userProfileSummary.classList.remove("hidden");
|
||||||
if (userProfileSummary)
|
|
||||||
userProfileSummary.classList.remove("hidden");
|
|
||||||
|
|
||||||
// Hide all sections first
|
// Hide all sections first
|
||||||
document
|
document.querySelectorAll(".dashboard-section").forEach((section) => {
|
||||||
.querySelectorAll(".dashboard-section")
|
|
||||||
.forEach((section) => {
|
|
||||||
section.classList.add("hidden");
|
section.classList.add("hidden");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -725,7 +645,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
"",
|
"",
|
||||||
{
|
{
|
||||||
fields: ["id", "type", "role"],
|
fields: ["id", "type", "role"],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (officerRecords && officerRecords.items.length > 0) {
|
if (officerRecords && officerRecords.items.length > 0) {
|
||||||
|
@ -763,23 +683,17 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
"",
|
"",
|
||||||
{
|
{
|
||||||
fields: ["id", "company"],
|
fields: ["id", "company"],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (sponsorRecords && sponsorRecords.items.length > 0) {
|
||||||
sponsorRecords &&
|
|
||||||
sponsorRecords.items.length > 0
|
|
||||||
) {
|
|
||||||
officerStatus = "sponsor";
|
officerStatus = "sponsor";
|
||||||
} else {
|
} else {
|
||||||
officerStatus = "none";
|
officerStatus = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error("Error determining officer status:", error);
|
||||||
"Error determining officer status:",
|
|
||||||
error
|
|
||||||
);
|
|
||||||
officerStatus = "none";
|
officerStatus = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,24 +704,17 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
// Only sponsors get a different default view
|
// Only sponsors get a different default view
|
||||||
if (officerStatus === "sponsor") {
|
if (officerStatus === "sponsor") {
|
||||||
// For sponsors, show the sponsor dashboard
|
// For sponsors, show the sponsor dashboard
|
||||||
defaultSection = document.getElementById(
|
defaultSection = document.getElementById("sponsorDashboardSection");
|
||||||
"sponsorDashboardSection"
|
|
||||||
);
|
|
||||||
defaultButton = document.querySelector(
|
defaultButton = document.querySelector(
|
||||||
'[data-section="sponsorDashboard"]'
|
'[data-section="sponsorDashboard"]',
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// For all other users (including administrators), show the profile section
|
// For all other users (including administrators), show the profile section
|
||||||
defaultSection =
|
defaultSection = document.getElementById("profileSection");
|
||||||
document.getElementById("profileSection");
|
defaultButton = document.querySelector('[data-section="profile"]');
|
||||||
defaultButton = document.querySelector(
|
|
||||||
'[data-section="profile"]'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Log the default section for debugging
|
// Log the default section for debugging
|
||||||
console.log(
|
// console.log(`Setting default section to profile for user with role: ${officerStatus}`);
|
||||||
`Setting default section to profile for user with role: ${officerStatus}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defaultSection) {
|
if (defaultSection) {
|
||||||
|
@ -821,20 +728,16 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
handleNavigation();
|
handleNavigation();
|
||||||
|
|
||||||
// Show actual menu and hide skeleton
|
// Show actual menu and hide skeleton
|
||||||
if (menuLoadingSkeleton)
|
if (menuLoadingSkeleton) menuLoadingSkeleton.classList.add("hidden");
|
||||||
menuLoadingSkeleton.classList.add("hidden");
|
|
||||||
if (actualMenu) actualMenu.classList.remove("hidden");
|
if (actualMenu) actualMenu.classList.remove("hidden");
|
||||||
|
|
||||||
// Show main content and hide loading
|
// Show main content and hide loading
|
||||||
if (mainContent) mainContent.classList.remove("hidden");
|
if (mainContent) mainContent.classList.remove("hidden");
|
||||||
if (pageLoadingState)
|
if (pageLoadingState) pageLoadingState.classList.add("hidden");
|
||||||
pageLoadingState.classList.add("hidden");
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error initializing dashboard:", error);
|
console.error("Error initializing dashboard:", error);
|
||||||
if (pageLoadingState)
|
if (pageLoadingState) pageLoadingState.classList.add("hidden");
|
||||||
pageLoadingState.classList.add("hidden");
|
if (pageErrorState) pageErrorState.classList.remove("hidden");
|
||||||
if (pageErrorState)
|
|
||||||
pageErrorState.classList.remove("hidden");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -846,24 +749,19 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
.querySelector(".login-button")
|
.querySelector(".login-button")
|
||||||
?.addEventListener("click", async () => {
|
?.addEventListener("click", async () => {
|
||||||
try {
|
try {
|
||||||
if (pageLoadingState)
|
if (pageLoadingState) pageLoadingState.classList.remove("hidden");
|
||||||
pageLoadingState.classList.remove("hidden");
|
|
||||||
if (notAuthenticatedState)
|
if (notAuthenticatedState)
|
||||||
notAuthenticatedState.classList.add("hidden");
|
notAuthenticatedState.classList.add("hidden");
|
||||||
await auth.login();
|
await auth.login();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Login error:", error);
|
console.error("Login error:", error);
|
||||||
if (pageLoadingState)
|
if (pageLoadingState) pageLoadingState.classList.add("hidden");
|
||||||
pageLoadingState.classList.add("hidden");
|
if (pageErrorState) pageErrorState.classList.remove("hidden");
|
||||||
if (pageErrorState)
|
|
||||||
pageErrorState.classList.remove("hidden");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle logout button click
|
// Handle logout button click
|
||||||
document
|
document.getElementById("logoutButton")?.addEventListener("click", () => {
|
||||||
.getElementById("logoutButton")
|
|
||||||
?.addEventListener("click", () => {
|
|
||||||
auth.logout();
|
auth.logout();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
|
@ -876,8 +774,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
|
||||||
|
|
||||||
window.addEventListener("resize", () => {
|
window.addEventListener("resize", () => {
|
||||||
if (window.innerWidth >= 1024) {
|
if (window.innerWidth >= 1024) {
|
||||||
const overlay =
|
const overlay = document.getElementById("sidebarOverlay");
|
||||||
document.getElementById("sidebarOverlay");
|
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
overlay.remove();
|
overlay.remove();
|
||||||
document.body.classList.remove("overflow-hidden");
|
document.body.classList.remove("overflow-hidden");
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class RedirectHandler {
|
||||||
{ emailVisibility: false },
|
{ emailVisibility: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("Auth successful:", authData);
|
// console.log("Auth successful:", authData);
|
||||||
this.contentEl.innerHTML = `
|
this.contentEl.innerHTML = `
|
||||||
<p class="text-3xl font-bold text-green-500 mb-4">Authentication Successful!</p>
|
<p class="text-3xl font-bold text-green-500 mb-4">Authentication Successful!</p>
|
||||||
<p class="text-2xl font-medium">Initializing your data...</p>
|
<p class="text-2xl font-medium">Initializing your data...</p>
|
||||||
|
@ -99,19 +99,15 @@ export class RedirectHandler {
|
||||||
private async initializeDataSync(): Promise<void> {
|
private async initializeDataSync(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Dynamically import the AuthSyncService to avoid circular dependencies
|
// Dynamically import the AuthSyncService to avoid circular dependencies
|
||||||
const { AuthSyncService } = await import('../database/AuthSyncService');
|
const { AuthSyncService } = await import("../database/AuthSyncService");
|
||||||
|
|
||||||
// Get the instance and trigger a full sync
|
// Get the instance and trigger a full sync
|
||||||
const authSync = AuthSyncService.getInstance();
|
const authSync = AuthSyncService.getInstance();
|
||||||
const syncResult = await authSync.handleLogin();
|
const syncResult = await authSync.handleLogin();
|
||||||
|
|
||||||
if (syncResult) {
|
// console.log('Initial data sync completed successfully');
|
||||||
console.log('Initial data sync completed successfully');
|
|
||||||
} else {
|
|
||||||
console.warn('Initial data sync completed with issues');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initialize data sync:', error);
|
console.error("Failed to initialize data sync:", error);
|
||||||
// Continue with login process even if sync fails
|
// Continue with login process even if sync fails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ export class AuthSyncService {
|
||||||
if (!isBrowser) return true;
|
if (!isBrowser) return true;
|
||||||
|
|
||||||
if (this.isSyncing) {
|
if (this.isSyncing) {
|
||||||
console.log("Sync already in progress, queueing login sync");
|
// console.log("Sync already in progress, queueing login sync");
|
||||||
if (this.syncPromise) {
|
if (this.syncPromise) {
|
||||||
this.syncPromise = this.syncPromise.then(() => this.performLoginSync());
|
this.syncPromise = this.syncPromise.then(() => this.performLoginSync());
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,7 +100,7 @@ export class AuthSyncService {
|
||||||
if (!isBrowser) return;
|
if (!isBrowser) return;
|
||||||
|
|
||||||
if (!this.auth.isAuthenticated()) {
|
if (!this.auth.isAuthenticated()) {
|
||||||
console.log("Not authenticated, skipping login sync");
|
// console.log("Not authenticated, skipping login sync");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ export class AuthSyncService {
|
||||||
this.syncErrors = {};
|
this.syncErrors = {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("Starting login sync process...");
|
// console.log("Starting login sync process...");
|
||||||
|
|
||||||
// Display sync notification if in browser environment
|
// Display sync notification if in browser environment
|
||||||
this.showSyncNotification("Syncing your data...");
|
this.showSyncNotification("Syncing your data...");
|
||||||
|
@ -123,7 +123,7 @@ export class AuthSyncService {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log the sync operation
|
// Log the sync operation
|
||||||
console.log("User data synchronized on login");
|
// console.log("User data synchronized on login");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync all collections in parallel with conflict resolution
|
// Sync all collections in parallel with conflict resolution
|
||||||
|
@ -131,9 +131,9 @@ export class AuthSyncService {
|
||||||
this.collectionsToSync.map(async (collection) => {
|
this.collectionsToSync.map(async (collection) => {
|
||||||
try {
|
try {
|
||||||
await this.dataSync.syncCollection(collection);
|
await this.dataSync.syncCollection(collection);
|
||||||
console.log(`Successfully synced ${collection}`);
|
// console.log(`Successfully synced ${collection}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error syncing ${collection}:`, error);
|
// console.error(`Error syncing ${collection}:`, error);
|
||||||
this.syncErrors[collection] = error as Error;
|
this.syncErrors[collection] = error as Error;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -146,17 +146,17 @@ export class AuthSyncService {
|
||||||
const syncVerification = await this.verifySyncSuccess();
|
const syncVerification = await this.verifySyncSuccess();
|
||||||
|
|
||||||
if (syncVerification.success) {
|
if (syncVerification.success) {
|
||||||
console.log("Login sync completed successfully");
|
// console.log("Login sync completed successfully");
|
||||||
this.showSyncNotification("Data sync complete!", "success");
|
this.showSyncNotification("Data sync complete!", "success");
|
||||||
} else {
|
} else {
|
||||||
console.warn(
|
// console.warn(
|
||||||
"Login sync completed with issues:",
|
// "Login sync completed with issues:",
|
||||||
syncVerification.errors,
|
// syncVerification.errors,
|
||||||
);
|
// );
|
||||||
this.showSyncNotification("Some data could not be synced", "warning");
|
this.showSyncNotification("Some data could not be synced", "warning");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error during login sync:", error);
|
// console.error("Error during login sync:", error);
|
||||||
this.showSyncNotification("Failed to sync data", "error");
|
this.showSyncNotification("Failed to sync data", "error");
|
||||||
} finally {
|
} finally {
|
||||||
this.isSyncing = false;
|
this.isSyncing = false;
|
||||||
|
@ -180,7 +180,7 @@ export class AuthSyncService {
|
||||||
if (!isBrowser) return true;
|
if (!isBrowser) return true;
|
||||||
|
|
||||||
if (this.isSyncing) {
|
if (this.isSyncing) {
|
||||||
console.log("Sync already in progress, queueing logout cleanup");
|
// console.log("Sync already in progress, queueing logout cleanup");
|
||||||
this.syncQueue.push("logout");
|
this.syncQueue.push("logout");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ export class AuthSyncService {
|
||||||
this.isSyncing = true;
|
this.isSyncing = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("Starting logout cleanup process...");
|
// console.log("Starting logout cleanup process...");
|
||||||
|
|
||||||
// Ensure any pending changes are synced before logout
|
// Ensure any pending changes are synced before logout
|
||||||
await this.syncPendingChanges();
|
await this.syncPendingChanges();
|
||||||
|
@ -196,10 +196,10 @@ export class AuthSyncService {
|
||||||
// Clear all data from IndexedDB
|
// Clear all data from IndexedDB
|
||||||
await this.dexieService.clearAllData();
|
await this.dexieService.clearAllData();
|
||||||
|
|
||||||
console.log("Logout cleanup completed successfully");
|
// console.log("Logout cleanup completed successfully");
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error during logout cleanup:", error);
|
// console.error("Error during logout cleanup:", error);
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
this.isSyncing = false;
|
this.isSyncing = false;
|
||||||
|
@ -224,7 +224,7 @@ export class AuthSyncService {
|
||||||
|
|
||||||
// This would be implemented if we had offline capabilities
|
// This would be implemented if we had offline capabilities
|
||||||
// For now, we just log that we would sync pending changes
|
// For now, we just log that we would sync pending changes
|
||||||
console.log("Checking for pending changes to sync before logout...");
|
// console.log("Checking for pending changes to sync before logout...");
|
||||||
// In a real implementation, this would sync any offline changes
|
// In a real implementation, this would sync any offline changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ export class AuthSyncService {
|
||||||
window.toast(message, { type });
|
window.toast(message, { type });
|
||||||
} else {
|
} else {
|
||||||
// Fallback to console
|
// Fallback to console
|
||||||
console.log(`[${type.toUpperCase()}] ${message}`);
|
// console.log(`[${type.toUpperCase()}] ${message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ export class AuthSyncService {
|
||||||
*/
|
*/
|
||||||
public async forceSyncAll(): Promise<boolean> {
|
public async forceSyncAll(): Promise<boolean> {
|
||||||
if (this.isSyncing) {
|
if (this.isSyncing) {
|
||||||
console.log("Sync already in progress, queueing full sync");
|
// console.log("Sync already in progress, queueing full sync");
|
||||||
this.syncQueue.push("login"); // Reuse login sync logic
|
this.syncQueue.push("login"); // Reuse login sync logic
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ export class DataSyncService {
|
||||||
private async handleOnline(): Promise<void> {
|
private async handleOnline(): Promise<void> {
|
||||||
if (!isBrowser) return;
|
if (!isBrowser) return;
|
||||||
|
|
||||||
console.log("Device is online, syncing pending changes...");
|
// console.log("Device is online, syncing pending changes...");
|
||||||
this.offlineMode = false;
|
this.offlineMode = false;
|
||||||
await this.syncOfflineChanges();
|
await this.syncOfflineChanges();
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ export class DataSyncService {
|
||||||
private handleOffline(): void {
|
private handleOffline(): void {
|
||||||
if (!isBrowser) return;
|
if (!isBrowser) return;
|
||||||
|
|
||||||
console.log("Device is offline, enabling offline mode...");
|
// console.log("Device is offline, enabling offline mode...");
|
||||||
this.offlineMode = true;
|
this.offlineMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,13 +109,13 @@ export class DataSyncService {
|
||||||
): Promise<T[]> {
|
): Promise<T[]> {
|
||||||
// Skip in non-browser environments
|
// Skip in non-browser environments
|
||||||
if (!isBrowser) {
|
if (!isBrowser) {
|
||||||
console.log(`Skipping sync for ${collection} in non-browser environment`);
|
// console.log(`Skipping sync for ${collection} in non-browser environment`);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent multiple syncs of the same collection at the same time
|
// Prevent multiple syncs of the same collection at the same time
|
||||||
if (this.syncInProgress[collection]) {
|
if (this.syncInProgress[collection]) {
|
||||||
console.log(`Sync already in progress for ${collection}`);
|
// console.log(`Sync already in progress for ${collection}`);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,19 +124,19 @@ export class DataSyncService {
|
||||||
try {
|
try {
|
||||||
// Check if we're authenticated
|
// Check if we're authenticated
|
||||||
if (!this.auth.isAuthenticated()) {
|
if (!this.auth.isAuthenticated()) {
|
||||||
console.log(`Not authenticated, skipping sync for ${collection}`);
|
// console.log(`Not authenticated, skipping sync for ${collection}`);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we're offline
|
// Check if we're offline
|
||||||
if (this.offlineMode) {
|
if (this.offlineMode) {
|
||||||
console.log(`Device is offline, using cached data for ${collection}`);
|
// console.log(`Device is offline, using cached data for ${collection}`);
|
||||||
const db = this.dexieService.getDB();
|
const db = this.dexieService.getDB();
|
||||||
const table = this.getTableForCollection(collection);
|
const table = this.getTableForCollection(collection);
|
||||||
return table ? ((await table.toArray()) as T[]) : [];
|
return table ? ((await table.toArray()) as T[]) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Syncing ${collection}...`);
|
// console.log(`Syncing ${collection}...`);
|
||||||
|
|
||||||
// Normalize expand parameter to be an array of strings
|
// Normalize expand parameter to be an array of strings
|
||||||
let normalizedExpand: string[] | undefined;
|
let normalizedExpand: string[] | undefined;
|
||||||
|
@ -158,7 +158,7 @@ export class DataSyncService {
|
||||||
const items = await this.get.getAll<T>(collection, filter, sort, {
|
const items = await this.get.getAll<T>(collection, filter, sort, {
|
||||||
expand: normalizedExpand,
|
expand: normalizedExpand,
|
||||||
});
|
});
|
||||||
console.log(`Fetched ${items.length} items from ${collection}`);
|
// console.log(`Fetched ${items.length} items from ${collection}`);
|
||||||
|
|
||||||
// Get the database table
|
// Get the database table
|
||||||
const db = this.dexieService.getDB();
|
const db = this.dexieService.getDB();
|
||||||
|
@ -181,11 +181,11 @@ export class DataSyncService {
|
||||||
const existingItem = existingItemsMap.get(item.id);
|
const existingItem = existingItemsMap.get(item.id);
|
||||||
|
|
||||||
// SECURITY FIX: Remove event_code from events before storing in IndexedDB
|
// SECURITY FIX: Remove event_code from events before storing in IndexedDB
|
||||||
if (collection === Collections.EVENTS && 'event_code' in item) {
|
if (collection === Collections.EVENTS && "event_code" in item) {
|
||||||
// Keep the event_code but ensure files array is properly handled
|
// Keep the event_code but ensure files array is properly handled
|
||||||
if ('files' in item && Array.isArray((item as any).files)) {
|
if ("files" in item && Array.isArray((item as any).files)) {
|
||||||
// Ensure files array is properly stored
|
// Ensure files array is properly stored
|
||||||
console.log(`Event ${item.id} has ${(item as any).files.length} files`);
|
// console.log(`Event ${item.id} has ${(item as any).files.length} files`);
|
||||||
} else {
|
} else {
|
||||||
// Initialize empty files array if not present
|
// Initialize empty files array if not present
|
||||||
(item as any).files = [];
|
(item as any).files = [];
|
||||||
|
@ -232,18 +232,21 @@ export class DataSyncService {
|
||||||
// For events, ensure we handle the files field properly
|
// For events, ensure we handle the files field properly
|
||||||
if (collection === Collections.EVENTS) {
|
if (collection === Collections.EVENTS) {
|
||||||
// Ensure files array is properly handled
|
// Ensure files array is properly handled
|
||||||
if ('files' in serverItem && Array.isArray((serverItem as any).files)) {
|
if ("files" in serverItem && Array.isArray((serverItem as any).files)) {
|
||||||
console.log(`Server event ${serverItem.id} has ${(serverItem as any).files.length} files`);
|
// console.log(`Server event ${serverItem.id} has ${(serverItem as any).files.length} files`);
|
||||||
} else {
|
} else {
|
||||||
// Initialize empty files array if not present
|
// Initialize empty files array if not present
|
||||||
(serverItem as any).files = [];
|
(serverItem as any).files = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If local item has files but server doesn't, preserve local files
|
// If local item has files but server doesn't, preserve local files
|
||||||
if ('files' in localItem && Array.isArray((localItem as any).files) &&
|
if (
|
||||||
|
"files" in localItem &&
|
||||||
|
Array.isArray((localItem as any).files) &&
|
||||||
(localItem as any).files.length > 0 &&
|
(localItem as any).files.length > 0 &&
|
||||||
(!('files' in serverItem) || !(serverItem as any).files.length)) {
|
(!("files" in serverItem) || !(serverItem as any).files.length)
|
||||||
console.log(`Preserving local files for event ${localItem.id}`);
|
) {
|
||||||
|
// console.log(`Preserving local files for event ${localItem.id}`);
|
||||||
(serverItem as any).files = (localItem as any).files;
|
(serverItem as any).files = (localItem as any).files;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,9 +258,9 @@ export class DataSyncService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (pendingChanges.length > 0) {
|
if (pendingChanges.length > 0) {
|
||||||
console.log(
|
// console.log(
|
||||||
`Found ${pendingChanges.length} pending changes for ${collection}:${localItem.id}`,
|
// `Found ${pendingChanges.length} pending changes for ${collection}:${localItem.id}`,
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Server-wins strategy by default, but preserve local changes that haven't been synced
|
// Server-wins strategy by default, but preserve local changes that haven't been synced
|
||||||
const mergedItem = { ...serverItem };
|
const mergedItem = { ...serverItem };
|
||||||
|
@ -268,12 +271,16 @@ export class DataSyncService {
|
||||||
// Apply each field change individually
|
// Apply each field change individually
|
||||||
Object.entries(change.data).forEach(([key, value]) => {
|
Object.entries(change.data).forEach(([key, value]) => {
|
||||||
// Special handling for files array
|
// Special handling for files array
|
||||||
if (key === 'files' && Array.isArray(value)) {
|
if (key === "files" && Array.isArray(value)) {
|
||||||
// Merge files arrays, removing duplicates
|
// Merge files arrays, removing duplicates
|
||||||
const existingFiles = Array.isArray((mergedItem as any)[key]) ? (mergedItem as any)[key] : [];
|
const existingFiles = Array.isArray((mergedItem as any)[key])
|
||||||
|
? (mergedItem as any)[key]
|
||||||
|
: [];
|
||||||
const newFiles = value as string[];
|
const newFiles = value as string[];
|
||||||
(mergedItem as any)[key] = [...new Set([...existingFiles, ...newFiles])];
|
(mergedItem as any)[key] = [
|
||||||
console.log(`Merged files for ${collection}:${localItem.id}`, (mergedItem as any)[key]);
|
...new Set([...existingFiles, ...newFiles]),
|
||||||
|
];
|
||||||
|
// console.log(`Merged files for ${collection}:${localItem.id}`, (mergedItem as any)[key]);
|
||||||
} else {
|
} else {
|
||||||
(mergedItem as any)[key] = value;
|
(mergedItem as any)[key] = value;
|
||||||
}
|
}
|
||||||
|
@ -326,11 +333,11 @@ export class DataSyncService {
|
||||||
.toArray();
|
.toArray();
|
||||||
|
|
||||||
if (pendingChanges.length === 0) {
|
if (pendingChanges.length === 0) {
|
||||||
console.log("No pending offline changes to sync");
|
// console.log("No pending offline changes to sync");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Syncing ${pendingChanges.length} offline changes...`);
|
// console.log(`Syncing ${pendingChanges.length} offline changes...`);
|
||||||
|
|
||||||
// Group changes by collection for more efficient processing
|
// Group changes by collection for more efficient processing
|
||||||
const changesByCollection = pendingChanges.reduce(
|
const changesByCollection = pendingChanges.reduce(
|
||||||
|
@ -411,9 +418,9 @@ export class DataSyncService {
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = await this.offlineChangesTable.add(change as OfflineChange);
|
const id = await this.offlineChangesTable.add(change as OfflineChange);
|
||||||
console.log(
|
// console.log(
|
||||||
`Recorded offline change: ${operation} on ${collection}:${recordId}`,
|
// `Recorded offline change: ${operation} on ${collection}:${recordId}`,
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Try to sync immediately if we're online
|
// Try to sync immediately if we're online
|
||||||
if (!this.offlineMode) {
|
if (!this.offlineMode) {
|
||||||
|
@ -500,7 +507,7 @@ export class DataSyncService {
|
||||||
// SECURITY FIX: Remove event_code from events before returning them
|
// SECURITY FIX: Remove event_code from events before returning them
|
||||||
if (collection === Collections.EVENTS) {
|
if (collection === Collections.EVENTS) {
|
||||||
data = data.map((item: any) => {
|
data = data.map((item: any) => {
|
||||||
if ('event_code' in item) {
|
if ("event_code" in item) {
|
||||||
const { event_code, ...rest } = item;
|
const { event_code, ...rest } = item;
|
||||||
return rest;
|
return rest;
|
||||||
}
|
}
|
||||||
|
@ -538,14 +545,19 @@ export class DataSyncService {
|
||||||
// For events, ensure we handle the files field properly
|
// For events, ensure we handle the files field properly
|
||||||
if (collection === Collections.EVENTS) {
|
if (collection === Collections.EVENTS) {
|
||||||
// Ensure files array is properly handled
|
// Ensure files array is properly handled
|
||||||
if (!('files' in pbItem) || !Array.isArray((pbItem as any).files)) {
|
if (!("files" in pbItem) || !Array.isArray((pbItem as any).files)) {
|
||||||
(pbItem as any).files = [];
|
(pbItem as any).files = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we already have a local item with files, preserve them if server has none
|
// If we already have a local item with files, preserve them if server has none
|
||||||
if (item && 'files' in item && Array.isArray((item as any).files) &&
|
if (
|
||||||
(item as any).files.length > 0 && !(pbItem as any).files.length) {
|
item &&
|
||||||
console.log(`Preserving local files for event ${id}`);
|
"files" in item &&
|
||||||
|
Array.isArray((item as any).files) &&
|
||||||
|
(item as any).files.length > 0 &&
|
||||||
|
!(pbItem as any).files.length
|
||||||
|
) {
|
||||||
|
// console.log(`Preserving local files for event ${id}`);
|
||||||
(pbItem as any).files = (item as any).files;
|
(pbItem as any).files = (item as any).files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,8 +599,8 @@ export class DataSyncService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special handling for files field in events
|
// Special handling for files field in events
|
||||||
if (collection === Collections.EVENTS && 'files' in data) {
|
if (collection === Collections.EVENTS && "files" in data) {
|
||||||
console.log(`Updating files for event ${id}`, (data as any).files);
|
// console.log(`Updating files for event ${id}`, (data as any).files);
|
||||||
|
|
||||||
// Ensure files is an array
|
// Ensure files is an array
|
||||||
if (!Array.isArray((data as any).files)) {
|
if (!Array.isArray((data as any).files)) {
|
||||||
|
@ -596,12 +608,12 @@ export class DataSyncService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're updating files, make sure we're not losing any
|
// If we're updating files, make sure we're not losing any
|
||||||
if ('files' in currentItem && Array.isArray((currentItem as any).files)) {
|
if ("files" in currentItem && Array.isArray((currentItem as any).files)) {
|
||||||
// Merge files arrays, removing duplicates
|
// Merge files arrays, removing duplicates
|
||||||
const existingFiles = (currentItem as any).files as string[];
|
const existingFiles = (currentItem as any).files as string[];
|
||||||
const newFiles = (data as any).files as string[];
|
const newFiles = (data as any).files as string[];
|
||||||
(data as any).files = [...new Set([...existingFiles, ...newFiles])];
|
(data as any).files = [...new Set([...existingFiles, ...newFiles])];
|
||||||
console.log(`Merged files for event ${id}`, (data as any).files);
|
// console.log(`Merged files for event ${id}`, (data as any).files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,11 +701,14 @@ export class DataSyncService {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Store in localStorage instead of IndexedDB for security
|
// Store in localStorage instead of IndexedDB for security
|
||||||
localStorage.setItem('pending_event_code', eventCode);
|
localStorage.setItem("pending_event_code", eventCode);
|
||||||
localStorage.setItem('pending_event_code_timestamp', Date.now().toString());
|
localStorage.setItem(
|
||||||
console.log('Event code stored for offline check-in');
|
"pending_event_code_timestamp",
|
||||||
|
Date.now().toString(),
|
||||||
|
);
|
||||||
|
// console.log('Event code stored for offline check-in');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error storing event code:', error);
|
console.error("Error storing event code:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,11 +719,11 @@ export class DataSyncService {
|
||||||
if (!isBrowser) return;
|
if (!isBrowser) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
localStorage.removeItem('pending_event_code');
|
localStorage.removeItem("pending_event_code");
|
||||||
localStorage.removeItem('pending_event_code_timestamp');
|
localStorage.removeItem("pending_event_code_timestamp");
|
||||||
console.log('Event code cleared');
|
// console.log('Event code cleared');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error clearing event code:', error);
|
console.error("Error clearing event code:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,21 +731,24 @@ export class DataSyncService {
|
||||||
* Get the stored event code from local storage
|
* Get the stored event code from local storage
|
||||||
* @returns The stored event code, or null if none exists
|
* @returns The stored event code, or null if none exists
|
||||||
*/
|
*/
|
||||||
public async getStoredEventCode(): Promise<{ code: string; timestamp: number } | null> {
|
public async getStoredEventCode(): Promise<{
|
||||||
|
code: string;
|
||||||
|
timestamp: number;
|
||||||
|
} | null> {
|
||||||
if (!isBrowser) return null;
|
if (!isBrowser) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const code = localStorage.getItem('pending_event_code');
|
const code = localStorage.getItem("pending_event_code");
|
||||||
const timestamp = localStorage.getItem('pending_event_code_timestamp');
|
const timestamp = localStorage.getItem("pending_event_code_timestamp");
|
||||||
|
|
||||||
if (!code || !timestamp) return null;
|
if (!code || !timestamp) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code,
|
code,
|
||||||
timestamp: parseInt(timestamp)
|
timestamp: parseInt(timestamp),
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting stored event code:', error);
|
console.error("Error getting stored event code:", error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,7 +765,7 @@ export class DataSyncService {
|
||||||
const table = this.getTableForCollection(Collections.EVENTS);
|
const table = this.getTableForCollection(Collections.EVENTS);
|
||||||
|
|
||||||
if (!table) {
|
if (!table) {
|
||||||
console.error('Events table not found');
|
console.error("Events table not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,8 +773,8 @@ export class DataSyncService {
|
||||||
const events = await table.toArray();
|
const events = await table.toArray();
|
||||||
|
|
||||||
// Remove event_code from each event
|
// Remove event_code from each event
|
||||||
const updatedEvents = events.map(event => {
|
const updatedEvents = events.map((event) => {
|
||||||
if ('event_code' in event) {
|
if ("event_code" in event) {
|
||||||
const { event_code, ...rest } = event;
|
const { event_code, ...rest } = event;
|
||||||
return rest;
|
return rest;
|
||||||
}
|
}
|
||||||
|
@ -767,9 +785,9 @@ export class DataSyncService {
|
||||||
await table.clear();
|
await table.clear();
|
||||||
await table.bulkAdd(updatedEvents);
|
await table.bulkAdd(updatedEvents);
|
||||||
|
|
||||||
console.log('Successfully purged event codes from IndexedDB');
|
// console.log('Successfully purged event codes from IndexedDB');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error purging event codes:', error);
|
console.error("Error purging event codes:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,8 @@ export class DashboardDatabase extends Dexie {
|
||||||
|
|
||||||
// Add version 4 with files field in events table
|
// Add version 4 with files field in events table
|
||||||
this.version(4).stores({
|
this.version(4).stores({
|
||||||
events: "id, event_name, event_code, start_date, end_date, published, files",
|
events:
|
||||||
|
"id, event_name, event_code, start_date, end_date, published, files",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +126,7 @@ export class DexieService {
|
||||||
this.db.initialize();
|
this.db.initialize();
|
||||||
} else {
|
} else {
|
||||||
// Use a mock database in non-browser environments
|
// Use a mock database in non-browser environments
|
||||||
console.log("Running in Node.js environment, using mock database");
|
// console.log("Running in Node.js environment, using mock database");
|
||||||
this.db = new MockDashboardDatabase() as any;
|
this.db = new MockDashboardDatabase() as any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Authentication } from '../pocketbase/Authentication';
|
import { Authentication } from "../pocketbase/Authentication";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize authentication synchronization
|
* Initialize authentication synchronization
|
||||||
|
@ -13,23 +13,23 @@ export async function initAuthSync(): Promise<void> {
|
||||||
// This will trigger the lazy loading of AuthSyncService
|
// This will trigger the lazy loading of AuthSyncService
|
||||||
// through the onAuthStateChange mechanism
|
// through the onAuthStateChange mechanism
|
||||||
auth.onAuthStateChange(() => {
|
auth.onAuthStateChange(() => {
|
||||||
console.log('Auth sync initialized and listening for auth state changes');
|
// console.log('Auth sync initialized and listening for auth state changes');
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Auth sync initialization complete');
|
// console.log('Auth sync initialization complete');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initialize auth sync:', error);
|
console.error("Failed to initialize auth sync:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export a function to manually trigger a full sync
|
// Export a function to manually trigger a full sync
|
||||||
export async function forceFullSync(): Promise<boolean> {
|
export async function forceFullSync(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const { AuthSyncService } = await import('./AuthSyncService');
|
const { AuthSyncService } = await import("./AuthSyncService");
|
||||||
const authSync = AuthSyncService.getInstance();
|
const authSync = AuthSyncService.getInstance();
|
||||||
return await authSync.forceSyncAll();
|
return await authSync.forceSyncAll();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to force full sync:', error);
|
console.error("Failed to force full sync:", error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -89,7 +89,7 @@ export class Authentication {
|
||||||
await this.initAuthSyncService();
|
await this.initAuthSyncService();
|
||||||
|
|
||||||
// Get AuthSyncService instance
|
// Get AuthSyncService instance
|
||||||
const { AuthSyncService } = await import('../database/AuthSyncService');
|
const { AuthSyncService } = await import("../database/AuthSyncService");
|
||||||
const authSync = AuthSyncService.getInstance();
|
const authSync = AuthSyncService.getInstance();
|
||||||
|
|
||||||
// Handle data cleanup before actual logout
|
// Handle data cleanup before actual logout
|
||||||
|
@ -98,9 +98,9 @@ export class Authentication {
|
||||||
// Clear auth store
|
// Clear auth store
|
||||||
this.pb.authStore.clear();
|
this.pb.authStore.clear();
|
||||||
|
|
||||||
console.log('Logout completed successfully with data cleanup');
|
// console.log('Logout completed successfully with data cleanup');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error during logout:', error);
|
console.error("Error during logout:", error);
|
||||||
// Fallback to basic logout if sync fails
|
// Fallback to basic logout if sync fails
|
||||||
this.pb.authStore.clear();
|
this.pb.authStore.clear();
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,10 @@ export class Authentication {
|
||||||
this.authChangeCallbacks.push(callback);
|
this.authChangeCallbacks.push(callback);
|
||||||
|
|
||||||
// Initialize AuthSyncService when first callback is registered
|
// Initialize AuthSyncService when first callback is registered
|
||||||
if (!this.authSyncServiceInitialized && this.authChangeCallbacks.length === 1) {
|
if (
|
||||||
|
!this.authSyncServiceInitialized &&
|
||||||
|
this.authChangeCallbacks.length === 1
|
||||||
|
) {
|
||||||
this.initAuthSyncService();
|
this.initAuthSyncService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,23 +176,23 @@ export class Authentication {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Dynamically import AuthSyncService to avoid circular dependencies
|
// Dynamically import AuthSyncService to avoid circular dependencies
|
||||||
const { AuthSyncService } = await import('../database/AuthSyncService');
|
const { AuthSyncService } = await import("../database/AuthSyncService");
|
||||||
|
|
||||||
// Initialize the service
|
// Initialize the service
|
||||||
AuthSyncService.getInstance();
|
AuthSyncService.getInstance();
|
||||||
|
|
||||||
this.authSyncServiceInitialized = true;
|
this.authSyncServiceInitialized = true;
|
||||||
console.log('AuthSyncService initialized successfully');
|
// console.log('AuthSyncService initialized successfully');
|
||||||
|
|
||||||
// If user is already authenticated, trigger initial sync
|
// If user is already authenticated, trigger initial sync
|
||||||
if (this.isAuthenticated()) {
|
if (this.isAuthenticated()) {
|
||||||
const authSync = AuthSyncService.getInstance();
|
const authSync = AuthSyncService.getInstance();
|
||||||
authSync.handleLogin().catch(err => {
|
authSync.handleLogin().catch((err) => {
|
||||||
console.error('Error during initial data sync:', err);
|
console.error("Error during initial data sync:", err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initialize AuthSyncService:', error);
|
console.error("Failed to initialize AuthSyncService:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Authentication } from "./Authentication";
|
||||||
export class FileManager {
|
export class FileManager {
|
||||||
private auth: Authentication;
|
private auth: Authentication;
|
||||||
private static instance: FileManager;
|
private static instance: FileManager;
|
||||||
private static UNSUPPORTED_EXTENSIONS = ['afdesign', 'psd', 'ai', 'sketch'];
|
private static UNSUPPORTED_EXTENSIONS = ["afdesign", "psd", "ai", "sketch"];
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
this.auth = Authentication.getInstance();
|
this.auth = Authentication.getInstance();
|
||||||
|
@ -25,12 +25,15 @@ export class FileManager {
|
||||||
* @returns Object with validation result and reason if invalid
|
* @returns Object with validation result and reason if invalid
|
||||||
*/
|
*/
|
||||||
public validateFileType(file: File): { valid: boolean; reason?: string } {
|
public validateFileType(file: File): { valid: boolean; reason?: string } {
|
||||||
const fileExtension = file.name.split('.').pop()?.toLowerCase();
|
const fileExtension = file.name.split(".").pop()?.toLowerCase();
|
||||||
|
|
||||||
if (fileExtension && FileManager.UNSUPPORTED_EXTENSIONS.includes(fileExtension)) {
|
if (
|
||||||
|
fileExtension &&
|
||||||
|
FileManager.UNSUPPORTED_EXTENSIONS.includes(fileExtension)
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
valid: false,
|
valid: false,
|
||||||
reason: `File type .${fileExtension} is not supported. Please convert to PDF or image format.`
|
reason: `File type .${fileExtension} is not supported. Please convert to PDF or image format.`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +54,7 @@ export class FileManager {
|
||||||
recordId: string,
|
recordId: string,
|
||||||
field: string,
|
field: string,
|
||||||
file: File,
|
file: File,
|
||||||
append: boolean = false
|
append: boolean = false,
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
if (!this.auth.isAuthenticated()) {
|
if (!this.auth.isAuthenticated()) {
|
||||||
throw new Error("User must be authenticated to upload files");
|
throw new Error("User must be authenticated to upload files");
|
||||||
|
@ -64,11 +67,13 @@ export class FileManager {
|
||||||
// Validate file size
|
// Validate file size
|
||||||
const maxSize = 200 * 1024 * 1024; // 200MB
|
const maxSize = 200 * 1024 * 1024; // 200MB
|
||||||
if (file.size > maxSize) {
|
if (file.size > maxSize) {
|
||||||
throw new Error(`File size ${(file.size / 1024 / 1024).toFixed(2)}MB exceeds 200MB limit`);
|
throw new Error(
|
||||||
|
`File size ${(file.size / 1024 / 1024).toFixed(2)}MB exceeds 200MB limit`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for potentially problematic file types
|
// Check for potentially problematic file types
|
||||||
const fileExtension = file.name.split('.').pop()?.toLowerCase();
|
const fileExtension = file.name.split(".").pop()?.toLowerCase();
|
||||||
|
|
||||||
// Validate file type
|
// Validate file type
|
||||||
const validation = this.validateFileType(file);
|
const validation = this.validateFileType(file);
|
||||||
|
@ -77,16 +82,16 @@ export class FileManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log upload attempt
|
// Log upload attempt
|
||||||
console.log('Attempting file upload:', {
|
// console.log('Attempting file upload:', {
|
||||||
name: file.name,
|
// name: file.name,
|
||||||
size: file.size,
|
// size: file.size,
|
||||||
type: file.type,
|
// type: file.type,
|
||||||
extension: fileExtension,
|
// extension: fileExtension,
|
||||||
collection: collectionName,
|
// collection: collectionName,
|
||||||
recordId: recordId,
|
// recordId: recordId,
|
||||||
field: field,
|
// field: field,
|
||||||
append: append
|
// append: append
|
||||||
});
|
// });
|
||||||
|
|
||||||
// Create FormData for the upload
|
// Create FormData for the upload
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
@ -104,20 +109,21 @@ export class FileManager {
|
||||||
existingFiles = existingRecord[field] || [];
|
existingFiles = existingRecord[field] || [];
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Could not fetch existing record:', error);
|
// console.warn('Could not fetch existing record:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the file already exists
|
// Check if the file already exists
|
||||||
const fileExists = existingFiles.some(existingFile =>
|
const fileExists = existingFiles.some(
|
||||||
existingFile.toLowerCase() === file.name.toLowerCase()
|
(existingFile) =>
|
||||||
|
existingFile.toLowerCase() === file.name.toLowerCase(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (fileExists) {
|
if (fileExists) {
|
||||||
console.warn(`File with name ${file.name} already exists. Renaming to avoid conflicts.`);
|
// console.warn(`File with name ${file.name} already exists. Renaming to avoid conflicts.`);
|
||||||
const timestamp = new Date().getTime();
|
const timestamp = new Date().getTime();
|
||||||
const nameParts = file.name.split('.');
|
const nameParts = file.name.split(".");
|
||||||
const extension = nameParts.pop();
|
const extension = nameParts.pop();
|
||||||
const baseName = nameParts.join('.');
|
const baseName = nameParts.join(".");
|
||||||
const newFileName = `${baseName}_${timestamp}.${extension}`;
|
const newFileName = `${baseName}_${timestamp}.${extension}`;
|
||||||
|
|
||||||
// Create a new file with the modified name
|
// Create a new file with the modified name
|
||||||
|
@ -128,59 +134,70 @@ export class FileManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await pb.collection(collectionName).update<T>(recordId, formData);
|
const result = await pb
|
||||||
console.log('Upload successful:', {
|
.collection(collectionName)
|
||||||
result,
|
.update<T>(recordId, formData);
|
||||||
fileInfo: {
|
// console.log('Upload successful:', {
|
||||||
name: file.name,
|
// result,
|
||||||
size: file.size,
|
// fileInfo: {
|
||||||
type: file.type
|
// name: file.name,
|
||||||
},
|
// size: file.size,
|
||||||
collection: collectionName,
|
// type: file.type
|
||||||
recordId: recordId
|
// },
|
||||||
});
|
// collection: collectionName,
|
||||||
|
// recordId: recordId
|
||||||
|
// });
|
||||||
|
|
||||||
// Verify the file was actually added to the record
|
// Verify the file was actually added to the record
|
||||||
try {
|
try {
|
||||||
const updatedRecord = await pb.collection(collectionName).getOne(recordId);
|
const updatedRecord = await pb
|
||||||
console.log('Updated record files:', {
|
.collection(collectionName)
|
||||||
files: updatedRecord.files,
|
.getOne(recordId);
|
||||||
recordId: recordId
|
// console.log('Updated record files:', {
|
||||||
});
|
// files: updatedRecord.files,
|
||||||
|
// recordId: recordId
|
||||||
|
// });
|
||||||
} catch (verifyError) {
|
} catch (verifyError) {
|
||||||
console.warn('Could not verify file upload:', verifyError);
|
// console.warn('Could not verify file upload:', verifyError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} catch (pbError: any) {
|
} catch (pbError: any) {
|
||||||
// Log detailed PocketBase error
|
// Log detailed PocketBase error
|
||||||
console.error('PocketBase upload error:', {
|
// console.error('PocketBase upload error:', {
|
||||||
status: pbError?.status,
|
// status: pbError?.status,
|
||||||
response: pbError?.response,
|
// response: pbError?.response,
|
||||||
data: pbError?.data,
|
// data: pbError?.data,
|
||||||
message: pbError?.message
|
// message: pbError?.message
|
||||||
});
|
// });
|
||||||
|
|
||||||
// More specific error message based on file type
|
// More specific error message based on file type
|
||||||
if (fileExtension && FileManager.UNSUPPORTED_EXTENSIONS.includes(fileExtension)) {
|
if (
|
||||||
throw new Error(`Upload failed: File type .${fileExtension} is not supported. Please convert to PDF or image format.`);
|
fileExtension &&
|
||||||
|
FileManager.UNSUPPORTED_EXTENSIONS.includes(fileExtension)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Upload failed: File type .${fileExtension} is not supported. Please convert to PDF or image format.`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Upload failed: ${pbError?.message || 'Unknown PocketBase error'}`);
|
throw new Error(
|
||||||
|
`Upload failed: ${pbError?.message || "Unknown PocketBase error"}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to upload file to ${collectionName}:`, {
|
// console.error(`Failed to upload file to ${collectionName}:`, {
|
||||||
error: err,
|
// error: err,
|
||||||
fileInfo: {
|
// fileInfo: {
|
||||||
name: file.name,
|
// name: file.name,
|
||||||
size: file.size,
|
// size: file.size,
|
||||||
type: file.type
|
// type: file.type
|
||||||
},
|
// },
|
||||||
auth: {
|
// auth: {
|
||||||
isAuthenticated: this.auth.isAuthenticated(),
|
// isAuthenticated: this.auth.isAuthenticated(),
|
||||||
userId: this.auth.getUserId()
|
// userId: this.auth.getUserId()
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (err instanceof Error) {
|
if (err instanceof Error) {
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -241,7 +258,7 @@ export class FileManager {
|
||||||
.getOne<T>(recordId);
|
.getOne<T>(recordId);
|
||||||
existingFiles = (record as any)[field] || [];
|
existingFiles = (record as any)[field] || [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("Failed to fetch existing record:", error);
|
// console.warn("Failed to fetch existing record:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +277,7 @@ export class FileManager {
|
||||||
processedFile = await this.compressImageIfNeeded(file, 50); // 50MB max size
|
processedFile = await this.compressImageIfNeeded(file, 50); // 50MB max size
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`Failed to process file ${file.name}:`, error);
|
// console.warn(`Failed to process file ${file.name}:`, error);
|
||||||
processedFile = file; // Use original file if processing fails
|
processedFile = file; // Use original file if processing fails
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +315,7 @@ export class FileManager {
|
||||||
.getOne<T>(recordId);
|
.getOne<T>(recordId);
|
||||||
return finalRecord;
|
return finalRecord;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to upload files to ${collectionName}:`, err);
|
// console.error(`Failed to upload files to ${collectionName}:`, err);
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
this.auth.setUpdating(false);
|
this.auth.setUpdating(false);
|
||||||
|
@ -324,7 +341,7 @@ export class FileManager {
|
||||||
const record = await pb.collection(collectionName).getOne(recordId);
|
const record = await pb.collection(collectionName).getOne(recordId);
|
||||||
existingFiles = record[field] || [];
|
existingFiles = record[field] || [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("Failed to fetch existing record for duplicate check:", error);
|
// console.warn("Failed to fetch existing record for duplicate check:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new files, renaming duplicates if needed
|
// Add new files, renaming duplicates if needed
|
||||||
|
@ -334,15 +351,15 @@ export class FileManager {
|
||||||
// Check if filename already exists
|
// Check if filename already exists
|
||||||
if (Array.isArray(existingFiles) && existingFiles.includes(file.name)) {
|
if (Array.isArray(existingFiles) && existingFiles.includes(file.name)) {
|
||||||
const timestamp = new Date().getTime();
|
const timestamp = new Date().getTime();
|
||||||
const nameParts = file.name.split('.');
|
const nameParts = file.name.split(".");
|
||||||
const extension = nameParts.pop();
|
const extension = nameParts.pop();
|
||||||
const baseName = nameParts.join('.');
|
const baseName = nameParts.join(".");
|
||||||
const newFileName = `${baseName}_${timestamp}.${extension}`;
|
const newFileName = `${baseName}_${timestamp}.${extension}`;
|
||||||
|
|
||||||
// Create a new file with the modified name
|
// Create a new file with the modified name
|
||||||
fileToUpload = new File([file], newFileName, { type: file.type });
|
fileToUpload = new File([file], newFileName, { type: file.type });
|
||||||
|
|
||||||
console.log(`Renamed duplicate file from ${file.name} to ${newFileName}`);
|
// console.log(`Renamed duplicate file from ${file.name} to ${newFileName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
formData.append(field, fileToUpload);
|
formData.append(field, fileToUpload);
|
||||||
|
@ -350,7 +367,7 @@ export class FileManager {
|
||||||
|
|
||||||
// Tell PocketBase to keep existing files
|
// Tell PocketBase to keep existing files
|
||||||
if (existingFiles.length > 0) {
|
if (existingFiles.length > 0) {
|
||||||
formData.append(`${field}@`, ''); // This tells PocketBase to keep existing files
|
formData.append(`${field}@`, ""); // This tells PocketBase to keep existing files
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -398,7 +415,7 @@ export class FileManager {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
// Tell PocketBase to keep existing files
|
// Tell PocketBase to keep existing files
|
||||||
formData.append(`${field}@`, '');
|
formData.append(`${field}@`, "");
|
||||||
|
|
||||||
// Append new files, renaming if needed to avoid duplicates
|
// Append new files, renaming if needed to avoid duplicates
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
|
@ -407,15 +424,15 @@ export class FileManager {
|
||||||
// Check if filename already exists
|
// Check if filename already exists
|
||||||
if (existingFilenames.has(file.name)) {
|
if (existingFilenames.has(file.name)) {
|
||||||
const timestamp = new Date().getTime();
|
const timestamp = new Date().getTime();
|
||||||
const nameParts = file.name.split('.');
|
const nameParts = file.name.split(".");
|
||||||
const extension = nameParts.pop();
|
const extension = nameParts.pop();
|
||||||
const baseName = nameParts.join('.');
|
const baseName = nameParts.join(".");
|
||||||
const newFileName = `${baseName}_${timestamp}.${extension}`;
|
const newFileName = `${baseName}_${timestamp}.${extension}`;
|
||||||
|
|
||||||
// Create a new file with the modified name
|
// Create a new file with the modified name
|
||||||
fileToUpload = new File([file], newFileName, { type: file.type });
|
fileToUpload = new File([file], newFileName, { type: file.type });
|
||||||
|
|
||||||
console.log(`Renamed duplicate file from ${file.name} to ${newFileName}`);
|
// console.log(`Renamed duplicate file from ${file.name} to ${newFileName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
formData.append(field, fileToUpload);
|
formData.append(field, fileToUpload);
|
||||||
|
@ -426,7 +443,7 @@ export class FileManager {
|
||||||
.update<T>(recordId, formData);
|
.update<T>(recordId, formData);
|
||||||
return result;
|
return result;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to append files to ${collectionName}:`, err);
|
// console.error(`Failed to append files to ${collectionName}:`, err);
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
this.auth.setUpdating(false);
|
this.auth.setUpdating(false);
|
||||||
|
@ -477,7 +494,7 @@ export class FileManager {
|
||||||
.update<T>(recordId, data);
|
.update<T>(recordId, data);
|
||||||
return result;
|
return result;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to delete file from ${collectionName}:`, err);
|
// console.error(`Failed to delete file from ${collectionName}:`, err);
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
this.auth.setUpdating(false);
|
this.auth.setUpdating(false);
|
||||||
|
@ -512,7 +529,7 @@ export class FileManager {
|
||||||
const result = await response.blob();
|
const result = await response.blob();
|
||||||
return result;
|
return result;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to download file from ${collectionName}:`, err);
|
// console.error(`Failed to download file from ${collectionName}:`, err);
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
this.auth.setUpdating(false);
|
this.auth.setUpdating(false);
|
||||||
|
@ -552,7 +569,7 @@ export class FileManager {
|
||||||
|
|
||||||
return fileUrls;
|
return fileUrls;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to get files from ${collectionName}:`, err);
|
// console.error(`Failed to get files from ${collectionName}:`, err);
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
this.auth.setUpdating(false);
|
this.auth.setUpdating(false);
|
||||||
|
@ -643,22 +660,22 @@ export class FileManager {
|
||||||
public async getFileToken(): Promise<string> {
|
public async getFileToken(): Promise<string> {
|
||||||
// Check authentication status
|
// Check authentication status
|
||||||
if (!this.auth.isAuthenticated()) {
|
if (!this.auth.isAuthenticated()) {
|
||||||
console.warn("User is not authenticated when trying to get file token");
|
// console.warn("User is not authenticated when trying to get file token");
|
||||||
|
|
||||||
// Try to refresh the auth if possible
|
// Try to refresh the auth if possible
|
||||||
try {
|
try {
|
||||||
const pb = this.auth.getPocketBase();
|
const pb = this.auth.getPocketBase();
|
||||||
if (pb.authStore.isValid) {
|
if (pb.authStore.isValid) {
|
||||||
console.log(
|
// console.log(
|
||||||
"Auth store is valid, but auth check failed. Trying to refresh token.",
|
// "Auth store is valid, but auth check failed. Trying to refresh token.",
|
||||||
);
|
// );
|
||||||
await pb.collection("users").authRefresh();
|
await pb.collection("users").authRefresh();
|
||||||
console.log("Auth refreshed successfully");
|
// console.log("Auth refreshed successfully");
|
||||||
} else {
|
} else {
|
||||||
throw new Error("User must be authenticated to get a file token");
|
throw new Error("User must be authenticated to get a file token");
|
||||||
}
|
}
|
||||||
} catch (refreshError) {
|
} catch (refreshError) {
|
||||||
console.error("Failed to refresh authentication:", refreshError);
|
// console.error("Failed to refresh authentication:", refreshError);
|
||||||
throw new Error("User must be authenticated to get a file token");
|
throw new Error("User must be authenticated to get a file token");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,19 +685,19 @@ export class FileManager {
|
||||||
const pb = this.auth.getPocketBase();
|
const pb = this.auth.getPocketBase();
|
||||||
|
|
||||||
// Log auth status
|
// Log auth status
|
||||||
console.log("Auth status before getting token:", {
|
// console.log("Auth status before getting token:", {
|
||||||
isValid: pb.authStore.isValid,
|
// isValid: pb.authStore.isValid,
|
||||||
token: pb.authStore.token
|
// token: pb.authStore.token
|
||||||
? pb.authStore.token.substring(0, 10) + "..."
|
// ? pb.authStore.token.substring(0, 10) + "..."
|
||||||
: "none",
|
// : "none",
|
||||||
model: pb.authStore.model ? pb.authStore.model.id : "none",
|
// model: pb.authStore.model ? pb.authStore.model.id : "none",
|
||||||
});
|
// });
|
||||||
|
|
||||||
const result = await pb.files.getToken();
|
const result = await pb.files.getToken();
|
||||||
console.log("Got file token:", result.substring(0, 10) + "...");
|
// console.log("Got file token:", result.substring(0, 10) + "...");
|
||||||
return result;
|
return result;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to get file token:", err);
|
// console.error("Failed to get file token:", err);
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
this.auth.setUpdating(false);
|
this.auth.setUpdating(false);
|
||||||
|
@ -705,25 +722,25 @@ export class FileManager {
|
||||||
|
|
||||||
// Check if filename is empty
|
// Check if filename is empty
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
console.error(
|
// console.error(
|
||||||
`Empty filename provided for ${collectionName}/${recordId}`,
|
// `Empty filename provided for ${collectionName}/${recordId}`,
|
||||||
);
|
// );
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user is authenticated
|
// Check if user is authenticated
|
||||||
if (!this.auth.isAuthenticated()) {
|
if (!this.auth.isAuthenticated()) {
|
||||||
console.warn("User is not authenticated when trying to get file URL");
|
// console.warn("User is not authenticated when trying to get file URL");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always try to use token for protected files
|
// Always try to use token for protected files
|
||||||
if (useToken) {
|
if (useToken) {
|
||||||
try {
|
try {
|
||||||
console.log(
|
// console.log(
|
||||||
`Getting file token for ${collectionName}/${recordId}/${filename}`,
|
// `Getting file token for ${collectionName}/${recordId}/${filename}`,
|
||||||
);
|
// );
|
||||||
const token = await this.getFileToken();
|
const token = await this.getFileToken();
|
||||||
console.log(`Got token: ${token.substring(0, 10)}...`);
|
// console.log(`Got token: ${token.substring(0, 10)}...`);
|
||||||
|
|
||||||
// Make sure to pass the token as a query parameter
|
// Make sure to pass the token as a query parameter
|
||||||
const url = pb.files.getURL(
|
const url = pb.files.getURL(
|
||||||
|
@ -731,16 +748,16 @@ export class FileManager {
|
||||||
filename,
|
filename,
|
||||||
{ token },
|
{ token },
|
||||||
);
|
);
|
||||||
console.log(`Generated URL with token: ${url.substring(0, 50)}...`);
|
// console.log(`Generated URL with token: ${url.substring(0, 50)}...`);
|
||||||
return url;
|
return url;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error getting file token:", error);
|
// console.error("Error getting file token:", error);
|
||||||
// Fall back to URL without token
|
// Fall back to URL without token
|
||||||
const url = pb.files.getURL(
|
const url = pb.files.getURL(
|
||||||
{ id: recordId, collectionId: collectionName },
|
{ id: recordId, collectionId: collectionName },
|
||||||
filename,
|
filename,
|
||||||
);
|
);
|
||||||
console.log(`Fallback URL without token: ${url.substring(0, 50)}...`);
|
// console.log(`Fallback URL without token: ${url.substring(0, 50)}...`);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -750,7 +767,7 @@ export class FileManager {
|
||||||
{ id: recordId, collectionId: collectionName },
|
{ id: recordId, collectionId: collectionName },
|
||||||
filename,
|
filename,
|
||||||
);
|
);
|
||||||
console.log(`Generated URL without token: ${url.substring(0, 50)}...`);
|
// console.log(`Generated URL without token: ${url.substring(0, 50)}...`);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue