diff --git a/src/lib/components/GoogleAuthButton.svelte b/src/lib/components/GoogleAuthButton.svelte index da0ca5d..b84361e 100644 --- a/src/lib/components/GoogleAuthButton.svelte +++ b/src/lib/components/GoogleAuthButton.svelte @@ -6,12 +6,14 @@ let { onSuccess, onError, + onDisconnect, disabled = false, size = 'default', variant = 'primary' } = $props<{ onSuccess?: (token: string) => void; onError?: (error: string) => void; + onDisconnect?: () => void; disabled?: boolean; size?: 'small' | 'default' | 'large'; variant?: 'primary' | 'secondary'; @@ -41,6 +43,7 @@ async function handleDisconnect() { await authManager.disconnectGoogle(); + onDisconnect?.(); } // Size classes diff --git a/src/lib/google/sheets/server.ts b/src/lib/google/sheets/server.ts index 1323fa9..331a2c6 100644 --- a/src/lib/google/sheets/server.ts +++ b/src/lib/google/sheets/server.ts @@ -51,25 +51,48 @@ export async function getRecentSpreadsheets( * Get data from a Google Sheet * @param refreshToken - Google refresh token * @param spreadsheetId - ID of the spreadsheet - * @param range - Cell range to retrieve (default: A1:Z10) + * @param range - Optional cell range. If not provided, it will fetch the entire first sheet. * @returns Sheet data as a 2D array */ export async function getSpreadsheetData( - refreshToken: string, - spreadsheetId: string, - range: string = 'A1:Z10' + refreshToken: string, + spreadsheetId: string, + range?: string ): Promise { - const oauth = getAuthenticatedClient(refreshToken); - const sheets = google.sheets({ version: 'v4', auth: oauth }); + const oauth = getAuthenticatedClient(refreshToken); + const sheets = google.sheets({ version: 'v4', auth: oauth }); - const response = await sheets.spreadsheets.values.get({ - spreadsheetId, - range - }); + let effectiveRange = range; - return { - values: response.data.values || [] - }; + // If no range is provided, get the name of the first sheet and use that as the range + // to fetch all its content. + if (!effectiveRange) { + try { + const info = await getSpreadsheetInfo(refreshToken, spreadsheetId); + const firstSheetName = info.sheets?.[0]?.properties?.title; + + if (firstSheetName) { + // To use a sheet name as a range, it must be quoted if it contains spaces or special characters. + effectiveRange = `'${firstSheetName}'`; + } else { + // Fallback if sheet name can't be determined. + effectiveRange = 'A1:Z1000'; // A sensible default for a large preview + } + } catch (error) { + console.error(`Failed to get sheet info for spreadsheet ${spreadsheetId}`, error); + // Fallback if the info call fails + effectiveRange = 'A1:Z1000'; + } + } + + const response = await sheets.spreadsheets.values.get({ + spreadsheetId, + range: effectiveRange + }); + + return { + values: response.data.values || [] + }; } /** diff --git a/src/routes/private/api/google/sheets/[sheetId]/data/+server.ts b/src/routes/private/api/google/sheets/[sheetId]/data/+server.ts index e0ca677..086bfdd 100644 --- a/src/routes/private/api/google/sheets/[sheetId]/data/+server.ts +++ b/src/routes/private/api/google/sheets/[sheetId]/data/+server.ts @@ -2,17 +2,18 @@ import { json } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; import { googleSheetsServer } from '$lib/google/sheets/server.js'; -export const GET: RequestHandler = async ({ params, request }) => { +export const GET: RequestHandler = async ({ params, request, url }) => { try { const { sheetId } = params; const authHeader = request.headers.get('authorization'); - + const range = url.searchParams.get('range') || undefined; + if (!authHeader?.startsWith('Bearer ')) { return json({ error: 'Missing or invalid authorization header' }, { status: 401 }); } const refreshToken = authHeader.slice(7); - const sheetData = await googleSheetsServer.getSpreadsheetData(refreshToken, sheetId, 'A1:Z10'); + const sheetData = await googleSheetsServer.getSpreadsheetData(refreshToken, sheetId, range); return json(sheetData); } catch (error) { diff --git a/src/routes/private/events/event/new/+page.svelte b/src/routes/private/events/event/new/+page.svelte index dcaf5df..5642b85 100644 --- a/src/routes/private/events/event/new/+page.svelte +++ b/src/routes/private/events/event/new/+page.svelte @@ -1,6 +1,5 @@ @@ -455,16 +268,9 @@
{#if currentStep === 0} { - authData.error = null; - authData.token = token; - authData.isConnected = true; - setTimeout(checkGoogleAuth, 100); - }} - onError={(error) => { - authData.error = error; - authData.isConnected = false; - }} + onSuccess={() => (isGoogleConnected = true)} + onDisconnect={() => (isGoogleConnected = false)} + onError={(err) => toast.error(err)} /> {:else if currentStep === 1} @@ -485,7 +291,7 @@ void; onError?: (error: string) => void; + onDisconnect?: () => void; }>(); @@ -15,11 +16,12 @@ To create events and import participants from Google Sheets, you need to connect your Google account.

- +
diff --git a/src/routes/private/events/event/view/+page.svelte b/src/routes/private/events/event/view/+page.svelte index 482450c..e1578ac 100644 --- a/src/routes/private/events/event/view/+page.svelte +++ b/src/routes/private/events/event/view/+page.svelte @@ -115,6 +115,8 @@ } syncingParticipants = true; + const previousCount = participants.length; // Capture count before sync + try { // Fetch sheet data const response = await fetch(`/private/api/google/sheets/${event.sheet_id}/data`, { @@ -177,16 +179,23 @@ // Reload participants await loadParticipants(); - - // Show success message with count of synced participants - const previousCount = participants.length; - const newCount = names.length; - const addedCount = Math.max(0, participants.length - previousCount); - - toast.success( - `Successfully synced participants. ${newCount} entries processed, ${addedCount} new participants added.`, - 5000 - ); + + // Show success message with accurate count of changes + const newCount = participants.length; + const diff = newCount - previousCount; + const processedCount = names.length; + + let message = `Sync complete. ${processedCount} confirmed entries processed from the sheet.`; + + if (diff > 0) { + message += ` ${diff} new participants added.`; + } else if (diff < 0) { + message += ` ${-diff} participants removed.`; + } else { + message += ` No changes to the participant list.`; + } + + toast.success(message, 6000); } catch (err) { console.error('Error syncing participants:', err); toast.error(`Failed to sync participants: ${err instanceof Error ? err.message : 'Unknown error'}`);