From 27bc2f4e70b8ba48fa4f0f85f81e33d347b2aa1c Mon Sep 17 00:00:00 2001 From: chark1es Date: Sat, 8 Mar 2025 22:23:30 -0800 Subject: [PATCH] no more console logs --- src/components/core/InView.astro | 20 +- src/components/dashboard/EventsSection.astro | 866 ++-- .../dashboard/EventsSection/EventCheckIn.tsx | 4 +- .../dashboard/EventsSection/EventLoad.tsx | 40 +- .../dashboard/Officer_EventManagement.astro | 3743 ++++++++--------- .../Officer_EventManagement/Attendees.tsx | 2 +- .../Officer_EventManagement/EventEditor.tsx | 8 +- .../dashboard/Officer_EventRequestForm.astro | 524 ++- .../EventRequestFormPreview.tsx | 16 +- .../UserEventRequests.tsx | 8 +- .../Officer_EventRequestManagement.astro | 30 +- .../EventRequestManagementTable.tsx | 18 +- .../ProfileSection/ShowProfileLogs.tsx | 62 +- .../dashboard/SettingsSection.astro | 8 - .../SettingsSection/DisplaySettings.tsx | 2 +- .../SettingsSection/NotificationSettings.tsx | 2 +- .../PasswordChangeSettings.tsx | 84 +- .../SettingsSection/ResumeSettings.tsx | 44 +- .../reimbursement/ReimbursementList.tsx | 82 +- .../ReimbursementManagementPortal.tsx | 7 +- .../dashboard/universal/FilePreview.tsx | 12 +- src/components/events/Calendar.jsx | 16 +- src/components/events/EventList.jsx | 12 +- src/pages/api/change-password.ts | 10 +- src/pages/dashboard.astro | 1575 ++++--- src/scripts/auth/RedirectHandler.ts | 16 +- src/scripts/database/AuthSyncService.ts | 38 +- src/scripts/database/DataSyncService.ts | 154 +- src/scripts/database/DexieService.ts | 9 +- src/scripts/database/initAuthSync.ts | 18 +- src/scripts/pocketbase/Authentication.ts | 41 +- src/scripts/pocketbase/FileManager.ts | 281 +- 32 files changed, 3752 insertions(+), 4000 deletions(-) diff --git a/src/components/core/InView.astro b/src/components/core/InView.astro index 535e23e..fc81906 100644 --- a/src/components/core/InView.astro +++ b/src/components/core/InView.astro @@ -1,18 +1,22 @@ - \ No newline at end of file + }, + { threshold: 0.2 }, + ); + + document + .querySelectorAll("[data-inview]") + .forEach((el) => observer.observe(el)); + diff --git a/src/components/dashboard/EventsSection.astro b/src/components/dashboard/EventsSection.astro index ac9d397..3dd4f25 100644 --- a/src/components/dashboard/EventsSection.astro +++ b/src/components/dashboard/EventsSection.astro @@ -5,151 +5,144 @@ import EventLoad from "./EventsSection/EventLoad"; ---
-
-

Events

-

- View and manage your IEEE UCSD events -

+
+

Events

+

+ View and manage your IEEE UCSD events +

+
+ +
+ +
+
-
- -
- + +
+
+
+ Coming Soon
- - -
-
-
- Coming Soon -
-
-

- Event Registration -

-
- -
- - -
-
-
+
+

+ Event Registration +

