no more console logs

This commit is contained in:
chark1es 2025-03-08 22:23:30 -08:00
parent 16d9ec9e1d
commit 27bc2f4e70
32 changed files with 3752 additions and 4000 deletions

View file

@ -1,18 +1,22 @@
<script>
const observer = new IntersectionObserver((entries) => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("in-view");
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 {
entry.target.classList.remove("in-view");
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 });
document.querySelectorAll("[data-inview]").forEach((el) => observer.observe(el));
</script>
},
{ threshold: 0.2 },
);
document
.querySelectorAll("[data-inview]")
.forEach((el) => observer.observe(el));
</script>

View file

@ -28,8 +28,7 @@ import EventLoad from "./EventsSection/EventLoad";
<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"
>
<span
class="text-base-content font-medium text-sm sm:text-base"
<span class="text-base-content font-medium text-sm sm:text-base"
>Coming Soon</span
>
</div>
@ -49,12 +48,8 @@ import EventLoad from "./EventsSection/EventLoad";
disabled
>
<option disabled selected>Pick an event</option>
<option
>Technical Workshop - Web Development</option
>
<option
>Professional Development Workshop</option
>
<option>Technical Workshop - Web Development</option>
<option>Professional Development Workshop</option>
<option>Social Event - Game Night</option>
</select>
<button
@ -94,9 +89,8 @@ import EventLoad from "./EventsSection/EventLoad";
class="btn btn-circle btn-ghost btn-sm sm:btn-md"
onclick="window.closeEventDetailsModal()"
>
<iconify-icon
icon="heroicons:x-mark"
className="h-4 w-4 sm:h-6 sm:w-6"></iconify-icon>
<iconify-icon icon="heroicons:x-mark" className="h-4 w-4 sm:h-6 sm:w-6"
></iconify-icon>
</button>
</div>
@ -130,8 +124,7 @@ import EventLoad from "./EventsSection/EventLoad";
id="previewLoadingSpinner"
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>
<span class="loading loading-spinner loading-md sm:loading-lg"></span>
</div>
<div id="previewContent" class="w-full">
<FilePreview client:load isModal={true} />
@ -191,14 +184,14 @@ import EventLoad from "./EventsSection/EventLoad";
// Universal file preview function for events section
window.previewFileEvents = function (url: string, filename: string) {
console.log("previewFileEvents called with:", { url, filename });
console.log("URL type:", typeof url, "URL length:", url?.length || 0);
console.log(
"Filename type:",
typeof filename,
"Filename length:",
filename?.length || 0
);
// console.log("previewFileEvents called with:", { url, filename });
// console.log("URL type:", typeof url, "URL length:", url?.length || 0);
// console.log(
// "Filename type:",
// typeof filename,
// "Filename length:",
// filename?.length || 0
// );
// Validate inputs
if (!url || typeof url !== "string") {
@ -210,7 +203,7 @@ import EventLoad from "./EventsSection/EventLoad";
if (!filename || typeof filename !== "string") {
console.error(
"Invalid filename provided to previewFileEvents:",
filename
filename,
);
toast.error("Cannot preview file: Invalid filename");
return;
@ -218,27 +211,24 @@ import EventLoad from "./EventsSection/EventLoad";
// Ensure URL is properly formatted
if (!url.startsWith("http")) {
console.warn(
"URL doesn't start with http, attempting to fix:",
url
);
console.warn("URL doesn't start with http, attempting to fix:", url);
if (url.startsWith("/")) {
url = `https://pocketbase.ieeeucsd.org${url}`;
} else {
url = `https://pocketbase.ieeeucsd.org/${url}`;
}
console.log("Fixed URL:", url);
// console.log("Fixed URL:", url);
}
const modal = document.getElementById(
"filePreviewModal"
"filePreviewModal",
) as HTMLDialogElement;
const previewFileName = document.getElementById("previewFileName");
const previewContent = document.getElementById("previewContent");
const loadingSpinner = document.getElementById("previewLoadingSpinner");
if (modal && previewFileName && previewContent) {
console.log("Found all required elements");
// console.log("Found all required elements");
// Show loading spinner
if (loadingSpinner) {
@ -254,11 +244,11 @@ import EventLoad from "./EventsSection/EventLoad";
// Test the URL with a fetch before dispatching the event
fetch(url, { method: "HEAD" })
.then((response) => {
console.log(
"URL test response:",
response.status,
response.ok
);
// console.log(
// "URL test response:",
// response.status,
// response.ok
// );
if (!response.ok) {
console.warn("URL might not be accessible:", url);
toast(
@ -270,7 +260,7 @@ import EventLoad from "./EventsSection/EventLoad";
background: "#FFC107",
color: "#000",
},
}
},
);
}
})
@ -279,14 +269,14 @@ import EventLoad from "./EventsSection/EventLoad";
})
.finally(() => {
// Dispatch state change event to update the FilePreview component
console.log(
"Dispatching filePreviewStateChange event with:",
{ url, filename }
);
// console.log(
// "Dispatching filePreviewStateChange event with:",
// { url, filename }
// );
window.dispatchEvent(
new CustomEvent("filePreviewStateChange", {
detail: { url, filename },
})
}),
);
});
@ -304,9 +294,9 @@ import EventLoad from "./EventsSection/EventLoad";
// Close file preview for events section
window.closeFilePreviewEvents = function () {
console.log("closeFilePreviewEvents called");
// console.log("closeFilePreviewEvents called");
const modal = document.getElementById(
"filePreviewModal"
"filePreviewModal",
) as HTMLDialogElement;
const previewFileName = document.getElementById("previewFileName");
const previewContent = document.getElementById("previewContent");
@ -317,14 +307,14 @@ import EventLoad from "./EventsSection/EventLoad";
}
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
// This ensures the FilePreview component clears its internal state
window.dispatchEvent(
new CustomEvent("filePreviewStateChange", {
detail: { url: "", filename: "" },
})
}),
);
// Reset the UI
@ -333,7 +323,7 @@ import EventLoad from "./EventsSection/EventLoad";
// Close the modal
modal.close();
console.log("File preview modal closed and state reset");
// console.log("File preview modal closed and state reset");
} else {
console.error("Could not find elements to close file preview");
}
@ -344,7 +334,7 @@ import EventLoad from "./EventsSection/EventLoad";
url: string;
name: string;
}) {
console.log("showFilePreviewEvents called with:", file);
// console.log("showFilePreviewEvents called with:", file);
if (!file || !file.url || !file.name) {
console.error("Invalid file data:", file);
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
window.openDetailsModal = function (event: any) {
const modal = document.getElementById(
"eventDetailsModal"
"eventDetailsModal",
) as HTMLDialogElement;
const filesContent = document.getElementById(
"filesContent"
"filesContent",
) as HTMLDivElement;
// Check if event has ended
@ -383,11 +373,7 @@ import EventLoad from "./EventsSection/EventLoad";
if (filesContent) filesContent.classList.remove("hidden");
// Populate files content
if (
event.files &&
Array.isArray(event.files) &&
event.files.length > 0
) {
if (event.files && Array.isArray(event.files) && event.files.length > 0) {
const baseUrl = "https://pocketbase.ieeeucsd.org";
const collectionId = "events";
const recordId = event.id;
@ -446,7 +432,7 @@ import EventLoad from "./EventsSection/EventLoad";
// Add downloadAllFiles function
window.downloadAllFiles = async function () {
const downloadBtn = document.getElementById(
"downloadAllBtn"
"downloadAllBtn",
) as HTMLButtonElement;
if (!downloadBtn) return;
const originalBtnContent = downloadBtn.innerHTML;
@ -501,7 +487,7 @@ import EventLoad from "./EventsSection/EventLoad";
} catch (error: any) {
console.error("Failed to download files:", error);
toast.error(
error?.message || "Failed to download files. Please try again."
error?.message || "Failed to download files. Please try again.",
);
} finally {
// Reset button state
@ -513,7 +499,7 @@ import EventLoad from "./EventsSection/EventLoad";
// Close event details modal
window.closeEventDetailsModal = function () {
const modal = document.getElementById(
"eventDetailsModal"
"eventDetailsModal",
) as HTMLDialogElement;
const filesContent = document.getElementById("filesContent");

View file

@ -249,8 +249,6 @@ const EventCheckIn = () => {
// Create the attendee record in PocketBase
const newAttendee = await update.create(Collections.EVENT_ATTENDEES, attendeeData);
console.log("Successfully created attendance record");
// Update user's total points
// First, get all the user's attendance records to calculate total points
const userAttendance = await get.getList<EventAttendee>(
@ -267,7 +265,7 @@ const EventCheckIn = () => {
});
// 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
await update.updateFields(Collections.USERS, userId, {

View file

@ -74,9 +74,9 @@ const EventLoad = () => {
// Clear events table
if (db && db.events) {
console.log("Clearing events cache...");
// console.log("Clearing events cache...");
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
@ -84,7 +84,7 @@ const EventLoad = () => {
const currentInfo = await dexieService.getLastSync(Collections.EVENTS);
// Then update it with a timestamp of 0 (forcing a fresh sync)
await dexieService.updateLastSync(Collections.EVENTS);
console.log("Events sync timestamp reset");
// console.log("Events sync timestamp reset");
// Reload events
setLoading(true);
@ -245,7 +245,7 @@ const EventLoad = () => {
const dataSync = DataSyncService.getInstance();
const auth = Authentication.getInstance();
console.log("Starting to load events...");
// console.log("Starting to load events...");
// Check if user is authenticated
if (!auth.isAuthenticated()) {
@ -255,7 +255,7 @@ const EventLoad = () => {
}
// Force sync to ensure we have the latest data
console.log("Syncing events collection...");
// console.log("Syncing events collection...");
let syncSuccess = false;
let retryCount = 0;
const maxRetries = 3;
@ -263,13 +263,13 @@ const EventLoad = () => {
while (!syncSuccess && retryCount < maxRetries) {
try {
if (retryCount > 0) {
console.log(`Retry attempt ${retryCount} of ${maxRetries}...`);
// console.log(`Retry attempt ${retryCount} of ${maxRetries}...`);
// Add a small delay between retries
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
}
await dataSync.syncCollection(Collections.EVENTS, "published = true", "-start_date");
console.log("Events collection synced successfully");
// console.log("Events collection synced successfully");
syncSuccess = true;
} catch (syncError) {
retryCount++;
@ -282,7 +282,7 @@ const EventLoad = () => {
}
// Get events from IndexedDB
console.log("Fetching events from IndexedDB...");
// console.log("Fetching events from IndexedDB...");
const allEvents = await dataSync.getData<Event>(
Collections.EVENTS,
false, // Don't force sync again
@ -290,27 +290,27 @@ const EventLoad = () => {
"-start_date"
);
console.log(`Retrieved ${allEvents.length} events from IndexedDB`);
// console.log(`Retrieved ${allEvents.length} events from IndexedDB`);
// Filter out invalid events
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
let eventsToProcess = validEvents;
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 {
const pbEvents = await get.getAll<Event>(
Collections.EVENTS,
"published = true",
"-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
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;
@ -319,7 +319,7 @@ const EventLoad = () => {
const dexieService = DexieService.getInstance();
const db = dexieService.getDB();
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);
}
}
@ -329,7 +329,7 @@ const EventLoad = () => {
}
// 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 { upcoming, ongoing, past } = eventsToProcess.reduce(
(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
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 {
console.log("Attempting to load events from IndexedDB only...");
// console.log("Attempting to load events from IndexedDB only...");
const dexieService = DexieService.getInstance();
const db = dexieService.getDB();
if (db && db.events) {
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
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) {
// Process these events
@ -458,7 +458,7 @@ const EventLoad = () => {
ongoing: ongoing.slice(0, 50),
past: past.slice(0, 50)
});
console.log("Successfully loaded events from cache");
// console.log("Successfully loaded events from cache");
}
}
} catch (cacheError) {

View file

@ -34,13 +34,7 @@ let upcomingEvents: Event[] = [];
// Fetch events
try {
if (auth.isAuthenticated()) {
eventResponse = await get.getList<Event>(
"events",
1,
5,
"",
"-start_date"
);
eventResponse = await get.getList<Event>("events", 1, 5, "", "-start_date");
upcomingEvents = eventResponse.items;
}
} 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"
>
<div class="stat p-4 md:p-6">
<div
class="stat-title text-sm md:text-base font-medium opacity-80"
>
<div class="stat-title text-sm md:text-base font-medium opacity-80">
Total Events
</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"
>
<div class="stat p-4 md:p-6">
<div
class="stat-title text-sm md:text-base font-medium opacity-80"
>
<div class="stat-title text-sm md:text-base font-medium opacity-80">
Unique Attendees
</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"
>
<div class="stat p-4 md:p-6">
<div
class="stat-title text-sm md:text-base font-medium opacity-80"
>
<div class="stat-title text-sm md:text-base font-medium opacity-80">
Recurring Attendees
</div>
<div
@ -155,20 +143,14 @@ const currentPage = eventResponse.page;
class="btn btn-ghost btn-sm md:btn-md gap-2"
onclick="window.refreshEvents()"
>
<Icon
name="heroicons:arrow-path"
class="h-4 w-4 md:h-5 md:w-5"
/>
<Icon name="heroicons:arrow-path" class="h-4 w-4 md:h-5 md:w-5" />
Refresh
</button>
<button
class="btn btn-primary btn-sm md:btn-md gap-2"
onclick="window.openEditModal()"
>
<Icon
name="heroicons:plus"
class="h-4 w-4 md:h-5 md:w-5"
/>
<Icon name="heroicons:plus" class="h-4 w-4 md:h-5 md:w-5" />
Add New Event
</button>
</div>
@ -182,8 +164,7 @@ const currentPage = eventResponse.page;
<div class="flex flex-wrap gap-4">
<div class="form-control w-full sm:w-auto">
<label class="label">
<span
class="label-text text-sm md:text-base font-medium"
<span class="label-text text-sm md:text-base font-medium"
>Time Filter</span
>
</label>
@ -223,8 +204,7 @@ const currentPage = eventResponse.page;
<!-- Other filters with similar responsive adjustments -->
<div class="form-control w-full sm:w-auto">
<label class="label">
<span
class="label-text text-sm md:text-base font-medium"
<span class="label-text text-sm md:text-base font-medium"
>Year</span
>
</label>
@ -254,8 +234,7 @@ const currentPage = eventResponse.page;
>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">All Years</span
>
<span class="label-text">All Years</span>
<input
type="checkbox"
class="checkbox"
@ -273,8 +252,7 @@ const currentPage = eventResponse.page;
<div class="form-control w-full sm:w-auto">
<label class="label">
<span
class="label-text text-sm md:text-base font-medium"
<span class="label-text text-sm md:text-base font-medium"
>Quarter</span
>
</label>
@ -284,9 +262,7 @@ const currentPage = eventResponse.page;
class="btn btn-sm m-1 w-[180px] justify-between items-center"
>
<div class="flex-1 text-left truncate">
<span id="quarterFilterLabel"
>All Quarters</span
>
<span id="quarterFilterLabel">All Quarters</span>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -307,9 +283,7 @@ const currentPage = eventResponse.page;
>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text"
>All Quarters</span
>
<span class="label-text">All Quarters</span>
<input
type="checkbox"
class="checkbox"
@ -321,41 +295,25 @@ const currentPage = eventResponse.page;
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Fall</span>
<input
type="checkbox"
class="checkbox"
value="fall"
/>
<input type="checkbox" class="checkbox" value="fall" />
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Winter</span>
<input
type="checkbox"
class="checkbox"
value="winter"
/>
<input type="checkbox" class="checkbox" value="winter" />
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Spring</span>
<input
type="checkbox"
class="checkbox"
value="spring"
/>
<input type="checkbox" class="checkbox" value="spring" />
</label>
</div>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Summer</span>
<input
type="checkbox"
class="checkbox"
value="summer"
/>
<input type="checkbox" class="checkbox" value="summer" />
</label>
</div>
</div>
@ -364,8 +322,7 @@ const currentPage = eventResponse.page;
<div class="form-control w-full sm:w-auto">
<label class="label">
<span
class="label-text text-sm md:text-base font-medium"
<span class="label-text text-sm md:text-base font-medium"
>Published</span
>
</label>
@ -431,8 +388,7 @@ const currentPage = eventResponse.page;
<div class="form-control w-full sm:w-auto">
<label class="label">
<span
class="label-text text-sm md:text-base font-medium"
<span class="label-text text-sm md:text-base font-medium"
>Has Files</span
>
</label>
@ -498,8 +454,7 @@ const currentPage = eventResponse.page;
<div class="form-control w-full sm:w-auto">
<label class="label">
<span
class="label-text text-sm md:text-base font-medium"
<span class="label-text text-sm md:text-base font-medium"
>Has Food</span
>
</label>
@ -569,9 +524,7 @@ const currentPage = eventResponse.page;
<div class="flex flex-col sm:flex-row gap-4 mb-4">
<div class="form-control flex-1">
<div class="join w-full">
<div
class="join-item bg-base-200 flex items-center px-3"
>
<div class="join-item bg-base-200 flex items-center px-3">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-4 w-4 md:h-5 md:w-5 opacity-70"
@ -618,29 +571,22 @@ const currentPage = eventResponse.page;
</div>
<!-- Pagination -->
<div
class="flex justify-center mt-4 md:mt-6"
id="paginationContainer"
>
<div class="flex justify-center mt-4 md:mt-6" id="paginationContainer">
<div class="join">
<button
class="join-item btn btn-xs md:btn-sm"
id="firstPageBtn">«</button
<button class="join-item btn btn-xs md:btn-sm" id="firstPageBtn"
>«</button
>
<button
class="join-item btn btn-xs md:btn-sm"
id="prevPageBtn"></button
<button class="join-item btn btn-xs md:btn-sm" id="prevPageBtn"
></button
>
<button class="join-item btn btn-xs md:btn-sm"
>Page <span id="currentPageNumber">1</span></button
>
<button
class="join-item btn btn-xs md:btn-sm"
id="nextPageBtn"></button
<button class="join-item btn btn-xs md:btn-sm" id="nextPageBtn"
></button
>
<button
class="join-item btn btn-xs md:btn-sm"
id="lastPageBtn">»</button
<button class="join-item btn btn-xs md:btn-sm" id="lastPageBtn"
>»</button
>
</div>
</div>
@ -735,10 +681,7 @@ const currentPage = eventResponse.page;
<div class="modal-box max-w-4xl">
<div class="flex justify-between items-center mb-4">
<h3 class="font-bold text-lg" id="attendeesModalTitle"></h3>
<button
class="btn btn-circle btn-ghost"
onclick="attendeesModal.close()"
>
<button class="btn btn-circle btn-ghost" onclick="attendeesModal.close()">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
@ -840,9 +783,7 @@ const currentPage = eventResponse.page;
) {
auth.setUpdating(true);
const response = await get.getAll<Event>("events");
cachedEvents = response.map((event) =>
Get.convertUTCToLocal(event)
);
cachedEvents = response.map((event) => Get.convertUTCToLocal(event));
lastCacheUpdate = now;
// Initialize year filter options from cache
@ -852,8 +793,7 @@ const currentPage = eventResponse.page;
years.add(year);
});
const yearCheckboxes =
document.getElementById("yearCheckboxes");
const yearCheckboxes = document.getElementById("yearCheckboxes");
if (yearCheckboxes) {
const sortedYears = Array.from(years).sort((a, b) => b - a);
yearCheckboxes.innerHTML = sortedYears
@ -863,18 +803,16 @@ const currentPage = eventResponse.page;
<span class="label-text">${year}</span>
<input type="checkbox" class="checkbox" value="${year}" />
</label>
`
`,
)
.join("");
// Add event listeners to checkboxes
const allYearsCheckbox = document.querySelector(
'input[type="checkbox"][value="all"]'
'input[type="checkbox"][value="all"]',
) as HTMLInputElement;
const yearInputs = Array.from(
yearCheckboxes.querySelectorAll(
'input[type="checkbox"]'
)
yearCheckboxes.querySelectorAll('input[type="checkbox"]'),
) as HTMLInputElement[];
if (allYearsCheckbox) {
@ -885,9 +823,8 @@ const currentPage = eventResponse.page;
input.checked = false;
});
filterState.year = ["all"];
document.getElementById(
"yearFilterLabel"
)!.textContent = "All Years";
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
}
currentPage = 1;
fetchEvents();
@ -903,15 +840,12 @@ const currentPage = eventResponse.page;
if (checkedYears.length === 0) {
allYearsCheckbox.checked = true;
filterState.year = ["all"];
document.getElementById(
"yearFilterLabel"
)!.textContent = "All Years";
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
} else {
allYearsCheckbox.checked = false;
filterState.year = checkedYears;
document.getElementById(
"yearFilterLabel"
)!.textContent =
document.getElementById("yearFilterLabel")!.textContent =
checkedYears.length === 1
? checkedYears[0]
: `${checkedYears.length} Years Selected`;
@ -1010,8 +944,7 @@ const currentPage = eventResponse.page;
const eventEnd = new Date(event.end_date).toISOString();
// Time filter
if (filterState.time === "upcoming" && eventStart <= now)
return false;
if (filterState.time === "upcoming" && eventStart <= now) return false;
if (filterState.time === "past" && eventEnd >= now) return false;
if (
filterState.time === "ongoing" &&
@ -1028,7 +961,7 @@ const currentPage = eventResponse.page;
// Check if either the start year or end year matches any selected year
const yearMatches = filterState.year.some(
(year) => year === eventStartYear || year === eventEndYear
(year) => year === eventStartYear || year === eventEndYear,
);
if (!yearMatches) return false;
}
@ -1065,8 +998,7 @@ const currentPage = eventResponse.page;
// Published filter
if (filterState.published !== "all") {
if ((filterState.published === "yes") !== event.published)
return false;
if ((filterState.published === "yes") !== event.published) return false;
}
// Has Files filter
@ -1077,8 +1009,7 @@ const currentPage = eventResponse.page;
// Has Food filter
if (filterState.hasFood !== "all") {
if ((filterState.hasFood === "yes") !== event.has_food)
return false;
if ((filterState.hasFood === "yes") !== event.has_food) return false;
}
// Search query
@ -1093,7 +1024,7 @@ const currentPage = eventResponse.page;
event.event_name.toLowerCase().includes(term) ||
event.event_code.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
async function fetchEvents() {
const eventsList = document.getElementById("eventsList");
const paginationContainer = document.getElementById(
"paginationContainer"
);
const paginationContainer = document.getElementById("paginationContainer");
if (!eventsList || !paginationContainer) return;
try {
@ -1133,8 +1062,7 @@ const currentPage = eventResponse.page;
// Sort events by start date (newest first)
filteredEvents.sort(
(a, b) =>
new Date(b.start_date).getTime() -
new Date(a.start_date).getTime()
new Date(b.start_date).getTime() - new Date(a.start_date).getTime(),
);
// Calculate pagination
@ -1146,19 +1074,18 @@ const currentPage = eventResponse.page;
// Update pagination UI
const firstPageBtn = document.getElementById(
"firstPageBtn"
"firstPageBtn",
) as HTMLButtonElement;
const prevPageBtn = document.getElementById(
"prevPageBtn"
"prevPageBtn",
) as HTMLButtonElement;
const nextPageBtn = document.getElementById(
"nextPageBtn"
"nextPageBtn",
) as HTMLButtonElement;
const lastPageBtn = document.getElementById(
"lastPageBtn"
"lastPageBtn",
) as HTMLButtonElement;
const currentPageNumber =
document.getElementById("currentPageNumber");
const currentPageNumber = document.getElementById("currentPageNumber");
if (firstPageBtn) firstPageBtn.disabled = currentPage <= 1;
if (prevPageBtn) prevPageBtn.disabled = currentPage <= 1;
@ -1206,12 +1133,8 @@ const currentPage = eventResponse.page;
console.error("Error formatting date:", e);
}
const locationStr = event.location
? `${event.location}`
: "";
const codeStr = event.event_code
? `${event.event_code}`
: "";
const locationStr = event.location ? `${event.location}` : "";
const codeStr = event.event_code ? `${event.event_code}` : "";
const detailsStr = [locationStr, codeStr]
.filter(Boolean)
.join(" | code: ");
@ -1276,8 +1199,7 @@ const currentPage = eventResponse.page;
async function calculateQuarterlyStats() {
try {
const { start: termStart, end: termEnd } = getCurrentTerm();
const { start: quarterStart, end: quarterEnd } =
getCurrentQuarter();
const { start: quarterStart, end: quarterEnd } = getCurrentQuarter();
// Update quarter name in UI
const quarterNameEl = document.getElementById("quarterName");
@ -1318,19 +1240,17 @@ const currentPage = eventResponse.page;
});
quarterlyStats.recurringAttendees = Array.from(
quarterAttendees.values()
quarterAttendees.values(),
).filter((count) => count > 1).length;
// Update the UI
const totalEventsEl = document.getElementById("totalEvents");
const uniqueAttendeesEl =
document.getElementById("uniqueAttendees");
const uniqueAttendeesEl = document.getElementById("uniqueAttendees");
const recurringAttendeesEl =
document.getElementById("recurringAttendees");
if (totalEventsEl)
totalEventsEl.textContent =
quarterlyStats.totalEvents.toString();
totalEventsEl.textContent = quarterlyStats.totalEvents.toString();
if (uniqueAttendeesEl)
uniqueAttendeesEl.textContent =
quarterlyStats.uniqueAttendees.toString();
@ -1383,24 +1303,20 @@ const currentPage = eventResponse.page;
});
// Year filter
document
.getElementById("yearCheckboxes")
?.addEventListener("change", (e) => {
document.getElementById("yearCheckboxes")?.addEventListener("change", (e) => {
const target = e.target as HTMLInputElement;
if (!target.matches('input[type="checkbox"]')) return;
const allYearsCheckbox = target
.closest(".dropdown-content")
?.querySelector(
'input[type="checkbox"][value="all"]'
'input[type="checkbox"][value="all"]',
) as HTMLInputElement;
const yearInputs = Array.from(
target
.closest(".dropdown-content")
?.querySelectorAll(
'#yearCheckboxes input[type="checkbox"]'
) || []
?.querySelectorAll('#yearCheckboxes input[type="checkbox"]') || [],
) as HTMLInputElement[];
if (target.value === "all" && target.checked) {
@ -1408,8 +1324,7 @@ const currentPage = eventResponse.page;
input.checked = false;
});
filterState.year = ["all"];
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
document.getElementById("yearFilterLabel")!.textContent = "All Years";
} else {
const checkedYears = yearInputs
.filter((inp) => inp.checked)
@ -1418,8 +1333,7 @@ const currentPage = eventResponse.page;
if (checkedYears.length === 0) {
allYearsCheckbox.checked = true;
filterState.year = ["all"];
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
document.getElementById("yearFilterLabel")!.textContent = "All Years";
} else {
allYearsCheckbox.checked = false;
filterState.year = checkedYears;
@ -1439,9 +1353,7 @@ const currentPage = eventResponse.page;
?.addEventListener("change", (e) => {
const target = e.target as HTMLInputElement;
const yearInputs = Array.from(
document.querySelectorAll(
'#yearCheckboxes input[type="checkbox"]'
)
document.querySelectorAll('#yearCheckboxes input[type="checkbox"]'),
) as HTMLInputElement[];
if (target.checked) {
@ -1449,8 +1361,7 @@ const currentPage = eventResponse.page;
input.checked = false;
});
filterState.year = ["all"];
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
document.getElementById("yearFilterLabel")!.textContent = "All Years";
currentPage = 1;
fetchEvents();
}
@ -1466,15 +1377,15 @@ const currentPage = eventResponse.page;
const allQuartersCheckbox = target
.closest("#quarterDropdownContent")
?.querySelector(
'input[type="checkbox"][value="all"]'
'input[type="checkbox"][value="all"]',
) as HTMLInputElement;
const quarterInputs = Array.from(
target
.closest("#quarterDropdownContent")
?.querySelectorAll('input[type="checkbox"]') || []
?.querySelectorAll('input[type="checkbox"]') || [],
).filter(
(inp) => (inp as HTMLInputElement).value !== "all"
(inp) => (inp as HTMLInputElement).value !== "all",
) as HTMLInputElement[];
if (target.value === "all" && target.checked) {
@ -1516,8 +1427,8 @@ const currentPage = eventResponse.page;
const target = e.target as HTMLInputElement;
filterState.published = target.value;
document.getElementById("publishedFilterLabel")!.textContent =
target.parentElement?.querySelector(".label-text")
?.textContent || "All";
target.parentElement?.querySelector(".label-text")?.textContent ||
"All";
currentPage = 1;
fetchEvents();
});
@ -1531,8 +1442,8 @@ const currentPage = eventResponse.page;
const target = e.target as HTMLInputElement;
filterState.hasFiles = target.value;
document.getElementById("hasFilesFilterLabel")!.textContent =
target.parentElement?.querySelector(".label-text")
?.textContent || "All";
target.parentElement?.querySelector(".label-text")?.textContent ||
"All";
currentPage = 1;
fetchEvents();
});
@ -1546,8 +1457,8 @@ const currentPage = eventResponse.page;
const target = e.target as HTMLInputElement;
filterState.hasFood = target.value;
document.getElementById("hasFoodFilterLabel")!.textContent =
target.parentElement?.querySelector(".label-text")
?.textContent || "All";
target.parentElement?.querySelector(".label-text")?.textContent ||
"All";
currentPage = 1;
fetchEvents();
});
@ -1576,9 +1487,7 @@ const currentPage = eventResponse.page;
}
// Per page select
document
.getElementById("perPageSelect")
?.addEventListener("change", (e) => {
document.getElementById("perPageSelect")?.addEventListener("change", (e) => {
const target = e.target as HTMLSelectElement;
perPage = parseInt(target.value);
currentPage = 1;
@ -1590,7 +1499,7 @@ const currentPage = eventResponse.page;
window.addEventListener("DOMContentLoaded", () => {
// Reset all filters to defaults
const timeFilterAll = document.querySelector(
'input[name="timeFilter"][value="all"]'
'input[name="timeFilter"][value="all"]',
) as HTMLInputElement;
if (timeFilterAll) {
// Ensure the radio button is properly checked
@ -1600,10 +1509,10 @@ const currentPage = eventResponse.page;
// Reset year filter
const yearAllCheckbox = document.querySelector(
'input[type="checkbox"][value="all"]'
'input[type="checkbox"][value="all"]',
) as HTMLInputElement;
const yearCheckboxes = document.querySelectorAll(
'#yearCheckboxes input[type="checkbox"]'
'#yearCheckboxes input[type="checkbox"]',
);
if (yearAllCheckbox && yearCheckboxes) {
yearAllCheckbox.checked = true;
@ -1611,16 +1520,15 @@ const currentPage = eventResponse.page;
(checkbox as HTMLInputElement).checked = false;
});
filterState.year = ["all"];
document.getElementById("yearFilterLabel")!.textContent =
"All Years";
document.getElementById("yearFilterLabel")!.textContent = "All Years";
}
// Reset quarter filter
const quarterAllCheckbox = document.querySelector(
'#quarterDropdownContent input[type="checkbox"][value="all"]'
'#quarterDropdownContent input[type="checkbox"][value="all"]',
) as HTMLInputElement;
const quarterCheckboxes = document.querySelectorAll(
'#quarterDropdownContent input[type="checkbox"]:not([value="all"])'
'#quarterDropdownContent input[type="checkbox"]:not([value="all"])',
);
if (quarterAllCheckbox && quarterCheckboxes) {
quarterAllCheckbox.checked = true;
@ -1633,27 +1541,27 @@ const currentPage = eventResponse.page;
}
const publishedFilter = document.getElementById(
"publishedFilter"
"publishedFilter",
) as HTMLSelectElement;
if (publishedFilter) publishedFilter.value = "all";
const hasFilesFilter = document.getElementById(
"hasFilesFilter"
"hasFilesFilter",
) as HTMLSelectElement;
if (hasFilesFilter) hasFilesFilter.value = "all";
const hasFoodFilter = document.getElementById(
"hasFoodFilter"
"hasFoodFilter",
) as HTMLSelectElement;
if (hasFoodFilter) hasFoodFilter.value = "all";
const searchInput = document.getElementById(
"searchInput"
"searchInput",
) as HTMLInputElement;
if (searchInput) searchInput.value = "";
const perPageSelect = document.getElementById(
"perPageSelect"
"perPageSelect",
) as HTMLSelectElement;
if (perPageSelect) perPageSelect.value = "5";
@ -1683,12 +1591,10 @@ const currentPage = eventResponse.page;
// Update the previewFileInEditModal function
window.previewFileInEditModal = async function (
url: string,
filename: string
filename: string,
) {
const editFormSection = document.getElementById("editFormSection");
const previewSection = document.getElementById(
"editModalPreviewSection"
);
const previewSection = document.getElementById("editModalPreviewSection");
const editFilePreview = document.getElementById("editFilePreview");
const previewFileName = document.getElementById("editPreviewFileName");
const loadingSpinner = document.getElementById("editLoadingSpinner");
@ -1724,16 +1630,14 @@ const currentPage = eventResponse.page;
// Update the showFilePreview function
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);
};
// Add backToEditForm function
window.backToEditForm = function () {
const editFormSection = document.getElementById("editFormSection");
const previewSection = document.getElementById(
"editModalPreviewSection"
);
const previewSection = document.getElementById("editModalPreviewSection");
const editFilePreview = document.getElementById("editFilePreview");
const previewFileName = document.getElementById("editPreviewFileName");
@ -1756,17 +1660,15 @@ const currentPage = eventResponse.page;
// Universal file preview function
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(
"filePreviewModal"
"filePreviewModal",
) as HTMLDialogElement;
const filePreview = document.getElementById(
"officerFilePreview"
) as any;
const filePreview = document.getElementById("officerFilePreview") as any;
const previewFileName = document.getElementById("previewFileName");
if (filePreview && modal && previewFileName) {
console.log("Found all required elements");
// console.log("Found all required elements");
// Update the filename display
previewFileName.textContent = filename;
@ -1774,7 +1676,7 @@ const currentPage = eventResponse.page;
modal.showModal();
// Update the preview component
console.log("Dispatching updateFilePreview event");
// console.log("Dispatching updateFilePreview event");
const event = new CustomEvent("updateFilePreview", {
detail: { url, filename },
});
@ -1790,17 +1692,15 @@ const currentPage = eventResponse.page;
// Close file preview
window.closeFilePreview = function () {
console.log("closeFilePreview called");
// console.log("closeFilePreview called");
const modal = document.getElementById(
"filePreviewModal"
"filePreviewModal",
) as HTMLDialogElement;
const filePreview = document.getElementById(
"officerFilePreview"
) as any;
const filePreview = document.getElementById("officerFilePreview") as any;
const previewFileName = document.getElementById("previewFileName");
if (modal && filePreview && previewFileName) {
console.log("Resetting preview and closing modal");
// console.log("Resetting preview and closing modal");
// Reset the preview
const event = new CustomEvent("updateFilePreview", {
detail: { url: "", filename: "" },
@ -1814,7 +1714,7 @@ const currentPage = eventResponse.page;
// Close event details modal
window.closeEventDetailsModal = function () {
const modal = document.getElementById(
"eventDetailsModal"
"eventDetailsModal",
) as HTMLDialogElement;
const filesContent = document.getElementById("filesContent");
const attendeesContent = document.getElementById("attendeesContent");
@ -1835,11 +1735,7 @@ const currentPage = eventResponse.page;
function updateFilePreviewButtons(files: string[], eventId: string) {
return files
.map((filename) => {
const fileUrl = fileManager.getFileUrl(
"events",
eventId,
filename
);
const fileUrl = fileManager.getFileUrl("events", eventId, filename);
const previewData = JSON.stringify({
url: fileUrl,
name: filename,
@ -1884,12 +1780,10 @@ const currentPage = eventResponse.page;
if (newFiles && fileInput.files) {
// Get existing files if any
const existingFiles = newFiles.querySelectorAll(".file-item");
const existingFilesArray = Array.from(existingFiles).map(
(item) => {
const existingFilesArray = Array.from(existingFiles).map((item) => {
const nameSpan = item.querySelector(".file-name");
return nameSpan ? nameSpan.textContent : "";
}
);
});
// Store new files in the storage and update UI
Array.from(fileInput.files)
@ -1936,12 +1830,11 @@ const currentPage = eventResponse.page;
const currentFiles = document.getElementById("currentFiles");
if (currentFiles) {
const fileElement = currentFiles.querySelector(
`[data-filename="${filename}"]`
`[data-filename="${filename}"]`,
);
if (fileElement) {
fileElement.classList.add("opacity-50");
const deleteButton =
fileElement.querySelector(".text-error");
const deleteButton = fileElement.querySelector(".text-error");
if (deleteButton) {
deleteButton.innerHTML = `
<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.`,
{
icon: "🗑️",
}
},
);
} catch (error) {
console.error("Failed to stage file deletion:", error);
@ -1973,7 +1866,7 @@ const currentPage = eventResponse.page;
const currentFiles = document.getElementById("currentFiles");
if (currentFiles) {
const fileElement = currentFiles.querySelector(
`[data-filename="${filename}"]`
`[data-filename="${filename}"]`,
);
if (fileElement) {
fileElement.classList.remove("opacity-50");
@ -2002,7 +1895,7 @@ const currentPage = eventResponse.page;
// Universal file preview function for officer section
window.previewFileOfficer = function (url: string, filename: string) {
const modal = document.getElementById(
"filePreviewModal"
"filePreviewModal",
) as HTMLDialogElement;
if (!modal) {
@ -2014,7 +1907,7 @@ const currentPage = eventResponse.page;
window.dispatchEvent(
new CustomEvent(FILE_PREVIEW_STATE_CHANGE, {
detail: { url, filename },
})
}),
);
// Show modal after event dispatch
@ -2026,7 +1919,7 @@ const currentPage = eventResponse.page;
// Close file preview for officer section
window.closeFilePreviewOfficer = function () {
const modal = document.getElementById(
"filePreviewModal"
"filePreviewModal",
) as HTMLDialogElement;
const previewContent = document.getElementById("previewContent");
@ -2049,7 +1942,7 @@ const currentPage = eventResponse.page;
window.dispatchEvent(
new CustomEvent(FILE_PREVIEW_STATE_CHANGE, {
detail: { url: "", filename: "" },
})
}),
);
// Close modal after cleanup
@ -2083,18 +1976,14 @@ const currentPage = eventResponse.page;
}
// Get fresh URL from FileManager to ensure we have the latest
const freshUrl = fileManager.getFileUrl(
"events",
eventId,
file.name
);
const freshUrl = fileManager.getFileUrl("events", eventId, file.name);
// Show the preview with fresh URL
window.previewFileOfficer(freshUrl, file.name);
} catch (error) {
console.error("Failed to fetch fresh file data:", 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
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(
"attendeesModal"
"attendeesModal",
) as HTMLDialogElement;
const modalTitle = document.getElementById("attendeesModalTitle");
@ -2126,7 +2015,7 @@ const currentPage = eventResponse.page;
eventId: event.id,
eventName: event.event_name,
},
})
}),
);
// Show modal
@ -2136,7 +2025,7 @@ const currentPage = eventResponse.page;
// Add event listeners when the document loads
document.addEventListener("DOMContentLoaded", () => {
const modal = document.getElementById(
"filePreviewModal"
"filePreviewModal",
) as HTMLDialogElement;
if (modal) {
// Handle modal close via backdrop

View file

@ -287,7 +287,7 @@ export default function Attendees() {
const fetchEventData = async () => {
if (!eventId || !auth.isAuthenticated()) {
if (!auth.isAuthenticated()) {
console.log('User not authenticated');
// console.log('User not authenticated');
setError('Authentication required');
}
return;

View file

@ -631,7 +631,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) {
has_food: eventData.has_food || false
});
console.log("Event data loaded successfully:", eventData);
// console.log("Event data loaded successfully:", eventData);
} else {
setEvent({
id: '',
@ -784,7 +784,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) {
// 1. Remove files marked for deletion
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));
// 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
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
const newFiles = Array.from(selectedFiles.values());
@ -849,7 +849,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) {
// Then upload files if any
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
const newFiles = Array.from(selectedFiles.values());

View file

@ -31,7 +31,7 @@ if (auth.isAuthenticated()) {
userEventRequests = await get.getAll<EventRequest>(
Collections.EVENT_REQUESTS,
`requested_user="${userId}"`,
"-created"
"-created",
);
}
} catch (err) {
@ -46,8 +46,8 @@ if (auth.isAuthenticated()) {
<h1 class="text-3xl font-bold text-white mb-2">Event Request Form</h1>
<p class="text-gray-300 mb-4">
Submit your event request at least 6 weeks before your event. After
submitting, please notify PR and/or Coordinators in the #-events
Slack channel.
submitting, please notify PR and/or Coordinators in the #-events Slack
channel.
</p>
<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>
@ -109,10 +109,7 @@ if (auth.isAuthenticated()) {
{
!error && (
<UserEventRequests
client:load
eventRequests={userEventRequests}
/>
<UserEventRequests client:load eventRequests={userEventRequests} />
)
}
</div>
@ -171,10 +168,10 @@ if (auth.isAuthenticated()) {
<script is:inline>
// Define the global function immediately to ensure it's available
window.showEventRequestFormPreview = function (formData) {
console.log(
"Global showEventRequestFormPreview called with data",
formData
);
// console.log(
// "Global showEventRequestFormPreview called with data",
// formData
// );
// Remove any elements that might be obstructing the view
const removeObstructions = () => {
@ -204,12 +201,12 @@ if (auth.isAuthenticated()) {
// Dispatch event to show modal
document.dispatchEvent(event);
console.log("showEventRequestPreviewModal event dispatched");
// console.log("showEventRequestPreviewModal event dispatched");
// Ensure modal container is visible
setTimeout(() => {
const modalContainer = document.getElementById(
"event-request-preview-modal-container"
"event-request-preview-modal-container",
);
if (modalContainer) {
modalContainer.style.zIndex = "99999";
@ -226,8 +223,7 @@ if (auth.isAuthenticated()) {
document.body.style.overflow = "auto";
// Ensure the modal content is properly sized
const modalContent =
modalContainer.querySelector("div > div > div");
const modalContent = modalContainer.querySelector("div > div > div");
if (modalContent) {
modalContent.style.maxWidth = "90vw";
modalContent.style.width = "100%";
@ -261,30 +257,26 @@ if (auth.isAuthenticated()) {
await dataSync.syncCollection(
Collections.EVENT_REQUESTS,
`requested_user="${userId}"`,
"-created"
);
console.log(
"Initial data sync complete for user event requests"
"-created",
);
// console.log("Initial data sync complete for user event requests");
}
} 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 submissionsTab = document.getElementById("submissions-tab");
const formContent = document.getElementById("form-content");
const submissionsContent = document.getElementById(
"submissions-content"
);
const submissionsContent = document.getElementById("submissions-content");
// Function to switch tabs
const switchTab = (
activeTab: HTMLElement,
activeContent: HTMLElement,
inactiveTab: HTMLElement,
inactiveContent: HTMLElement
inactiveContent: HTMLElement,
) => {
// Update tab classes
activeTab.classList.add("tab-active");
@ -305,24 +297,14 @@ if (auth.isAuthenticated()) {
formTab?.addEventListener("click", (e) => {
e.preventDefault();
if (formContent && submissionsContent && submissionsTab) {
switchTab(
formTab,
formContent,
submissionsTab,
submissionsContent
);
switchTab(formTab, formContent, submissionsTab, submissionsContent);
}
});
submissionsTab?.addEventListener("click", (e) => {
e.preventDefault();
if (formContent && submissionsContent && formTab) {
switchTab(
submissionsTab,
submissionsContent,
formTab,
formContent
);
switchTab(submissionsTab, submissionsContent, formTab, formContent);
}
});

View file

@ -12,7 +12,7 @@ export const EventRequestFormPreviewModal: React.FC = () => {
// Function to handle showing the modal
const showModal = (data: any) => {
console.log('showModal called with data', data);
// console.log('showModal called with data', data);
setFormData(data);
setIsOpen(true);
};
@ -24,23 +24,23 @@ export const EventRequestFormPreviewModal: React.FC = () => {
// Define the global function
window.showEventRequestFormPreview = (data: any) => {
console.log('Global showEventRequestFormPreview called with data', data);
// console.log('Global showEventRequestFormPreview called with data', data);
showModal(data);
};
// Listen for the custom event as a fallback
const handleShowModal = (event: CustomEvent) => {
console.log('Received showEventRequestPreviewModal event', event.detail);
// console.log('Received showEventRequestPreviewModal event', event.detail);
if (event.detail && event.detail.formData) {
showModal(event.detail.formData);
} else {
console.error('Event detail or formData is missing', event.detail);
// console.error('Event detail or formData is missing', event.detail);
}
};
// Add event listener
document.addEventListener('showEventRequestPreviewModal', handleShowModal as EventListener);
console.log('Event listener for showEventRequestPreviewModal added');
// console.log('Event listener for showEventRequestPreviewModal added');
// Clean up
return () => {
@ -53,12 +53,12 @@ export const EventRequestFormPreviewModal: React.FC = () => {
}
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
const handleClose = () => {
console.log('Modal closed');
// console.log('Modal closed');
setIsOpen(false);
};
@ -122,7 +122,7 @@ const EventRequestFormPreview: React.FC<EventRequestFormPreviewProps> = ({
const parsedData = JSON.parse(savedData);
setFormData(parsedData);
} catch (e) {
console.error('Error parsing saved form data:', e);
// console.error('Error parsing saved form data:', e);
}
}
setLoading(false);

View file

@ -69,7 +69,7 @@ const UserEventRequests: React.FC<UserEventRequestsProps> = ({ eventRequests: in
// Listen for tab visibility changes and refresh data when tab becomes visible
useEffect(() => {
const handleTabVisible = () => {
console.log("Tab became visible, refreshing event requests...");
// console.log("Tab became visible, refreshing event requests...");
refreshEventRequests();
};
@ -411,19 +411,19 @@ const UserEventRequests: React.FC<UserEventRequestsProps> = ({ eventRequests: in
className="btn btn-sm btn-primary"
onClick={(e) => {
e.stopPropagation();
console.log('Full Preview button clicked', selectedRequest);
// console.log('Full Preview button clicked', selectedRequest);
try {
// Direct call to the global function
if (typeof window.showEventRequestFormPreview === 'function') {
window.showEventRequestFormPreview(selectedRequest);
} 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
const event = new CustomEvent("showEventRequestPreviewModal", {
detail: { formData: selectedRequest }
});
document.dispatchEvent(event);
console.log('Fallback: showEventRequestPreviewModal event dispatched');
// console.log('Fallback: showEventRequestPreviewModal event dispatched');
}
} catch (error) {
console.error('Error showing full preview:', error);

View file

@ -37,7 +37,7 @@ try {
// 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
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
allEventRequests = await get
.getAll<ExtendedEventRequest>(Collections.EVENT_REQUESTS, "", "-created", {
@ -49,9 +49,9 @@ try {
return [];
});
console.log(
`Fetched ${allEventRequests.length} event requests in Astro component`,
);
// console.log(
// `Fetched ${allEventRequests.length} event requests in Astro component`,
// );
// Process the event requests to add the requested_user_expand property
allEventRequests = allEventRequests.map((request) => {
@ -172,9 +172,9 @@ try {
"-created",
{ expand: "requested_user" },
);
console.log("Initial data sync complete");
// console.log("Initial data sync complete");
} 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
@ -183,9 +183,9 @@ try {
errorElement &&
errorElement.textContent?.includes("Authentication error")
) {
console.log(
"Authentication error detected in UI, redirecting to login...",
);
// console.log(
// "Authentication error detected in UI, redirecting to login...",
// );
// Redirect to login page after a short delay
setTimeout(() => {
window.location.href = "/login";
@ -196,13 +196,13 @@ try {
// Also check if we have any event requests
const tableContainer = document.querySelector(".event-table-container");
if (tableContainer) {
console.log(
"Event table container found, component should load normally",
);
// console.log(
// "Event table container found, component should load normally",
// );
} else {
console.log(
"Event table container not found, might be an issue with rendering",
);
// console.log(
// "Event table container not found, might be an issue with rendering",
// );
}
});
</script>

View file

@ -56,7 +56,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
// Don't check authentication here - try to fetch anyway
// 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
const updatedRequests = await dataSync.getData<ExtendedEventRequest>(
@ -67,12 +67,12 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
'requested_user'
);
console.log(`Fetched ${updatedRequests.length} event requests`);
// console.log(`Fetched ${updatedRequests.length} event requests`);
setEventRequests(updatedRequests);
applyFilters(updatedRequests);
} catch (error) {
console.error('Error refreshing event requests:', error);
// console.error('Error refreshing event requests:', error);
toast.error('Failed to refresh event requests');
} finally {
setIsRefreshing(false);
@ -169,7 +169,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
const eventRequest = eventRequests.find(req => req.id === id);
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}"`);
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
closeUpdateModal();
} catch (error) {
console.error('Error in handleUpdateStatus:', error);
// console.error('Error in handleUpdateStatus:', error);
// Toast is now shown in updateEventRequestStatus
// Keep modal open so user can try again
}
@ -273,14 +273,14 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
// Check if we're authenticated
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
try {
// Try to refresh event requests anyway - the token might be valid
await refreshEventRequests();
} 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.");
// Only redirect if refresh fails
@ -289,7 +289,7 @@ const EventRequestManagementTable = ({ eventRequests: initialEventRequests }: Ev
}, 2000);
}
} 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
useEffect(() => {
const handleTabVisible = () => {
console.log("Tab became visible, refreshing event requests...");
// console.log("Tab became visible, refreshing event requests...");
refreshEventRequests();
};

View file

@ -49,7 +49,7 @@ export default function ShowProfileLogs() {
try {
setIsFetchingAll(true);
console.log("Fetching logs for user:", userId);
// console.log("Fetching logs for user:", userId);
// Use DataSyncService to fetch logs
const dataSync = DataSyncService.getInstance();
@ -70,15 +70,15 @@ export default function ShowProfileLogs() {
"-created"
);
console.log("Fetched logs:", fetchedLogs.length);
// console.log("Fetched logs:", fetchedLogs.length);
if (fetchedLogs.length === 0) {
// 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 {
const sendLog = SendLog.getInstance();
const directLogs = await sendLog.getUserLogs(userId);
console.log("Direct fetch logs:", directLogs.length);
// console.log("Direct fetch logs:", directLogs.length);
if (directLogs.length > 0) {
setAllLogs(directLogs);
@ -90,7 +90,7 @@ export default function ShowProfileLogs() {
setTotalLogs(fetchedLogs.length);
}
} catch (directError) {
console.error("Failed to fetch logs directly:", directError);
// console.error("Failed to fetch logs directly:", directError);
setAllLogs(fetchedLogs);
setTotalPages(Math.ceil(fetchedLogs.length / LOGS_PER_PAGE));
setTotalLogs(fetchedLogs.length);
@ -101,7 +101,7 @@ export default function ShowProfileLogs() {
setTotalLogs(fetchedLogs.length);
}
} catch (error) {
console.error("Failed to fetch logs:", error);
// console.error("Failed to fetch logs:", error);
setError("Error loading activity");
} finally {
setLoading(false);
@ -134,7 +134,7 @@ export default function ShowProfileLogs() {
// Update displayed logs whenever filtered results change
useEffect(() => {
setLogs(filteredLogs);
console.log("Filtered logs updated:", filteredLogs.length, "logs");
// console.log("Filtered logs updated:", filteredLogs.length, "logs");
}, [filteredLogs]);
// Debounced search handler
@ -178,12 +178,12 @@ export default function ShowProfileLogs() {
setTimeout(async () => {
// Check if logs were loaded
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();
}
}, 1000);
} 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
const result = await pb.collection(Collections.LOGS).getList(1, 1);
console.log("Logs collection check:", {
totalItems: result.totalItems,
page: result.page,
perPage: result.perPage,
totalPages: result.totalPages
});
// console.log("Logs collection check:", {
// totalItems: result.totalItems,
// page: result.page,
// perPage: result.perPage,
// totalPages: result.totalPages
// });
} 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;
}
console.log("Direct fetching logs for user:", userId);
// console.log("Direct fetching logs for user:", userId);
// Fetch logs directly from PocketBase
const result = await pb.collection(Collections.LOGS).getList<Log>(1, 100, {
@ -264,10 +264,10 @@ export default function ShowProfileLogs() {
expand: "user"
});
console.log("Direct fetch result:", {
totalItems: result.totalItems,
items: result.items.length
});
// console.log("Direct fetch result:", {
// totalItems: result.totalItems,
// items: result.items.length
// });
if (result.items.length > 0) {
setAllLogs(result.items);
@ -275,7 +275,7 @@ export default function ShowProfileLogs() {
setTotalLogs(result.items.length);
}
} catch (error) {
console.error("Failed to direct fetch logs:", error);
// console.error("Failed to direct fetch logs:", error);
setError("Error loading activity");
} finally {
setLoading(false);
@ -315,13 +315,13 @@ export default function ShowProfileLogs() {
}
// Debug logs
console.log("Render state:", {
logsLength: logs.length,
allLogsLength: allLogs.length,
searchQuery,
loading,
currentPage
});
// console.log("Render state:", {
// logsLength: logs.length,
// allLogsLength: allLogs.length,
// searchQuery,
// loading,
// currentPage
// });
if (allLogs.length === 0 && !searchQuery && !loading) {
return (
@ -348,10 +348,10 @@ export default function ShowProfileLogs() {
"Test log created for debugging",
userId
);
console.log("Created test log");
// console.log("Created test log");
setTimeout(() => fetchLogs(true), 1000);
} catch (error) {
console.error("Failed to create test log:", error);
// console.error("Failed to create test log:", error);
}
}}
>

View file

@ -13,14 +13,6 @@ const logtoEndpoint = import.meta.env.LOGTO_ENDPOINT;
const logtoTokenEndpoint = import.meta.env.LOGTO_TOKEN_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
const safeLogtoAppId = logtoAppId || "missing_app_id";
const safeLogtoAppSecret = logtoAppSecret || "missing_app_secret";

View file

@ -162,7 +162,7 @@ export default function DisplaySettings() {
if (Object.keys(updateData).length > 0) {
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) {
console.error('Error initializing default settings:', error);

View file

@ -67,7 +67,7 @@ export default function NotificationSettings() {
{ notification_preferences: JSON.stringify(DEFAULT_NOTIFICATION_PREFERENCES) }
);
setPreferences(DEFAULT_NOTIFICATION_PREFERENCES);
console.log('Initialized default notification preferences');
// console.log('Initialized default notification preferences');
} catch (error) {
console.error('Error initializing default notification preferences:', error);
}

View file

@ -45,29 +45,7 @@ export default function PasswordChangeSettings({
const logtoTokenEndpoint = envLogtoTokenEndpoint || propLogtoTokenEndpoint;
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
useEffect(() => {
@ -80,17 +58,17 @@ export default function PasswordChangeSettings({
return;
}
console.log("Current user:", user);
// console.log("Current user:", user);
const pb = auth.getPocketBase();
try {
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;
if (userId) {
setLogtoUserId(userId);
console.log("Set Logto user ID:", userId);
// console.log("Set Logto user ID:", userId);
} else {
console.error("No providerId found in external auth record");
toast.error("Could not determine your user ID. Please try again later or contact support.");
@ -153,7 +131,7 @@ export default function PasswordChangeSettings({
try {
const response = await fetch('/api/check-env');
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
const { envStatus } = data;
@ -244,7 +222,7 @@ export default function PasswordChangeSettings({
const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
if (iframeDocument) {
const responseText = iframeDocument.body.innerText;
console.log("Response from iframe:", responseText);
// console.log("Response from iframe:", responseText);
if (responseText) {
try {
@ -308,7 +286,7 @@ export default function PasswordChangeSettings({
} else {
// Use the fetch API with JSON
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
if (!logtoUserId) {
@ -317,13 +295,13 @@ export default function PasswordChangeSettings({
}
// Log the values we're about to use
console.log("Values being used for API call:");
console.log("- logtoUserId:", logtoUserId);
console.log("- newPassword:", formData.newPassword ? "[PRESENT]" : "[MISSING]");
console.log("- logtoAppId:", logtoAppId);
console.log("- logtoAppSecret:", logtoAppSecret ? "[PRESENT]" : "[MISSING]");
console.log("- logtoTokenEndpoint:", logtoTokenEndpoint);
console.log("- logtoApiEndpoint:", logtoApiEndpoint);
// console.log("Values being used for API call:");
// console.log("- logtoUserId:", logtoUserId);
// console.log("- newPassword:", formData.newPassword ? "[PRESENT]" : "[MISSING]");
// console.log("- logtoAppId:", logtoAppId);
// console.log("- logtoAppSecret:", logtoAppSecret ? "[PRESENT]" : "[MISSING]");
// console.log("- logtoTokenEndpoint:", logtoTokenEndpoint);
// console.log("- logtoApiEndpoint:", logtoApiEndpoint);
// Prepare request data with explicit values (not relying on variable references that might be undefined)
const requestData = {
@ -336,12 +314,12 @@ export default function PasswordChangeSettings({
logtoApiEndpoint: logtoApiEndpoint || logtoEndpoint
};
console.log("Request data:", {
...requestData,
currentPassword: "[REDACTED]",
newPassword: "[REDACTED]",
logtoAppSecret: "[REDACTED]"
});
// console.log("Request data:", {
// ...requestData,
// currentPassword: "[REDACTED]",
// newPassword: "[REDACTED]",
// logtoAppSecret: "[REDACTED]"
// });
// Validate request data before sending
if (!requestData.userId) {
@ -368,7 +346,7 @@ export default function PasswordChangeSettings({
// Stringify the request data to ensure it's valid JSON
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
const debugObj = {
@ -394,13 +372,13 @@ export default function PasswordChangeSettings({
body: requestBody
});
console.log("Response status:", response.status);
// console.log("Response status:", response.status);
// Process the response
let result: any;
try {
const responseText = await response.text();
console.log("Raw response:", responseText);
// console.log("Raw response:", responseText);
if (responseText) {
result = JSON.parse(responseText);
@ -408,7 +386,7 @@ export default function PasswordChangeSettings({
result = { success: false, message: 'Empty response from server' };
}
console.log("API response:", result);
// console.log("API response:", result);
// Add response to debug info
setDebugInfo((prev: any) => ({
@ -470,13 +448,13 @@ export default function PasswordChangeSettings({
type="button"
className="btn btn-sm btn-warning"
onClick={() => {
console.log("Debug Info:");
console.log("- logtoUserId:", logtoUserId);
console.log("- Environment Variables:");
console.log(" - LOGTO_APP_ID:", import.meta.env.LOGTO_APP_ID);
console.log(" - LOGTO_ENDPOINT:", import.meta.env.LOGTO_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("Debug Info:");
// console.log("- logtoUserId:", logtoUserId);
// console.log("- Environment Variables:");
// console.log(" - LOGTO_APP_ID:", import.meta.env.LOGTO_APP_ID);
// console.log(" - LOGTO_ENDPOINT:", import.meta.env.LOGTO_ENDPOINT);
// console.log(" - LOGTO_TOKEN_ENDPOINT:", import.meta.env.LOGTO_TOKEN_ENDPOINT);
// console.log(" - LOGTO_API_ENDPOINT:", import.meta.env.LOGTO_API_ENDPOINT);
toast.success("Debug info logged to console");
}}

View file

@ -104,17 +104,17 @@ export default function ResumeSettings() {
const loadingToast = toast.loading('Uploading resume...');
// Log the file being uploaded for debugging
console.log('Uploading file:', {
name: resumeFile.name,
size: resumeFile.size,
type: resumeFile.type
});
// console.log('Uploading file:', {
// name: resumeFile.name,
// size: resumeFile.size,
// type: resumeFile.type
// });
let updatedUserData: User;
try {
// 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
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');
}
console.log('Resume upload successful:', result.resume);
// console.log('Resume upload successful:', result.resume);
// Store the updated user data
updatedUserData = result;
// Fetch the updated user record to ensure we have the latest data
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
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) {
console.error('Error in file upload process:', uploadError);
@ -173,7 +173,7 @@ export default function ResumeSettings() {
toast.success('Resume uploaded successfully');
// 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
const event = new CustomEvent('resumeUploaded', {
@ -223,14 +223,14 @@ export default function ResumeSettings() {
const loadingToast = toast.loading('Deleting resume...');
// 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
const formData = new FormData();
formData.append('resume', '');
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
const result = await fileManager.deleteFile<User>(
@ -241,22 +241,22 @@ export default function ResumeSettings() {
// Verify the file was deleted
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.error('Failed to completely remove the resume. Please try again.');
setUploading(false);
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
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
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) {
console.error('Error in file deletion process:', deleteError);
@ -275,7 +275,7 @@ export default function ResumeSettings() {
toast.success('Resume deleted successfully');
// 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
const event = new CustomEvent('resumeUploaded', {
@ -356,11 +356,11 @@ export default function ResumeSettings() {
const loadingToast = toast.loading('Replacing resume...');
// Log the file being uploaded for debugging
console.log('Replacing resume with file:', {
name: file.name,
size: file.size,
type: file.type
});
// console.log('Replacing resume with file:', {
// name: file.name,
// size: file.size,
// type: file.type
// });
// Create a FormData object for the file upload
const formData = new FormData();

View file

@ -112,27 +112,27 @@ export default function ReimbursementList() {
const fileManager = FileManager.getInstance();
useEffect(() => {
console.log('Component mounted');
// console.log('Component mounted');
fetchReimbursements();
}, []);
// Add effect to monitor requests state
useEffect(() => {
console.log('Requests state updated:', requests);
console.log('Number of requests:', requests.length);
// console.log('Requests state updated:', requests);
// console.log('Number of requests:', requests.length);
}, [requests]);
// Add a useEffect to log preview URL and filename changes
useEffect(() => {
console.log('Preview URL changed:', previewUrl);
console.log('Preview filename changed:', previewFilename);
// console.log('Preview URL changed:', previewUrl);
// console.log('Preview filename changed:', previewFilename);
}, [previewUrl, previewFilename]);
// Add a useEffect to log when the preview modal is shown/hidden
useEffect(() => {
console.log('Show preview changed:', showPreview);
// console.log('Show preview changed:', showPreview);
if (showPreview) {
console.log('Selected receipt:', selectedReceipt);
// console.log('Selected receipt:', selectedReceipt);
}
}, [showPreview, selectedReceipt]);
@ -167,7 +167,7 @@ export default function ReimbursementList() {
'-created'
);
console.log('Reimbursement records from IndexedDB:', reimbursementRecords);
// console.log('Reimbursement records from IndexedDB:', reimbursementRecords);
// Process the records
const processedRecords = reimbursementRecords.map(record => {
@ -183,7 +183,7 @@ export default function ReimbursementList() {
auditNotes = record.audit_notes;
}
} 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[];
}
} 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) {
console.error(`Error fetching receipt ${receiptId}:`, e);
// console.error(`Error fetching receipt ${receiptId}:`, e);
}
}
}
}
} catch (err) {
console.error('Error fetching reimbursements:', err);
// console.error('Error fetching reimbursements:', err);
setError('Failed to load reimbursements. Please try again.');
} finally {
setLoading(false);
@ -256,7 +256,7 @@ export default function ReimbursementList() {
const handlePreviewFile = async (request: ReimbursementRequest, receiptId: string) => {
try {
console.log('Previewing file for receipt ID:', receiptId);
// console.log('Previewing file for receipt ID:', receiptId);
const pb = auth.getPocketBase();
const fileManager = FileManager.getInstance();
@ -265,13 +265,13 @@ export default function ReimbursementList() {
// Check if we already have the receipt details in our map
if (receiptDetailsMap[receiptId]) {
console.log('Using cached receipt details');
// console.log('Using cached receipt details');
// Use the cached receipt details
setSelectedReceipt(receiptDetailsMap[receiptId]);
// Check if the receipt has a 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');
setPreviewUrl('');
setPreviewFilename('');
@ -280,7 +280,7 @@ export default function ReimbursementList() {
}
// 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(
'receipts',
receiptId,
@ -290,7 +290,7 @@ export default function ReimbursementList() {
// Check if the URL is empty
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');
// Still show the preview modal but with empty URL to display the error message
setPreviewUrl('');
@ -299,7 +299,7 @@ export default function ReimbursementList() {
return;
}
console.log('Got URL:', url.substring(0, 50) + '...');
// console.log('Got URL:', url.substring(0, 50) + '...');
// Set the preview URL and filename
setPreviewUrl(url);
@ -309,28 +309,28 @@ export default function ReimbursementList() {
setShowPreview(true);
// Log the current state
console.log('Current state after setting:', {
previewUrl: url,
previewFilename: receiptDetailsMap[receiptId].file,
showPreview: true
});
// console.log('Current state after setting:', {
// previewUrl: url,
// previewFilename: receiptDetailsMap[receiptId].file,
// showPreview: true
// });
return;
}
// 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, {
$autoCancel: false
});
if (receiptRecord) {
console.log('Receipt record found:', receiptRecord.id);
console.log('Receipt file:', receiptRecord.file);
// console.log('Receipt record found:', receiptRecord.id);
// console.log('Receipt file:', receiptRecord.file);
// Check if the receipt has a 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');
setPreviewUrl('');
setPreviewFilename('');
@ -367,7 +367,7 @@ export default function ReimbursementList() {
setSelectedReceipt(receiptDetails);
// 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(
'receipts',
receiptRecord.id,
@ -377,7 +377,7 @@ export default function ReimbursementList() {
// Check if the URL is empty
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');
// Still show the preview modal but with empty URL to display the error message
setPreviewUrl('');
@ -386,7 +386,7 @@ export default function ReimbursementList() {
return;
}
console.log('Got URL:', url.substring(0, 50) + '...');
// console.log('Got URL:', url.substring(0, 50) + '...');
// Set the preview URL and filename
setPreviewUrl(url);
@ -396,16 +396,16 @@ export default function ReimbursementList() {
setShowPreview(true);
// Log the current state
console.log('Current state after setting:', {
previewUrl: url,
previewFilename: receiptRecord.file,
showPreview: true
});
// console.log('Current state after setting:', {
// previewUrl: url,
// previewFilename: receiptRecord.file,
// showPreview: true
// });
} else {
throw new Error('Receipt not found');
}
} catch (error) {
console.error('Error loading receipt:', error);
// console.error('Error loading receipt:', error);
toast.error('Failed to load receipt. Please try again.');
// Show the preview modal with empty URL to display the error message
setPreviewUrl('');
@ -423,7 +423,7 @@ export default function ReimbursementList() {
};
if (loading) {
console.log('Rendering loading state');
// console.log('Rendering loading state');
return (
<motion.div
initial={{ opacity: 0 }}
@ -437,7 +437,7 @@ export default function ReimbursementList() {
}
if (error) {
console.log('Rendering error state:', error);
// console.log('Rendering error state:', error);
return (
<motion.div
initial={{ opacity: 0, y: -20 }}
@ -450,8 +450,8 @@ export default function ReimbursementList() {
);
}
console.log('Rendering main component. Requests:', requests);
console.log('Requests length:', requests.length);
// console.log('Rendering main component. Requests:', requests);
// console.log('Requests length:', requests.length);
return (
<>
@ -482,7 +482,7 @@ export default function ReimbursementList() {
>
<AnimatePresence mode="popLayout">
{requests.map((request, index) => {
console.log('Rendering request:', request);
// console.log('Rendering request:', request);
return (
<motion.div
key={request.id}

View file

@ -134,7 +134,6 @@ export default function ReimbursementManagementPortal() {
}
const records = await get.getAll<ExtendedReimbursement>('reimbursement', filter, sort);
console.log('Loaded reimbursements:', records);
// Load user data for submitters
const userIds = new Set(records.map(r => r.submitted_by));
@ -165,11 +164,9 @@ export default function ReimbursementManagementPortal() {
// Load associated 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) {
try {
console.log('Attempting to load receipts with IDs:', receiptIds);
const receiptRecords = await Promise.all(
receiptIds.map(async id => {
try {
@ -202,12 +199,10 @@ export default function ReimbursementManagementPortal() {
);
const validReceipts = receiptRecords.filter((r): r is ExtendedReceipt => r !== null);
console.log('Successfully loaded receipt records:', validReceipts);
const receiptMap = Object.fromEntries(
validReceipts.map(receipt => [receipt.id, receipt])
);
console.log('Created receipt map:', receiptMap);
setReceipts(receiptMap);
} catch (error: any) {
console.error('Error loading receipts:', error);
@ -219,7 +214,7 @@ export default function ReimbursementManagementPortal() {
toast.error('Failed to load receipts: ' + (error?.message || 'Unknown error'));
}
} else {
console.log('No receipt IDs found in reimbursements');
// console.log('No receipt IDs found in reimbursements');
setReceipts({});
}
} catch (error) {

View file

@ -29,7 +29,7 @@ const ImageWithFallback = ({ url, filename, onError }: ImageWithFallbackProps) =
try {
// 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' });
if (!response.ok) {
@ -38,7 +38,7 @@ const ImageWithFallback = ({ url, filename, onError }: ImageWithFallbackProps) =
const blob = await response.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
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.');
// Log additional details
console.log('Image URL that failed:', url);
console.log('Current auth status:',
Authentication.getInstance().isAuthenticated() ? 'Authenticated' : 'Not authenticated'
);
// console.log('Image URL that failed:', url);
// console.log('Current auth status:',
// Authentication.getInstance().isAuthenticated() ? 'Authenticated' : 'Not authenticated'
// );
}
};

View file

@ -76,26 +76,26 @@ const Calendar = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
const loadGapiAndListEvents = async () => {
try {
console.log("Starting to load events...");
// console.log("Starting to load events...");
if (typeof window.gapi === "undefined") {
console.log("Loading GAPI script...");
// console.log("Loading GAPI script...");
await new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = "https://apis.google.com/js/api.js";
document.body.appendChild(script);
script.onload = () => {
console.log("GAPI script loaded");
// console.log("GAPI script loaded");
window.gapi.load("client", resolve);
};
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."));
};
});
}
console.log("Initializing GAPI client...");
// console.log("Initializing GAPI client...");
await window.gapi.client.init({
apiKey: CALENDAR_API_KEY,
discoveryDocs: [
@ -115,7 +115,7 @@ const Calendar = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
0,
);
console.log("Fetching events...");
// console.log("Fetching events...");
const response = await window.gapi.client.calendar.events.list({
calendarId: calendarId,
timeZone: userTimeZone,
@ -125,13 +125,13 @@ const Calendar = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
orderBy: "startTime",
});
console.log("Response received:", response);
// console.log("Response received:", response);
if (response.result.items) {
setEvents(response.result.items);
}
} catch (error) {
console.error("Detailed Error: ", error);
// console.error("Detailed Error: ", error);
setError(error.message || "Failed to load events");
} finally {
setLoading(false);

View file

@ -48,16 +48,16 @@ const EventList = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
const loadGapiAndListEvents = async () => {
try {
console.log("Starting to load events...");
// console.log("Starting to load events...");
if (typeof window.gapi === "undefined") {
console.log("Loading GAPI script...");
// console.log("Loading GAPI script...");
await new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = "https://apis.google.com/js/api.js";
document.body.appendChild(script);
script.onload = () => {
console.log("GAPI script loaded");
// console.log("GAPI script loaded");
window.gapi.load("client", resolve);
};
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({
apiKey: apiKey,
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({
calendarId: calendarId,
timeZone: userTimeZone,
@ -85,7 +85,7 @@ const EventList = ({ CALENDAR_API_KEY, EVENT_CALENDAR_ID }) => {
orderBy: "startTime",
});
console.log("Response received:", response);
// console.log("Response received:", response);
if (response.result.items) {
setEvents(response.result.items);

View file

@ -11,8 +11,6 @@ async function getLogtoAccessToken(
scope: string = "all",
): Promise<string | null> {
try {
console.log("Attempting to get access token from Logto");
// Create Basic auth string
const authString = Buffer.from(`${clientId}:${clientSecret}`).toString(
"base64",
@ -59,8 +57,6 @@ async function verifyUserPassword(
accessToken: string,
): Promise<boolean> {
try {
console.log("Verifying current password");
const response = await fetch(
`${logtoApiEndpoint}/api/users/${userId}/password/verify`,
{
@ -75,7 +71,6 @@ async function verifyUserPassword(
// 204 means password matches, 422 means it doesn't match
if (response.status === 204) {
console.log("Current password verified successfully");
return true;
}
@ -101,8 +96,6 @@ async function verifyUserPassword(
export const POST: APIRoute = async ({ request }) => {
try {
console.log("Received change password request");
// Parse request body
const contentType = request.headers.get("content-type");
const rawBody = await request.text();
@ -161,6 +154,7 @@ export const POST: APIRoute = async ({ request }) => {
}
// Get access token
// console.log("Attempting to get access token from Logto");
const accessToken = await getLogtoAccessToken(
logtoTokenEndpoint,
logtoAppId,
@ -181,6 +175,7 @@ export const POST: APIRoute = async ({ request }) => {
}
// Verify current password before proceeding
// console.log("Verifying current password");
const isPasswordValid = await verifyUserPassword(
logtoApiEndpoint,
userId,
@ -202,6 +197,7 @@ export const POST: APIRoute = async ({ request }) => {
}
// Change password using Logto Management API
// console.log("Current password verified successfully");
const changePasswordResponse = await fetch(
`${logtoApiEndpoint}/api/users/${userId}/password`,
{

View file

@ -26,13 +26,13 @@ const components = Object.fromEntries(
const component = await import(
`../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];
})
)
}),
),
);
console.log("Available components:", Object.keys(components)); // Debug log
// console.log("Available components:", Object.keys(components)); // Debug log
---
<!doctype html>
@ -65,33 +65,19 @@ console.log("Available components:", Object.keys(components)); // Debug log
<!-- User Profile -->
<div class="p-6 border-b border-base-200">
<!-- Loading State -->
<div
id="userProfileSkeleton"
class="flex items-center gap-4"
>
<div id="userProfileSkeleton" class="flex items-center gap-4">
<div class="avatar flex items-center justify-center">
<div
class="w-12 h-12 rounded-xl bg-base-300 animate-pulse"
>
</div>
<div class="w-12 h-12 rounded-xl bg-base-300 animate-pulse"></div>
</div>
<div class="flex-1">
<div
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 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>
<!-- Signed Out State -->
<div
id="userProfileSignedOut"
class="flex items-center gap-4 hidden"
>
<div id="userProfileSignedOut" class="flex items-center gap-4 hidden">
<div class="avatar flex items-center justify-center">
<div
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>
<h3
class="font-medium text-lg text-base-content/70"
>
<h3 class="font-medium text-lg text-base-content/70">
Signed Out
</h3>
<div class="badge badge-outline mt-1 opacity-50">
Guest
</div>
<div class="badge badge-outline mt-1 opacity-50">Guest</div>
</div>
</div>
<!-- Actual Profile -->
<div
id="userProfileSummary"
class="flex items-center gap-4 hidden"
>
<div id="userProfileSummary" class="flex items-center gap-4 hidden">
<div class="avatar flex items-center justify-center">
<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"
@ -127,9 +106,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
</div>
</div>
<div>
<h3 class="font-medium text-lg" id="userName">
Loading...
</h3>
<h3 class="font-medium text-lg" id="userName">Loading...</h3>
<div
class="badge badge-outline mt-1 border-[#06659d] text-[#06659d]"
id="userRole"
@ -168,64 +145,41 @@ console.log("Available components:", Object.keys(components)); // Debug log
<div id="actualMenu" class="hidden">
{
Object.entries(dashboardConfig.categories).map(
([categoryKey, category]: [
string,
any,
]) => (
([categoryKey, category]: [string, any]) => (
<>
<li
class={`menu-title font-medium opacity-70 ${
category.role &&
category.role !== "none"
category.role && category.role !== "none"
? "hidden"
: ""
}`}
data-role-required={
category.role || "none"
}
data-role-required={category.role || "none"}
>
<span>{category.title}</span>
</li>
{category.sections.map(
(sectionKey: string) => {
const section =
dashboardConfig
.sections[
sectionKey
];
{category.sections.map((sectionKey: string) => {
const section = dashboardConfig.sections[sectionKey];
return (
<li
class={
section.role &&
section.role !==
"none"
section.role && section.role !== "none"
? "hidden"
: ""
}
data-role-required={
section.role
}
data-role-required={section.role}
>
<button
class={`dashboard-nav-btn gap-4 transition-all duration-200 outline-none focus:outline-none hover:bg-opacity-5 ${section.class || ""}`}
data-section={
sectionKey
}
data-section={sectionKey}
>
<Icon
name={
section.icon
}
class="h-5 w-5"
/>
<Icon name={section.icon} class="h-5 w-5" />
{section.title}
</button>
</li>
);
}
)}
})}
</>
)
),
)
}
</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)]"
>
<!-- Mobile Header -->
<header
class="bg-base-100 p-4 shadow-md xl:hidden sticky top-0 z-40"
>
<header 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 gap-2">
<button
id="mobileSidebarToggle"
class="btn btn-square btn-ghost"
>
<button id="mobileSidebarToggle" class="btn btn-square btn-ghost">
<Icon name="heroicons:bars-3" class="h-6 w-6" />
</button>
<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">
<!-- Loading State -->
<div id="pageLoadingState" class="w-full">
<div
class="flex flex-col items-center justify-center p-4 sm:p-8"
>
<div class="loading loading-spinner loading-lg">
</div>
<div class="flex flex-col items-center justify-center p-4 sm:p-8">
<div class="loading loading-spinner loading-lg"></div>
<p class="mt-4 opacity-70">Loading dashboard...</p>
</div>
</div>
@ -288,9 +234,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
<!-- Not Authenticated State -->
<div id="notAuthenticatedState" class="hidden w-full">
<div class="card bg-base-100 shadow-xl mx-2 sm:mx-0">
<div
class="card-body items-center text-center p-4 sm:p-8"
>
<div class="card-body items-center text-center p-4 sm:p-8">
<div class="mb-4 sm:mb-6">
<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">
Sign in to Access Dashboard
</h2>
<p
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.
<p 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.
</p>
<button
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
if (!section.component) return null;
const Component =
components[section.component];
const Component = components[section.component];
return (
<div
id={`${sectionKey}Section`}
class={`dashboard-section hidden ${
section.role &&
section.role !== "none"
section.role && section.role !== "none"
? "role-restricted"
: ""
}`}
@ -359,7 +299,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
<Component />
</div>
);
}
},
)
}
</div>
@ -383,11 +323,10 @@ console.log("Available components:", Object.keys(components)); // Debug log
const logger = SendLog.getInstance();
// Initialize page state
const pageLoadingState =
document.getElementById("pageLoadingState");
const pageLoadingState = document.getElementById("pageLoadingState");
const pageErrorState = document.getElementById("pageErrorState");
const notAuthenticatedState = document.getElementById(
"notAuthenticatedState"
"notAuthenticatedState",
);
const mainContent = document.getElementById("mainContent");
const sidebar = document.querySelector("aside");
@ -418,11 +357,9 @@ console.log("Available components:", Object.keys(components)); // Debug log
}
// For non-sponsor roles, handle normally
document
.querySelectorAll("[data-role-required]")
.forEach((element) => {
document.querySelectorAll("[data-role-required]").forEach((element) => {
const requiredRole = element.getAttribute(
"data-role-required"
"data-role-required",
) as OfficerStatus;
// 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
const hasPermission = hasAccess(
officerStatus,
requiredRole
);
const hasPermission = hasAccess(officerStatus, requiredRole);
// Only show elements if user has permission
element.classList.toggle("hidden", !hasPermission);
@ -444,10 +378,8 @@ console.log("Available components:", Object.keys(components)); // Debug log
// Handle navigation
const handleNavigation = () => {
const navButtons =
document.querySelectorAll(".dashboard-nav-btn");
const sections =
document.querySelectorAll(".dashboard-section");
const navButtons = document.querySelectorAll(".dashboard-nav-btn");
const sections = document.querySelectorAll(".dashboard-section");
const mainContentDiv = document.getElementById("mainContent");
// Ensure mainContent is visible
@ -481,19 +413,17 @@ console.log("Available components:", Object.keys(components)); // Debug log
// Show selected section
const sectionId = `${sectionKey}Section`;
const targetSection =
document.getElementById(sectionId);
const targetSection = document.getElementById(sectionId);
if (targetSection) {
targetSection.classList.remove("hidden");
console.log(`Showing section: ${sectionId}`); // Debug log
// console.log(`Showing section: ${sectionId}`); // Debug log
}
// Close mobile sidebar if needed
if (window.innerWidth < 1024 && sidebar) {
sidebar.classList.add("-translate-x-full");
document.body.classList.remove("overflow-hidden");
const overlay =
document.getElementById("sidebarOverlay");
const overlay = document.getElementById("sidebarOverlay");
overlay?.remove();
}
});
@ -537,7 +467,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
"",
{
fields: ["id", "type", "role"],
}
},
);
if (officerRecords && officerRecords.items.length > 0) {
@ -579,7 +509,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
"",
{
fields: ["id", "company"],
}
},
);
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 (userRole) userRole.textContent = fallbackValues.role;
if (userInitials)
userInitials.textContent = fallbackValues.initials;
if (userInitials) userInitials.textContent = fallbackValues.initials;
updateSectionVisibility("" as OfficerStatus);
}
@ -622,18 +551,16 @@ console.log("Available components:", Object.keys(components)); // Debug log
// Mobile sidebar toggle
const mobileSidebarToggle = document.getElementById(
"mobileSidebarToggle"
"mobileSidebarToggle",
);
if (mobileSidebarToggle && sidebar) {
const toggleSidebar = () => {
const isOpen =
!sidebar.classList.contains("-translate-x-full");
const isOpen = !sidebar.classList.contains("-translate-x-full");
if (isOpen) {
sidebar.classList.add("-translate-x-full");
document.body.classList.remove("overflow-hidden");
const overlay =
document.getElementById("sidebarOverlay");
const overlay = document.getElementById("sidebarOverlay");
overlay?.remove();
} else {
sidebar.classList.remove("-translate-x-full");
@ -658,38 +585,35 @@ console.log("Available components:", Object.keys(components)); // Debug log
// Check if user is authenticated
if (!auth.isAuthenticated()) {
console.log("User not authenticated");
if (pageLoadingState)
pageLoadingState.classList.add("hidden");
// console.log("User not authenticated");
if (pageLoadingState) pageLoadingState.classList.add("hidden");
if (notAuthenticatedState)
notAuthenticatedState.classList.remove("hidden");
return;
}
if (pageLoadingState)
pageLoadingState.classList.remove("hidden");
if (pageLoadingState) pageLoadingState.classList.remove("hidden");
if (pageErrorState) pageErrorState.classList.add("hidden");
if (notAuthenticatedState)
notAuthenticatedState.classList.add("hidden");
// Show loading states
const userProfileSkeleton = document.getElementById(
"userProfileSkeleton"
"userProfileSkeleton",
);
const userProfileSignedOut = document.getElementById(
"userProfileSignedOut"
"userProfileSignedOut",
);
const userProfileSummary =
document.getElementById("userProfileSummary");
const menuLoadingSkeleton = document.getElementById(
"menuLoadingSkeleton"
"menuLoadingSkeleton",
);
const actualMenu = document.getElementById("actualMenu");
if (userProfileSkeleton)
userProfileSkeleton.classList.remove("hidden");
if (userProfileSummary)
userProfileSummary.classList.add("hidden");
if (userProfileSummary) userProfileSummary.classList.add("hidden");
if (userProfileSignedOut)
userProfileSignedOut.classList.add("hidden");
if (menuLoadingSkeleton)
@ -700,15 +624,11 @@ console.log("Available components:", Object.keys(components)); // Debug log
await updateUserProfile(user);
// Show actual profile and hide skeleton
if (userProfileSkeleton)
userProfileSkeleton.classList.add("hidden");
if (userProfileSummary)
userProfileSummary.classList.remove("hidden");
if (userProfileSkeleton) userProfileSkeleton.classList.add("hidden");
if (userProfileSummary) userProfileSummary.classList.remove("hidden");
// Hide all sections first
document
.querySelectorAll(".dashboard-section")
.forEach((section) => {
document.querySelectorAll(".dashboard-section").forEach((section) => {
section.classList.add("hidden");
});
@ -725,7 +645,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
"",
{
fields: ["id", "type", "role"],
}
},
);
if (officerRecords && officerRecords.items.length > 0) {
@ -763,23 +683,17 @@ console.log("Available components:", Object.keys(components)); // Debug log
"",
{
fields: ["id", "company"],
}
},
);
if (
sponsorRecords &&
sponsorRecords.items.length > 0
) {
if (sponsorRecords && sponsorRecords.items.length > 0) {
officerStatus = "sponsor";
} else {
officerStatus = "none";
}
}
} catch (error) {
console.error(
"Error determining officer status:",
error
);
console.error("Error determining officer status:", error);
officerStatus = "none";
}
@ -790,24 +704,17 @@ console.log("Available components:", Object.keys(components)); // Debug log
// Only sponsors get a different default view
if (officerStatus === "sponsor") {
// For sponsors, show the sponsor dashboard
defaultSection = document.getElementById(
"sponsorDashboardSection"
);
defaultSection = document.getElementById("sponsorDashboardSection");
defaultButton = document.querySelector(
'[data-section="sponsorDashboard"]'
'[data-section="sponsorDashboard"]',
);
} else {
// For all other users (including administrators), show the profile section
defaultSection =
document.getElementById("profileSection");
defaultButton = document.querySelector(
'[data-section="profile"]'
);
defaultSection = document.getElementById("profileSection");
defaultButton = document.querySelector('[data-section="profile"]');
// Log the default section for debugging
console.log(
`Setting default section to profile for user with role: ${officerStatus}`
);
// console.log(`Setting default section to profile for user with role: ${officerStatus}`);
}
if (defaultSection) {
@ -821,20 +728,16 @@ console.log("Available components:", Object.keys(components)); // Debug log
handleNavigation();
// Show actual menu and hide skeleton
if (menuLoadingSkeleton)
menuLoadingSkeleton.classList.add("hidden");
if (menuLoadingSkeleton) menuLoadingSkeleton.classList.add("hidden");
if (actualMenu) actualMenu.classList.remove("hidden");
// Show main content and hide loading
if (mainContent) mainContent.classList.remove("hidden");
if (pageLoadingState)
pageLoadingState.classList.add("hidden");
if (pageLoadingState) pageLoadingState.classList.add("hidden");
} catch (error) {
console.error("Error initializing dashboard:", error);
if (pageLoadingState)
pageLoadingState.classList.add("hidden");
if (pageErrorState)
pageErrorState.classList.remove("hidden");
if (pageLoadingState) pageLoadingState.classList.add("hidden");
if (pageErrorState) pageErrorState.classList.remove("hidden");
}
};
@ -846,24 +749,19 @@ console.log("Available components:", Object.keys(components)); // Debug log
.querySelector(".login-button")
?.addEventListener("click", async () => {
try {
if (pageLoadingState)
pageLoadingState.classList.remove("hidden");
if (pageLoadingState) pageLoadingState.classList.remove("hidden");
if (notAuthenticatedState)
notAuthenticatedState.classList.add("hidden");
await auth.login();
} catch (error) {
console.error("Login error:", error);
if (pageLoadingState)
pageLoadingState.classList.add("hidden");
if (pageErrorState)
pageErrorState.classList.remove("hidden");
if (pageLoadingState) pageLoadingState.classList.add("hidden");
if (pageErrorState) pageErrorState.classList.remove("hidden");
}
});
// Handle logout button click
document
.getElementById("logoutButton")
?.addEventListener("click", () => {
document.getElementById("logoutButton")?.addEventListener("click", () => {
auth.logout();
window.location.reload();
});
@ -876,8 +774,7 @@ console.log("Available components:", Object.keys(components)); // Debug log
window.addEventListener("resize", () => {
if (window.innerWidth >= 1024) {
const overlay =
document.getElementById("sidebarOverlay");
const overlay = document.getElementById("sidebarOverlay");
if (overlay) {
overlay.remove();
document.body.classList.remove("overflow-hidden");

View file

@ -60,7 +60,7 @@ export class RedirectHandler {
{ emailVisibility: false },
);
console.log("Auth successful:", authData);
// console.log("Auth successful:", authData);
this.contentEl.innerHTML = `
<p class="text-3xl font-bold text-green-500 mb-4">Authentication Successful!</p>
<p class="text-2xl font-medium">Initializing your data...</p>
@ -99,19 +99,15 @@ export class RedirectHandler {
private async initializeDataSync(): Promise<void> {
try {
// 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
const authSync = AuthSyncService.getInstance();
const syncResult = await authSync.handleLogin();
if (syncResult) {
console.log('Initial data sync completed successfully');
} else {
console.warn('Initial data sync completed with issues');
}
// console.log('Initial data sync completed successfully');
} 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
}
}

View file

@ -78,7 +78,7 @@ export class AuthSyncService {
if (!isBrowser) return true;
if (this.isSyncing) {
console.log("Sync already in progress, queueing login sync");
// console.log("Sync already in progress, queueing login sync");
if (this.syncPromise) {
this.syncPromise = this.syncPromise.then(() => this.performLoginSync());
} else {
@ -100,7 +100,7 @@ export class AuthSyncService {
if (!isBrowser) return;
if (!this.auth.isAuthenticated()) {
console.log("Not authenticated, skipping login sync");
// console.log("Not authenticated, skipping login sync");
return;
}
@ -108,7 +108,7 @@ export class AuthSyncService {
this.syncErrors = {};
try {
console.log("Starting login sync process...");
// console.log("Starting login sync process...");
// Display sync notification if in browser environment
this.showSyncNotification("Syncing your data...");
@ -123,7 +123,7 @@ export class AuthSyncService {
);
// 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
@ -131,9 +131,9 @@ export class AuthSyncService {
this.collectionsToSync.map(async (collection) => {
try {
await this.dataSync.syncCollection(collection);
console.log(`Successfully synced ${collection}`);
// console.log(`Successfully synced ${collection}`);
} catch (error) {
console.error(`Error syncing ${collection}:`, error);
// console.error(`Error syncing ${collection}:`, error);
this.syncErrors[collection] = error as Error;
}
}),
@ -146,17 +146,17 @@ export class AuthSyncService {
const syncVerification = await this.verifySyncSuccess();
if (syncVerification.success) {
console.log("Login sync completed successfully");
// console.log("Login sync completed successfully");
this.showSyncNotification("Data sync complete!", "success");
} else {
console.warn(
"Login sync completed with issues:",
syncVerification.errors,
);
// console.warn(
// "Login sync completed with issues:",
// syncVerification.errors,
// );
this.showSyncNotification("Some data could not be synced", "warning");
}
} catch (error) {
console.error("Error during login sync:", error);
// console.error("Error during login sync:", error);
this.showSyncNotification("Failed to sync data", "error");
} finally {
this.isSyncing = false;
@ -180,7 +180,7 @@ export class AuthSyncService {
if (!isBrowser) return true;
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");
return true;
}
@ -188,7 +188,7 @@ export class AuthSyncService {
this.isSyncing = true;
try {
console.log("Starting logout cleanup process...");
// console.log("Starting logout cleanup process...");
// Ensure any pending changes are synced before logout
await this.syncPendingChanges();
@ -196,10 +196,10 @@ export class AuthSyncService {
// Clear all data from IndexedDB
await this.dexieService.clearAllData();
console.log("Logout cleanup completed successfully");
// console.log("Logout cleanup completed successfully");
return true;
} catch (error) {
console.error("Error during logout cleanup:", error);
// console.error("Error during logout cleanup:", error);
return false;
} finally {
this.isSyncing = false;
@ -224,7 +224,7 @@ export class AuthSyncService {
// This would be implemented if we had offline capabilities
// 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
}
@ -284,7 +284,7 @@ export class AuthSyncService {
window.toast(message, { type });
} else {
// 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> {
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
return true;
}

View file

@ -83,7 +83,7 @@ export class DataSyncService {
private async handleOnline(): Promise<void> {
if (!isBrowser) return;
console.log("Device is online, syncing pending changes...");
// console.log("Device is online, syncing pending changes...");
this.offlineMode = false;
await this.syncOfflineChanges();
}
@ -94,7 +94,7 @@ export class DataSyncService {
private handleOffline(): void {
if (!isBrowser) return;
console.log("Device is offline, enabling offline mode...");
// console.log("Device is offline, enabling offline mode...");
this.offlineMode = true;
}
@ -109,13 +109,13 @@ export class DataSyncService {
): Promise<T[]> {
// Skip in non-browser environments
if (!isBrowser) {
console.log(`Skipping sync for ${collection} in non-browser environment`);
// console.log(`Skipping sync for ${collection} in non-browser environment`);
return [];
}
// Prevent multiple syncs of the same collection at the same time
if (this.syncInProgress[collection]) {
console.log(`Sync already in progress for ${collection}`);
// console.log(`Sync already in progress for ${collection}`);
return [];
}
@ -124,19 +124,19 @@ export class DataSyncService {
try {
// Check if we're authenticated
if (!this.auth.isAuthenticated()) {
console.log(`Not authenticated, skipping sync for ${collection}`);
// console.log(`Not authenticated, skipping sync for ${collection}`);
return [];
}
// Check if we're offline
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 table = this.getTableForCollection(collection);
return table ? ((await table.toArray()) as T[]) : [];
}
console.log(`Syncing ${collection}...`);
// console.log(`Syncing ${collection}...`);
// Normalize expand parameter to be an array of strings
let normalizedExpand: string[] | undefined;
@ -158,7 +158,7 @@ export class DataSyncService {
const items = await this.get.getAll<T>(collection, filter, sort, {
expand: normalizedExpand,
});
console.log(`Fetched ${items.length} items from ${collection}`);
// console.log(`Fetched ${items.length} items from ${collection}`);
// Get the database table
const db = this.dexieService.getDB();
@ -181,11 +181,11 @@ export class DataSyncService {
const existingItem = existingItemsMap.get(item.id);
// 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
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
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 {
// Initialize empty files array if not present
(item as any).files = [];
@ -232,18 +232,21 @@ export class DataSyncService {
// For events, ensure we handle the files field properly
if (collection === Collections.EVENTS) {
// Ensure files array is properly handled
if ('files' in serverItem && Array.isArray((serverItem as any).files)) {
console.log(`Server event ${serverItem.id} has ${(serverItem as any).files.length} files`);
if ("files" in serverItem && Array.isArray((serverItem as any).files)) {
// console.log(`Server event ${serverItem.id} has ${(serverItem as any).files.length} files`);
} else {
// Initialize empty files array if not present
(serverItem as any).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 &&
(!('files' in serverItem) || !(serverItem as any).files.length)) {
console.log(`Preserving local files for event ${localItem.id}`);
(!("files" in serverItem) || !(serverItem as any).files.length)
) {
// console.log(`Preserving local files for event ${localItem.id}`);
(serverItem as any).files = (localItem as any).files;
}
}
@ -255,9 +258,9 @@ export class DataSyncService {
);
if (pendingChanges.length > 0) {
console.log(
`Found ${pendingChanges.length} pending changes for ${collection}:${localItem.id}`,
);
// console.log(
// `Found ${pendingChanges.length} pending changes for ${collection}:${localItem.id}`,
// );
// Server-wins strategy by default, but preserve local changes that haven't been synced
const mergedItem = { ...serverItem };
@ -268,12 +271,16 @@ export class DataSyncService {
// Apply each field change individually
Object.entries(change.data).forEach(([key, value]) => {
// Special handling for files array
if (key === 'files' && Array.isArray(value)) {
if (key === "files" && Array.isArray(value)) {
// 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[];
(mergedItem as any)[key] = [...new Set([...existingFiles, ...newFiles])];
console.log(`Merged files for ${collection}:${localItem.id}`, (mergedItem as any)[key]);
(mergedItem as any)[key] = [
...new Set([...existingFiles, ...newFiles]),
];
// console.log(`Merged files for ${collection}:${localItem.id}`, (mergedItem as any)[key]);
} else {
(mergedItem as any)[key] = value;
}
@ -326,11 +333,11 @@ export class DataSyncService {
.toArray();
if (pendingChanges.length === 0) {
console.log("No pending offline changes to sync");
// console.log("No pending offline changes to sync");
return true;
}
console.log(`Syncing ${pendingChanges.length} offline changes...`);
// console.log(`Syncing ${pendingChanges.length} offline changes...`);
// Group changes by collection for more efficient processing
const changesByCollection = pendingChanges.reduce(
@ -411,9 +418,9 @@ export class DataSyncService {
};
const id = await this.offlineChangesTable.add(change as OfflineChange);
console.log(
`Recorded offline change: ${operation} on ${collection}:${recordId}`,
);
// console.log(
// `Recorded offline change: ${operation} on ${collection}:${recordId}`,
// );
// Try to sync immediately if we're online
if (!this.offlineMode) {
@ -500,7 +507,7 @@ export class DataSyncService {
// SECURITY FIX: Remove event_code from events before returning them
if (collection === Collections.EVENTS) {
data = data.map((item: any) => {
if ('event_code' in item) {
if ("event_code" in item) {
const { event_code, ...rest } = item;
return rest;
}
@ -538,14 +545,19 @@ export class DataSyncService {
// For events, ensure we handle the files field properly
if (collection === Collections.EVENTS) {
// 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 = [];
}
// 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) &&
(item as any).files.length > 0 && !(pbItem as any).files.length) {
console.log(`Preserving local files for event ${id}`);
if (
item &&
"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;
}
@ -587,8 +599,8 @@ export class DataSyncService {
}
// Special handling for files field in events
if (collection === Collections.EVENTS && 'files' in data) {
console.log(`Updating files for event ${id}`, (data as any).files);
if (collection === Collections.EVENTS && "files" in data) {
// console.log(`Updating files for event ${id}`, (data as any).files);
// Ensure files is an array
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 ('files' in currentItem && Array.isArray((currentItem as any).files)) {
if ("files" in currentItem && Array.isArray((currentItem as any).files)) {
// Merge files arrays, removing duplicates
const existingFiles = (currentItem as any).files as string[];
const newFiles = (data as any).files as string[];
(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 {
// Store in localStorage instead of IndexedDB for security
localStorage.setItem('pending_event_code', eventCode);
localStorage.setItem('pending_event_code_timestamp', Date.now().toString());
console.log('Event code stored for offline check-in');
localStorage.setItem("pending_event_code", eventCode);
localStorage.setItem(
"pending_event_code_timestamp",
Date.now().toString(),
);
// console.log('Event code stored for offline check-in');
} 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;
try {
localStorage.removeItem('pending_event_code');
localStorage.removeItem('pending_event_code_timestamp');
console.log('Event code cleared');
localStorage.removeItem("pending_event_code");
localStorage.removeItem("pending_event_code_timestamp");
// console.log('Event code cleared');
} 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
* @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;
try {
const code = localStorage.getItem('pending_event_code');
const timestamp = localStorage.getItem('pending_event_code_timestamp');
const code = localStorage.getItem("pending_event_code");
const timestamp = localStorage.getItem("pending_event_code_timestamp");
if (!code || !timestamp) return null;
return {
code,
timestamp: parseInt(timestamp)
timestamp: parseInt(timestamp),
};
} catch (error) {
console.error('Error getting stored event code:', error);
console.error("Error getting stored event code:", error);
return null;
}
}
@ -747,7 +765,7 @@ export class DataSyncService {
const table = this.getTableForCollection(Collections.EVENTS);
if (!table) {
console.error('Events table not found');
console.error("Events table not found");
return;
}
@ -755,8 +773,8 @@ export class DataSyncService {
const events = await table.toArray();
// Remove event_code from each event
const updatedEvents = events.map(event => {
if ('event_code' in event) {
const updatedEvents = events.map((event) => {
if ("event_code" in event) {
const { event_code, ...rest } = event;
return rest;
}
@ -767,9 +785,9 @@ export class DataSyncService {
await table.clear();
await table.bulkAdd(updatedEvents);
console.log('Successfully purged event codes from IndexedDB');
// console.log('Successfully purged event codes from IndexedDB');
} catch (error) {
console.error('Error purging event codes:', error);
console.error("Error purging event codes:", error);
}
}
}

View file

@ -74,7 +74,8 @@ export class DashboardDatabase extends Dexie {
// Add version 4 with files field in events table
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();
} else {
// 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;
}
}

View file

@ -1,4 +1,4 @@
import { Authentication } from '../pocketbase/Authentication';
import { Authentication } from "../pocketbase/Authentication";
/**
* Initialize authentication synchronization
@ -13,23 +13,23 @@ export async function initAuthSync(): Promise<void> {
// This will trigger the lazy loading of AuthSyncService
// through the onAuthStateChange mechanism
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) {
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 async function forceFullSync(): Promise<boolean> {
try {
const { AuthSyncService } = await import('./AuthSyncService');
const { AuthSyncService } = await import("./AuthSyncService");
const authSync = AuthSyncService.getInstance();
return await authSync.forceSyncAll();
} catch (error) {
console.error('Failed to force full sync:', error);
console.error("Failed to force full sync:", error);
return false;
}
}

View file

@ -89,7 +89,7 @@ export class Authentication {
await this.initAuthSyncService();
// Get AuthSyncService instance
const { AuthSyncService } = await import('../database/AuthSyncService');
const { AuthSyncService } = await import("../database/AuthSyncService");
const authSync = AuthSyncService.getInstance();
// Handle data cleanup before actual logout
@ -98,9 +98,9 @@ export class Authentication {
// Clear auth store
this.pb.authStore.clear();
console.log('Logout completed successfully with data cleanup');
// console.log('Logout completed successfully with data cleanup');
} catch (error) {
console.error('Error during logout:', error);
console.error("Error during logout:", error);
// Fallback to basic logout if sync fails
this.pb.authStore.clear();
}
@ -135,7 +135,10 @@ export class Authentication {
this.authChangeCallbacks.push(callback);
// Initialize AuthSyncService when first callback is registered
if (!this.authSyncServiceInitialized && this.authChangeCallbacks.length === 1) {
if (
!this.authSyncServiceInitialized &&
this.authChangeCallbacks.length === 1
) {
this.initAuthSyncService();
}
}
@ -173,23 +176,23 @@ export class Authentication {
try {
// Dynamically import AuthSyncService to avoid circular dependencies
const { AuthSyncService } = await import('../database/AuthSyncService');
const { AuthSyncService } = await import("../database/AuthSyncService");
// Initialize the service
AuthSyncService.getInstance();
this.authSyncServiceInitialized = true;
console.log('AuthSyncService initialized successfully');
// console.log('AuthSyncService initialized successfully');
// If user is already authenticated, trigger initial sync
if (this.isAuthenticated()) {
const authSync = AuthSyncService.getInstance();
authSync.handleLogin().catch(err => {
console.error('Error during initial data sync:', err);
authSync.handleLogin().catch((err) => {
console.error("Error during initial data sync:", err);
});
}
} catch (error) {
console.error('Failed to initialize AuthSyncService:', error);
console.error("Failed to initialize AuthSyncService:", error);
}
}
}

View file

@ -3,7 +3,7 @@ import { Authentication } from "./Authentication";
export class FileManager {
private auth: Authentication;
private static instance: FileManager;
private static UNSUPPORTED_EXTENSIONS = ['afdesign', 'psd', 'ai', 'sketch'];
private static UNSUPPORTED_EXTENSIONS = ["afdesign", "psd", "ai", "sketch"];
private constructor() {
this.auth = Authentication.getInstance();
@ -25,12 +25,15 @@ export class FileManager {
* @returns Object with validation result and reason if invalid
*/
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 {
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,
field: string,
file: File,
append: boolean = false
append: boolean = false,
): Promise<T> {
if (!this.auth.isAuthenticated()) {
throw new Error("User must be authenticated to upload files");
@ -64,11 +67,13 @@ export class FileManager {
// Validate file size
const maxSize = 200 * 1024 * 1024; // 200MB
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
const fileExtension = file.name.split('.').pop()?.toLowerCase();
const fileExtension = file.name.split(".").pop()?.toLowerCase();
// Validate file type
const validation = this.validateFileType(file);
@ -77,16 +82,16 @@ export class FileManager {
}
// Log upload attempt
console.log('Attempting file upload:', {
name: file.name,
size: file.size,
type: file.type,
extension: fileExtension,
collection: collectionName,
recordId: recordId,
field: field,
append: append
});
// console.log('Attempting file upload:', {
// name: file.name,
// size: file.size,
// type: file.type,
// extension: fileExtension,
// collection: collectionName,
// recordId: recordId,
// field: field,
// append: append
// });
// Create FormData for the upload
const formData = new FormData();
@ -104,20 +109,21 @@ export class FileManager {
existingFiles = existingRecord[field] || [];
}
} catch (error) {
console.warn('Could not fetch existing record:', error);
// console.warn('Could not fetch existing record:', error);
}
// Check if the file already exists
const fileExists = existingFiles.some(existingFile =>
existingFile.toLowerCase() === file.name.toLowerCase()
const fileExists = existingFiles.some(
(existingFile) =>
existingFile.toLowerCase() === file.name.toLowerCase(),
);
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 nameParts = file.name.split('.');
const nameParts = file.name.split(".");
const extension = nameParts.pop();
const baseName = nameParts.join('.');
const baseName = nameParts.join(".");
const newFileName = `${baseName}_${timestamp}.${extension}`;
// Create a new file with the modified name
@ -128,59 +134,70 @@ export class FileManager {
}
try {
const result = await pb.collection(collectionName).update<T>(recordId, formData);
console.log('Upload successful:', {
result,
fileInfo: {
name: file.name,
size: file.size,
type: file.type
},
collection: collectionName,
recordId: recordId
});
const result = await pb
.collection(collectionName)
.update<T>(recordId, formData);
// console.log('Upload successful:', {
// result,
// fileInfo: {
// name: file.name,
// size: file.size,
// type: file.type
// },
// collection: collectionName,
// recordId: recordId
// });
// Verify the file was actually added to the record
try {
const updatedRecord = await pb.collection(collectionName).getOne(recordId);
console.log('Updated record files:', {
files: updatedRecord.files,
recordId: recordId
});
const updatedRecord = await pb
.collection(collectionName)
.getOne(recordId);
// console.log('Updated record files:', {
// files: updatedRecord.files,
// recordId: recordId
// });
} catch (verifyError) {
console.warn('Could not verify file upload:', verifyError);
// console.warn('Could not verify file upload:', verifyError);
}
return result;
} catch (pbError: any) {
// Log detailed PocketBase error
console.error('PocketBase upload error:', {
status: pbError?.status,
response: pbError?.response,
data: pbError?.data,
message: pbError?.message
});
// console.error('PocketBase upload error:', {
// status: pbError?.status,
// response: pbError?.response,
// data: pbError?.data,
// message: pbError?.message
// });
// More specific error message based on file type
if (fileExtension && FileManager.UNSUPPORTED_EXTENSIONS.includes(fileExtension)) {
throw new Error(`Upload failed: File type .${fileExtension} is not supported. Please convert to PDF or image format.`);
if (
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) {
console.error(`Failed to upload file to ${collectionName}:`, {
error: err,
fileInfo: {
name: file.name,
size: file.size,
type: file.type
},
auth: {
isAuthenticated: this.auth.isAuthenticated(),
userId: this.auth.getUserId()
}
});
// console.error(`Failed to upload file to ${collectionName}:`, {
// error: err,
// fileInfo: {
// name: file.name,
// size: file.size,
// type: file.type
// },
// auth: {
// isAuthenticated: this.auth.isAuthenticated(),
// userId: this.auth.getUserId()
// }
// });
if (err instanceof Error) {
throw err;
@ -241,7 +258,7 @@ export class FileManager {
.getOne<T>(recordId);
existingFiles = (record as any)[field] || [];
} 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
}
} 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
}
@ -298,7 +315,7 @@ export class FileManager {
.getOne<T>(recordId);
return finalRecord;
} catch (err) {
console.error(`Failed to upload files to ${collectionName}:`, err);
// console.error(`Failed to upload files to ${collectionName}:`, err);
throw err;
} finally {
this.auth.setUpdating(false);
@ -324,7 +341,7 @@ export class FileManager {
const record = await pb.collection(collectionName).getOne(recordId);
existingFiles = record[field] || [];
} 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
@ -334,15 +351,15 @@ export class FileManager {
// Check if filename already exists
if (Array.isArray(existingFiles) && existingFiles.includes(file.name)) {
const timestamp = new Date().getTime();
const nameParts = file.name.split('.');
const nameParts = file.name.split(".");
const extension = nameParts.pop();
const baseName = nameParts.join('.');
const baseName = nameParts.join(".");
const newFileName = `${baseName}_${timestamp}.${extension}`;
// Create a new file with the modified name
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);
@ -350,7 +367,7 @@ export class FileManager {
// Tell PocketBase to keep existing files
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 {
@ -398,7 +415,7 @@ export class FileManager {
const formData = new FormData();
// Tell PocketBase to keep existing files
formData.append(`${field}@`, '');
formData.append(`${field}@`, "");
// Append new files, renaming if needed to avoid duplicates
for (const file of files) {
@ -407,15 +424,15 @@ export class FileManager {
// Check if filename already exists
if (existingFilenames.has(file.name)) {
const timestamp = new Date().getTime();
const nameParts = file.name.split('.');
const nameParts = file.name.split(".");
const extension = nameParts.pop();
const baseName = nameParts.join('.');
const baseName = nameParts.join(".");
const newFileName = `${baseName}_${timestamp}.${extension}`;
// Create a new file with the modified name
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);
@ -426,7 +443,7 @@ export class FileManager {
.update<T>(recordId, formData);
return result;
} catch (err) {
console.error(`Failed to append files to ${collectionName}:`, err);
// console.error(`Failed to append files to ${collectionName}:`, err);
throw err;
} finally {
this.auth.setUpdating(false);
@ -477,7 +494,7 @@ export class FileManager {
.update<T>(recordId, data);
return result;
} catch (err) {
console.error(`Failed to delete file from ${collectionName}:`, err);
// console.error(`Failed to delete file from ${collectionName}:`, err);
throw err;
} finally {
this.auth.setUpdating(false);
@ -512,7 +529,7 @@ export class FileManager {
const result = await response.blob();
return result;
} catch (err) {
console.error(`Failed to download file from ${collectionName}:`, err);
// console.error(`Failed to download file from ${collectionName}:`, err);
throw err;
} finally {
this.auth.setUpdating(false);
@ -552,7 +569,7 @@ export class FileManager {
return fileUrls;
} catch (err) {
console.error(`Failed to get files from ${collectionName}:`, err);
// console.error(`Failed to get files from ${collectionName}:`, err);
throw err;
} finally {
this.auth.setUpdating(false);
@ -643,22 +660,22 @@ export class FileManager {
public async getFileToken(): Promise<string> {
// Check authentication status
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 {
const pb = this.auth.getPocketBase();
if (pb.authStore.isValid) {
console.log(
"Auth store is valid, but auth check failed. Trying to refresh token.",
);
// console.log(
// "Auth store is valid, but auth check failed. Trying to refresh token.",
// );
await pb.collection("users").authRefresh();
console.log("Auth refreshed successfully");
// console.log("Auth refreshed successfully");
} else {
throw new Error("User must be authenticated to get a file token");
}
} 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");
}
}
@ -668,19 +685,19 @@ export class FileManager {
const pb = this.auth.getPocketBase();
// Log auth status
console.log("Auth status before getting token:", {
isValid: pb.authStore.isValid,
token: pb.authStore.token
? pb.authStore.token.substring(0, 10) + "..."
: "none",
model: pb.authStore.model ? pb.authStore.model.id : "none",
});
// console.log("Auth status before getting token:", {
// isValid: pb.authStore.isValid,
// token: pb.authStore.token
// ? pb.authStore.token.substring(0, 10) + "..."
// : "none",
// model: pb.authStore.model ? pb.authStore.model.id : "none",
// });
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;
} catch (err) {
console.error("Failed to get file token:", err);
// console.error("Failed to get file token:", err);
throw err;
} finally {
this.auth.setUpdating(false);
@ -705,25 +722,25 @@ export class FileManager {
// Check if filename is empty
if (!filename) {
console.error(
`Empty filename provided for ${collectionName}/${recordId}`,
);
// console.error(
// `Empty filename provided for ${collectionName}/${recordId}`,
// );
return "";
}
// Check if user is authenticated
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
if (useToken) {
try {
console.log(
`Getting file token for ${collectionName}/${recordId}/${filename}`,
);
// console.log(
// `Getting file token for ${collectionName}/${recordId}/${filename}`,
// );
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
const url = pb.files.getURL(
@ -731,16 +748,16 @@ export class FileManager {
filename,
{ token },
);
console.log(`Generated URL with token: ${url.substring(0, 50)}...`);
// console.log(`Generated URL with token: ${url.substring(0, 50)}...`);
return url;
} catch (error) {
console.error("Error getting file token:", error);
// console.error("Error getting file token:", error);
// Fall back to URL without token
const url = pb.files.getURL(
{ id: recordId, collectionId: collectionName },
filename,
);
console.log(`Fallback URL without token: ${url.substring(0, 50)}...`);
// console.log(`Fallback URL without token: ${url.substring(0, 50)}...`);
return url;
}
}
@ -750,7 +767,7 @@ export class FileManager {
{ id: recordId, collectionId: collectionName },
filename,
);
console.log(`Generated URL without token: ${url.substring(0, 50)}...`);
// console.log(`Generated URL without token: ${url.substring(0, 50)}...`);
return url;
}
}