+
+ +
+ +
+
+
+
- +
- - diff --git a/src/components/dashboard/EventsSection/EventCheckIn.tsx b/src/components/dashboard/EventsSection/EventCheckIn.tsx index a588d50..69ef38e 100644 --- a/src/components/dashboard/EventsSection/EventCheckIn.tsx +++ b/src/components/dashboard/EventsSection/EventCheckIn.tsx @@ -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( @@ -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, { diff --git a/src/components/dashboard/EventsSection/EventLoad.tsx b/src/components/dashboard/EventsSection/EventLoad.tsx index 6e25136..616e228 100644 --- a/src/components/dashboard/EventsSection/EventLoad.tsx +++ b/src/components/dashboard/EventsSection/EventLoad.tsx @@ -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( 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( 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) { diff --git a/src/components/dashboard/Officer_EventManagement.astro b/src/components/dashboard/Officer_EventManagement.astro index 7ef9130..fed24df 100644 --- a/src/components/dashboard/Officer_EventManagement.astro +++ b/src/components/dashboard/Officer_EventManagement.astro @@ -14,37 +14,31 @@ const get = Get.getInstance(); const auth = Authentication.getInstance(); interface ListResponse { - page: number; - perPage: number; - totalItems: number; - totalPages: number; - items: T[]; + page: number; + perPage: number; + totalItems: number; + totalPages: number; + items: T[]; } // Initialize variables let eventResponse: ListResponse = { - page: 1, - perPage: 5, - totalItems: 0, - totalPages: 0, - items: [], + page: 1, + perPage: 5, + totalItems: 0, + totalPages: 0, + items: [], }; let upcomingEvents: Event[] = []; // Fetch events try { - if (auth.isAuthenticated()) { - eventResponse = await get.getList( - "events", - 1, - 5, - "", - "-start_date" - ); - upcomingEvents = eventResponse.items; - } + if (auth.isAuthenticated()) { + eventResponse = await get.getList("events", 1, 5, "", "-start_date"); + upcomingEvents = eventResponse.items; + } } catch (error) { - console.error("Failed to fetch events:", error); + console.error("Failed to fetch events:", error); } const totalEvents = eventResponse.totalItems; @@ -53,1066 +47,1001 @@ const currentPage = eventResponse.page; ---
-
-
-

Event Management

-

- Manage and create IEEE UCSD events -

-
+
+
+

Event Management

+

+ Manage and create IEEE UCSD events +

+
- + +
-
-
-
- Total Events -
-
- - -
-
-
- Current Academic Term -
-
-
+
+
+ Total Events
-
-
- Unique Attendees -
-
- - -
-
-
- Current Academic Term -
-
-
+ -
-
-
-
- Recurring Attendees -
-
- - -
-
-
- Current Quarter (-) -
-
-
+
+
+ Current Academic Term +
+
- -
-
-

-
-
- -
- Events List -
-
- - -
-

+
+
+ Unique Attendees +
+
+ - +
+
+
+ Current Academic Term +
+
+
+
+
+
+
+ Recurring Attendees +
+
+ - +
+
+
+ Current Quarter (-) +
+
+
+
+
-
+ +
+
+

+
+
+ +
+ Events List +
+
+ + +
+

- -
- -
-
- -
- - - - -
-
+
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
+ +
+ +
+
+ +
+ + + +
+
- -
-
-
-
- - - -
- -
+ +
+ + - -
- +
+ + +
- +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+
+
+ + + +
+ +
+
+
+
-
- - - - - -
+ Per Page
+ +
+
+ + +
+ +
+ + +
+
+ + + + + +
+
+
{ - // Reset cache timestamp to force refresh - window.lastCacheUpdate = 0; - // Refresh events list - window.fetchEvents?.(); - }} + client:load + onEventSaved={() => { + // Reset cache timestamp to force refresh + window.lastCacheUpdate = 0; + // Refresh events list + window.fetchEvents?.(); + }} /> - - - diff --git a/src/components/dashboard/Officer_EventManagement/Attendees.tsx b/src/components/dashboard/Officer_EventManagement/Attendees.tsx index d16bb9f..818d509 100644 --- a/src/components/dashboard/Officer_EventManagement/Attendees.tsx +++ b/src/components/dashboard/Officer_EventManagement/Attendees.tsx @@ -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; diff --git a/src/components/dashboard/Officer_EventManagement/EventEditor.tsx b/src/components/dashboard/Officer_EventManagement/EventEditor.tsx index 6a6752b..9c25e60 100644 --- a/src/components/dashboard/Officer_EventManagement/EventEditor.tsx +++ b/src/components/dashboard/Officer_EventManagement/EventEditor.tsx @@ -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()); diff --git a/src/components/dashboard/Officer_EventRequestForm.astro b/src/components/dashboard/Officer_EventRequestForm.astro index 2e5d7f0..399507a 100644 --- a/src/components/dashboard/Officer_EventRequestForm.astro +++ b/src/components/dashboard/Officer_EventRequestForm.astro @@ -25,313 +25,295 @@ let error: string | null = null; // This provides initial data for server-side rendering // Client-side will use IndexedDB for data management if (auth.isAuthenticated()) { - try { - const userId = auth.getUserId(); - if (userId) { - userEventRequests = await get.getAll( - Collections.EVENT_REQUESTS, - `requested_user="${userId}"`, - "-created" - ); - } - } catch (err) { - console.error("Failed to fetch user event requests:", err); - error = "Failed to load your event requests. Please try again later."; + try { + const userId = auth.getUserId(); + if (userId) { + userEventRequests = await get.getAll( + Collections.EVENT_REQUESTS, + `requested_user="${userId}"`, + "-created", + ); } + } catch (err) { + console.error("Failed to fetch user event requests:", err); + error = "Failed to load your event requests. Please try again later."; + } } ---
-
-

Event Request Form

-

- Submit your event request at least 6 weeks before your event. After - submitting, please notify PR and/or Coordinators in the #-events - Slack channel. -

-
-

This form includes sections for:

-
    -
  • PR Materials (if needed)
  • -
  • Event Details
  • -
  • TAP Form Information
  • -
  • AS Funding (if needed)
  • -
-

- Your progress is automatically saved as you fill out the form. -

-
+
+

Event Request Form

+

+ Submit your event request at least 6 weeks before your event. After + submitting, please notify PR and/or Coordinators in the #-events Slack + channel. +

+
+

This form includes sections for:

+
    +
  • PR Materials (if needed)
  • +
  • Event Details
  • +
  • TAP Form Information
  • +
  • AS Funding (if needed)
  • +
+

+ Your progress is automatically saved as you fill out the form. +

+
- -
- Submit Event Request - View Your Submissions + + + + +
+
+
+
- -
-
- -
-
- - - diff --git a/src/components/dashboard/Officer_EventRequestForm/EventRequestFormPreview.tsx b/src/components/dashboard/Officer_EventRequestForm/EventRequestFormPreview.tsx index e357b29..6bf17af 100644 --- a/src/components/dashboard/Officer_EventRequestForm/EventRequestFormPreview.tsx +++ b/src/components/dashboard/Officer_EventRequestForm/EventRequestFormPreview.tsx @@ -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 = ({ 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); diff --git a/src/components/dashboard/Officer_EventRequestForm/UserEventRequests.tsx b/src/components/dashboard/Officer_EventRequestForm/UserEventRequests.tsx index 380b96c..8269acb 100644 --- a/src/components/dashboard/Officer_EventRequestForm/UserEventRequests.tsx +++ b/src/components/dashboard/Officer_EventRequestForm/UserEventRequests.tsx @@ -69,7 +69,7 @@ const UserEventRequests: React.FC = ({ 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 = ({ 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); diff --git a/src/components/dashboard/Officer_EventRequestManagement.astro b/src/components/dashboard/Officer_EventRequestManagement.astro index 85576ab..72f6c9d 100644 --- a/src/components/dashboard/Officer_EventRequestManagement.astro +++ b/src/components/dashboard/Officer_EventRequestManagement.astro @@ -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(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", + // ); } }); diff --git a/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx b/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx index fc9d852..96c4fda 100644 --- a/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx +++ b/src/components/dashboard/Officer_EventRequestManagement/EventRequestManagementTable.tsx @@ -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( @@ -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(); }; diff --git a/src/components/dashboard/ProfileSection/ShowProfileLogs.tsx b/src/components/dashboard/ProfileSection/ShowProfileLogs.tsx index 27ba406..8aed4e9 100644 --- a/src/components/dashboard/ProfileSection/ShowProfileLogs.tsx +++ b/src/components/dashboard/ProfileSection/ShowProfileLogs.tsx @@ -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(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); } }} > diff --git a/src/components/dashboard/SettingsSection.astro b/src/components/dashboard/SettingsSection.astro index a6770ec..750f6df 100644 --- a/src/components/dashboard/SettingsSection.astro +++ b/src/components/dashboard/SettingsSection.astro @@ -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"; diff --git a/src/components/dashboard/SettingsSection/DisplaySettings.tsx b/src/components/dashboard/SettingsSection/DisplaySettings.tsx index 113ca71..1085b77 100644 --- a/src/components/dashboard/SettingsSection/DisplaySettings.tsx +++ b/src/components/dashboard/SettingsSection/DisplaySettings.tsx @@ -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); diff --git a/src/components/dashboard/SettingsSection/NotificationSettings.tsx b/src/components/dashboard/SettingsSection/NotificationSettings.tsx index 44db6a1..241b042 100644 --- a/src/components/dashboard/SettingsSection/NotificationSettings.tsx +++ b/src/components/dashboard/SettingsSection/NotificationSettings.tsx @@ -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); } diff --git a/src/components/dashboard/SettingsSection/PasswordChangeSettings.tsx b/src/components/dashboard/SettingsSection/PasswordChangeSettings.tsx index d8857ec..9deb4f3 100644 --- a/src/components/dashboard/SettingsSection/PasswordChangeSettings.tsx +++ b/src/components/dashboard/SettingsSection/PasswordChangeSettings.tsx @@ -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"); }} diff --git a/src/components/dashboard/SettingsSection/ResumeSettings.tsx b/src/components/dashboard/SettingsSection/ResumeSettings.tsx index b14e252..6769619 100644 --- a/src/components/dashboard/SettingsSection/ResumeSettings.tsx +++ b/src/components/dashboard/SettingsSection/ResumeSettings.tsx @@ -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( @@ -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(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( @@ -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(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(); diff --git a/src/components/dashboard/reimbursement/ReimbursementList.tsx b/src/components/dashboard/reimbursement/ReimbursementList.tsx index 5654ab8..12b4618 100644 --- a/src/components/dashboard/reimbursement/ReimbursementList.tsx +++ b/src/components/dashboard/reimbursement/ReimbursementList.tsx @@ -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 ( @@ -482,7 +482,7 @@ export default function ReimbursementList() { > {requests.map((request, index) => { - console.log('Rendering request:', request); + // console.log('Rendering request:', request); return ( ('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) { diff --git a/src/components/dashboard/universal/FilePreview.tsx b/src/components/dashboard/universal/FilePreview.tsx index 4a34941..2242865 100644 --- a/src/components/dashboard/universal/FilePreview.tsx +++ b/src/components/dashboard/universal/FilePreview.tsx @@ -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' + // ); } }; diff --git a/src/components/events/Calendar.jsx b/src/components/events/Calendar.jsx index ae07c46..0826764 100644 --- a/src/components/events/Calendar.jsx +++ b/src/components/events/Calendar.jsx @@ -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); diff --git a/src/components/events/EventList.jsx b/src/components/events/EventList.jsx index a842970..5e11de4 100644 --- a/src/components/events/EventList.jsx +++ b/src/components/events/EventList.jsx @@ -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); diff --git a/src/pages/api/change-password.ts b/src/pages/api/change-password.ts index 9de557b..8e8dd7c 100644 --- a/src/pages/api/change-password.ts +++ b/src/pages/api/change-password.ts @@ -11,8 +11,6 @@ async function getLogtoAccessToken( scope: string = "all", ): Promise { 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 { 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`, { diff --git a/src/pages/dashboard.astro b/src/pages/dashboard.astro index 68ac770..011e7fe 100644 --- a/src/pages/dashboard.astro +++ b/src/pages/dashboard.astro @@ -19,873 +19,770 @@ const dashboardConfig = yaml.load(fs.readFileSync(configPath, "utf8")) as any; // Dynamically import all dashboard components const components = Object.fromEntries( - await Promise.all( - Object.values(dashboardConfig.sections) - .filter((section: any) => section.component) // Only process sections with components - .map(async (section: any) => { - const component = await import( - `../components/dashboard/${section.component}.astro` - ); - console.log(`Loaded component: ${section.component}`); // Debug log - return [section.component, component.default]; - }) - ) + await Promise.all( + Object.values(dashboardConfig.sections) + .filter((section: any) => section.component) // Only process sections with components + .map(async (section: any) => { + const component = await import( + `../components/dashboard/${section.component}.astro` + ); + // 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 --- - - - - {title} | IEEE UCSD - - - - -
- -
- - + +
+ +
+
+
+
+
+
+
+
+
+
- - + + // 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"); + overlay?.remove(); + } + }); + }); + }; + + // Display user profile information and handle role-based access + const updateUserProfile = async (user: { id: string }) => { + if (!user) return; + + try { + // Use fields from the User interface in the schema + const extendedUser = await get.getOne("users", user.id, { + fields: [ + "id", + "name", + "email", + "verified", + "avatar", + "pid", + "member_id", + "graduation_year", + "major", + ], + }); + + const displayName = extendedUser.name || "Unknown User"; + // Default role is Member + let displayRole = "Member"; + + // Map the officer type from the database to our OfficerStatus type + let officerStatus: OfficerStatus = ""; + + // Get the officer record for this user if it exists + // Use fields from the Officer interface in the schema + const officerRecords = await get.getList( + "officers", + 1, + 50, + `user="${user.id}"`, + "", + { + fields: ["id", "type", "role"], + }, + ); + + if (officerRecords && officerRecords.items.length > 0) { + const officerType = officerRecords.items[0].type; + const officerRole = officerRecords.items[0].role; + + // Use the role field from the officer's collection + if (officerRole) { + displayRole = officerRole; + } + + // Map the officer type to our OfficerStatus + switch (officerType) { + case OfficerTypes.ADMINISTRATOR: + officerStatus = "administrator"; + break; + case OfficerTypes.EXECUTIVE: + officerStatus = "executive"; + break; + case OfficerTypes.GENERAL: + officerStatus = "general"; + break; + case OfficerTypes.HONORARY: + officerStatus = "honorary"; + break; + case OfficerTypes.PAST: + officerStatus = "past"; + break; + default: + officerStatus = "none"; + } + } else { + // Check if user is a sponsor by querying the sponsors collection + const sponsorRecords = await get.getList( + "sponsors", + 1, + 1, + `user="${user.id}"`, + "", + { + fields: ["id", "company"], + }, + ); + + if (sponsorRecords && sponsorRecords.items.length > 0) { + officerStatus = "sponsor"; + displayRole = "Sponsor"; + } else { + officerStatus = "none"; + } + } + + const initials = (extendedUser.name || "U") + .split(" ") + .map((n: string) => n[0]) + .join("") + .toUpperCase(); + + // Update profile display + if (userName) userName.textContent = displayName; + if (userRole) userRole.textContent = displayRole; + if (userInitials) userInitials.textContent = initials; + + // Update section visibility based on role + updateSectionVisibility(officerStatus); + } catch (error) { + console.error("Error fetching user profile:", error); + const fallbackValues = { + name: "Unknown User", + role: "Member", + initials: "?", + }; + + if (userName) userName.textContent = fallbackValues.name; + if (userRole) userRole.textContent = fallbackValues.role; + if (userInitials) userInitials.textContent = fallbackValues.initials; + + updateSectionVisibility("" as OfficerStatus); + } + }; + + // Mobile sidebar toggle + const mobileSidebarToggle = document.getElementById( + "mobileSidebarToggle", + ); + if (mobileSidebarToggle && sidebar) { + const toggleSidebar = () => { + 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"); + overlay?.remove(); + } else { + sidebar.classList.remove("-translate-x-full"); + document.body.classList.add("overflow-hidden"); + const overlay = document.createElement("div"); + overlay.id = "sidebarOverlay"; + overlay.className = + "fixed inset-0 bg-black bg-opacity-50 z-40 xl:hidden"; + overlay.addEventListener("click", toggleSidebar); + document.body.appendChild(overlay); + } + }; + + mobileSidebarToggle.addEventListener("click", toggleSidebar); + } + + // Function to initialize the page + const initializePage = async () => { + try { + // Initialize auth sync for IndexedDB + await initAuthSync(); + + // Check if user is authenticated + if (!auth.isAuthenticated()) { + // 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 (pageErrorState) pageErrorState.classList.add("hidden"); + if (notAuthenticatedState) + notAuthenticatedState.classList.add("hidden"); + + // Show loading states + const userProfileSkeleton = document.getElementById( + "userProfileSkeleton", + ); + const userProfileSignedOut = document.getElementById( + "userProfileSignedOut", + ); + const userProfileSummary = + document.getElementById("userProfileSummary"); + const menuLoadingSkeleton = document.getElementById( + "menuLoadingSkeleton", + ); + const actualMenu = document.getElementById("actualMenu"); + + if (userProfileSkeleton) + userProfileSkeleton.classList.remove("hidden"); + if (userProfileSummary) userProfileSummary.classList.add("hidden"); + if (userProfileSignedOut) + userProfileSignedOut.classList.add("hidden"); + if (menuLoadingSkeleton) + menuLoadingSkeleton.classList.remove("hidden"); + if (actualMenu) actualMenu.classList.add("hidden"); + + const user = auth.getCurrentUser(); + await updateUserProfile(user); + + // Show actual profile and hide skeleton + if (userProfileSkeleton) userProfileSkeleton.classList.add("hidden"); + if (userProfileSummary) userProfileSummary.classList.remove("hidden"); + + // Hide all sections first + document.querySelectorAll(".dashboard-section").forEach((section) => { + section.classList.add("hidden"); + }); + + // Show appropriate default section based on role + // Get the officer record for this user if it exists + let officerStatus: OfficerStatus = "none"; + + try { + const officerRecords = await get.getList( + "officers", + 1, + 50, + `user="${user.id}"`, + "", + { + fields: ["id", "type", "role"], + }, + ); + + if (officerRecords && officerRecords.items.length > 0) { + const officerType = officerRecords.items[0].type; + // We can also get the role here if needed for display elsewhere + const officerRole = officerRecords.items[0].role; + + // Map the officer type to our OfficerStatus + switch (officerType) { + case OfficerTypes.ADMINISTRATOR: + officerStatus = "administrator"; + break; + case OfficerTypes.EXECUTIVE: + officerStatus = "executive"; + break; + case OfficerTypes.GENERAL: + officerStatus = "general"; + break; + case OfficerTypes.HONORARY: + officerStatus = "honorary"; + break; + case OfficerTypes.PAST: + officerStatus = "past"; + break; + default: + officerStatus = "none"; + } + } else { + // Check if user is a sponsor by querying the sponsors collection + const sponsorRecords = await get.getList( + "sponsors", + 1, + 1, + `user="${user.id}"`, + "", + { + fields: ["id", "company"], + }, + ); + + if (sponsorRecords && sponsorRecords.items.length > 0) { + officerStatus = "sponsor"; + } else { + officerStatus = "none"; + } + } + } catch (error) { + console.error("Error determining officer status:", error); + officerStatus = "none"; + } + + let defaultSection; + let defaultButton; + + // Set default section based on role + // Only sponsors get a different default view + if (officerStatus === "sponsor") { + // For sponsors, show the sponsor dashboard + defaultSection = document.getElementById("sponsorDashboardSection"); + defaultButton = document.querySelector( + '[data-section="sponsorDashboard"]', + ); + } else { + // For all other users (including administrators), show the profile section + 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}`); + } + + if (defaultSection) { + defaultSection.classList.remove("hidden"); + } + if (defaultButton) { + defaultButton.classList.add("active", "bg-base-200"); + } + + // Initialize navigation + handleNavigation(); + + // Show actual menu and hide skeleton + 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"); + } catch (error) { + console.error("Error initializing dashboard:", error); + if (pageLoadingState) pageLoadingState.classList.add("hidden"); + if (pageErrorState) pageErrorState.classList.remove("hidden"); + } + }; + + // Initialize when DOM is loaded + document.addEventListener("DOMContentLoaded", initializePage); + + // Handle login button click + document + .querySelector(".login-button") + ?.addEventListener("click", async () => { + try { + 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"); + } + }); + + // Handle logout button click + document.getElementById("logoutButton")?.addEventListener("click", () => { + auth.logout(); + window.location.reload(); + }); + + // Handle responsive sidebar + if (sidebar) { + if (window.innerWidth < 1024) { + sidebar.classList.add("-translate-x-full"); + } + + window.addEventListener("resize", () => { + if (window.innerWidth >= 1024) { + const overlay = document.getElementById("sidebarOverlay"); + if (overlay) { + overlay.remove(); + document.body.classList.remove("overflow-hidden"); + } + sidebar.classList.remove("-translate-x-full"); + } + }); + } + + diff --git a/src/scripts/auth/RedirectHandler.ts b/src/scripts/auth/RedirectHandler.ts index a387e31..ec71d3a 100644 --- a/src/scripts/auth/RedirectHandler.ts +++ b/src/scripts/auth/RedirectHandler.ts @@ -60,7 +60,7 @@ export class RedirectHandler { { emailVisibility: false }, ); - console.log("Auth successful:", authData); + // console.log("Auth successful:", authData); this.contentEl.innerHTML = `

Authentication Successful!

Initializing your data...

@@ -99,19 +99,15 @@ export class RedirectHandler { private async initializeDataSync(): Promise { 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 } } diff --git a/src/scripts/database/AuthSyncService.ts b/src/scripts/database/AuthSyncService.ts index 20c5862..2375cd1 100644 --- a/src/scripts/database/AuthSyncService.ts +++ b/src/scripts/database/AuthSyncService.ts @@ -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 { 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; } diff --git a/src/scripts/database/DataSyncService.ts b/src/scripts/database/DataSyncService.ts index 1435ec2..5e59b54 100644 --- a/src/scripts/database/DataSyncService.ts +++ b/src/scripts/database/DataSyncService.ts @@ -83,7 +83,7 @@ export class DataSyncService { private async handleOnline(): Promise { 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 { // 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(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) && - (localItem as any).files.length > 0 && - (!('files' in serverItem) || !(serverItem as any).files.length)) { - console.log(`Preserving local files for event ${localItem.id}`); + 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}`); (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,17 +545,22 @@ 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; } - + await table.put(pbItem); item = pbItem; } else { @@ -587,21 +599,21 @@ 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)) { (data as any).files = []; } - + // 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; } } @@ -745,31 +763,31 @@ export class DataSyncService { try { const db = this.dexieService.getDB(); const table = this.getTableForCollection(Collections.EVENTS); - + if (!table) { - console.error('Events table not found'); + console.error("Events table not found"); return; } - + // Get all events 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; } return event; }); - + // Clear the table and add the updated events 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); } } } diff --git a/src/scripts/database/DexieService.ts b/src/scripts/database/DexieService.ts index 030f086..bde5197 100644 --- a/src/scripts/database/DexieService.ts +++ b/src/scripts/database/DexieService.ts @@ -65,16 +65,17 @@ export class DashboardDatabase extends Dexie { offlineChanges: "id, collection, recordId, operation, timestamp, synced, syncAttempts", }); - + // Add version 3 with eventAttendees table and updated events table (no attendees field) this.version(3).stores({ events: "id, event_name, event_code, start_date, end_date, published", eventAttendees: "id, user, event, time_checked_in", }); - + // 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; } } diff --git a/src/scripts/database/initAuthSync.ts b/src/scripts/database/initAuthSync.ts index b48ea9e..26e8416 100644 --- a/src/scripts/database/initAuthSync.ts +++ b/src/scripts/database/initAuthSync.ts @@ -1,4 +1,4 @@ -import { Authentication } from '../pocketbase/Authentication'; +import { Authentication } from "../pocketbase/Authentication"; /** * Initialize authentication synchronization @@ -9,27 +9,27 @@ export async function initAuthSync(): Promise { try { // Get Authentication instance const auth = Authentication.getInstance(); - + // 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 { 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; } -} \ No newline at end of file +} diff --git a/src/scripts/pocketbase/Authentication.ts b/src/scripts/pocketbase/Authentication.ts index 586cc50..fdeb571 100644 --- a/src/scripts/pocketbase/Authentication.ts +++ b/src/scripts/pocketbase/Authentication.ts @@ -87,20 +87,20 @@ export class Authentication { try { // Initialize AuthSyncService if needed (lazy loading) 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 await authSync.handleLogout(); - + // 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(); } @@ -133,9 +133,12 @@ export class Authentication { */ public onAuthStateChange(callback: (isValid: boolean) => void): void { 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(); } } @@ -164,32 +167,32 @@ export class Authentication { const isValid = this.pb.authStore.isValid; this.authChangeCallbacks.forEach((callback) => callback(isValid)); } - + /** * Initialize the AuthSyncService (lazy loading) */ private async initAuthSyncService(): Promise { if (this.authSyncServiceInitialized) return; - + 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); } } } diff --git a/src/scripts/pocketbase/FileManager.ts b/src/scripts/pocketbase/FileManager.ts index 7ac8336..fb50654 100644 --- a/src/scripts/pocketbase/FileManager.ts +++ b/src/scripts/pocketbase/FileManager.ts @@ -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,15 +25,18 @@ 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(); - - if (fileExtension && FileManager.UNSUPPORTED_EXTENSIONS.includes(fileExtension)) { - return { - valid: false, - reason: `File type .${fileExtension} is not supported. Please convert to PDF or image format.` + const fileExtension = file.name.split(".").pop()?.toLowerCase(); + + if ( + fileExtension && + FileManager.UNSUPPORTED_EXTENSIONS.includes(fileExtension) + ) { + return { + valid: false, + reason: `File type .${fileExtension} is not supported. Please convert to PDF or image format.`, }; } - + return { valid: true }; } @@ -51,7 +54,7 @@ export class FileManager { recordId: string, field: string, file: File, - append: boolean = false + append: boolean = false, ): Promise { if (!this.auth.isAuthenticated()) { throw new Error("User must be authenticated to upload files"); @@ -60,16 +63,18 @@ export class FileManager { try { this.auth.setUpdating(true); const pb = this.auth.getPocketBase(); - + // 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); if (!validation.valid) { @@ -77,49 +82,50 @@ 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(); - + // Use the + prefix for the field name if append is true const fieldName = append ? `${field}+` : field; - + // Get existing record to preserve existing files let existingRecord: any = null; let existingFiles: string[] = []; - + try { if (recordId) { existingRecord = await pb.collection(collectionName).getOne(recordId); 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 const newFile = new File([file], newFileName, { type: file.type }); formData.append(fieldName, newFile); @@ -128,60 +134,71 @@ export class FileManager { } try { - const result = await pb.collection(collectionName).update(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(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; } @@ -224,7 +241,7 @@ export class FileManager { `File ${file.name} is too large. Maximum size is 50MB.`, ); } - + // Validate file type const validation = this.validateFileType(file); if (!validation.valid) { @@ -241,7 +258,7 @@ export class FileManager { .getOne(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(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,33 +341,33 @@ 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 for (const file of files) { let fileToUpload = file; - + // 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); } - + // 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 { @@ -396,28 +413,28 @@ export class FileManager { // Create FormData for the new files only 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) { let fileToUpload = file; - + // 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(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(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 { // 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; } }