diff --git a/src/routes/private/events/event/new/+page.server.ts b/src/routes/private/events/event/new/+page.server.ts
deleted file mode 100644
index 036c394..0000000
--- a/src/routes/private/events/event/new/+page.server.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export const load = async ({ locals }: { locals: any }) => {
- const { session } = await locals.safeGetSession();
-
- return {
- session
- };
-};
diff --git a/src/routes/private/events/event/new/+page.svelte b/src/routes/private/events/event/new/+page.svelte
index bad1c12..5f20ee6 100644
--- a/src/routes/private/events/event/new/+page.svelte
+++ b/src/routes/private/events/event/new/+page.svelte
@@ -2,6 +2,15 @@
import { onMount } from 'svelte';
import type { GoogleSheet } from '$lib/sheets.js';
import { isTokenValid, refreshAccessToken } from '$lib/google.js';
+ import { goto } from '$app/navigation';
+
+ // Import Components
+ import GoogleAuthStep from './components/GoogleAuthStep.svelte';
+ import EventDetailsStep from './components/EventDetailsStep.svelte';
+ import GoogleSheetsStep from './components/GoogleSheetsStep.svelte';
+ import EmailSettingsStep from './components/EmailSettingsStep.svelte';
+ import StepNavigator from './components/StepNavigator.svelte';
+ import StepNavigation from './components/StepNavigation.svelte';
let { data } = $props();
@@ -16,7 +25,8 @@
connecting: false,
showCancelOption: false,
token: null as string | null,
- error: null as string | null
+ error: null as string | null,
+ userEmail: null as string | null
});
// Step 1: Event Details
@@ -71,13 +81,20 @@
const isValid = await isTokenValid(accessToken);
authData.isConnected = isValid;
authData.token = accessToken;
+
+ if (isValid) {
+ // Fetch user info
+ await fetchUserInfo(accessToken);
+ }
} else {
authData.isConnected = false;
+ authData.userEmail = null;
}
} catch (error) {
console.error('Error checking Google auth:', error);
authData.isConnected = false;
authData.error = 'Error checking Google connection';
+ authData.userEmail = null;
} finally {
authData.checking = false;
}
@@ -170,6 +187,59 @@
authData.connecting = false;
authData.showCancelOption = false;
}
+
+ async function fetchUserInfo(accessToken: string) {
+ try {
+ const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
+ headers: {
+ Authorization: `Bearer ${accessToken}`
+ }
+ });
+
+ if (response.ok) {
+ const userData = await response.json();
+ authData.userEmail = userData.email;
+ } else {
+ console.error('Failed to fetch user info:', await response.text());
+ authData.userEmail = null;
+ }
+ } catch (error) {
+ console.error('Error fetching user info:', error);
+ authData.userEmail = null;
+ }
+ }
+
+ async function disconnectGoogle() {
+ try {
+ // First revoke the token at Google
+ const accessToken = localStorage.getItem('google_access_token');
+ if (accessToken) {
+ await fetch(`https://accounts.google.com/o/oauth2/revoke?token=${accessToken}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ }
+ });
+ }
+
+ // Remove tokens from local storage
+ localStorage.removeItem('google_access_token');
+ localStorage.removeItem('google_refresh_token');
+
+ // Update auth state
+ authData.isConnected = false;
+ authData.token = null;
+ authData.userEmail = null;
+
+ // Clear any selected sheets data
+ sheetsData.availableSheets = [];
+ sheetsData.selectedSheet = null;
+ sheetsData.sheetData = [];
+ } catch (error) {
+ console.error('Error disconnecting from Google:', error);
+ authData.error = 'Failed to disconnect from Google';
+ }
+ }
// Step navigation
function nextStep() {
@@ -300,7 +370,6 @@
loading = true;
try {
- // TODO: Replace with actual Supabase function call
const { error } = await data.supabase.rpc('create_event', {
p_name: eventData.name,
p_date: eventData.date,
@@ -316,7 +385,7 @@
if (error) throw error;
// Redirect to events list or show success message
- window.location.href = '/private/events';
+ goto('/private/events');
} catch (error) {
console.error('Error creating event:', error);
errors.submit = 'Failed to create event. Please try again.';
@@ -336,423 +405,22 @@
if (currentStep === 3) return emailData.subject && emailData.body;
return false;
});
-
- let stepTitle = $derived(() => {
- if (currentStep === 0) return 'Connect Google Account';
- if (currentStep === 1) return 'Event Details';
- if (currentStep === 2) return 'Connect Google Sheets';
- if (currentStep === 3) return 'Email Settings';
- return '';
- });
-
-
Create New Event
-
- {#each Array(totalSteps) as _, index}
-
-
- {index + 1}
-
- {#if index < totalSteps - 1}
-
- {/if}
-
- {/each}
-
-
Step {currentStep + 1} of {totalSteps}: {stepTitle}
-
+
{#if currentStep === 0}
-
-
-
-
Connect Your Google Account
-
- To create events and import participants from Google Sheets, you need to connect your Google account.
-
-
- {#if authData.checking}
-
-
-
Checking connection...
-
- {:else if authData.isConnected}
-
-
-
-
-
- Google account connected successfully!
-
-
- You can now access Google Sheets and Gmail features.
-
-
-
-
- {:else}
-
-
-
-
-
- Google account not connected
-
-
- Please connect your Google account to continue with event creation.
-
-
-
-
-
-
-
- {#if authData.connecting}
-
- Connecting...
- {:else}
-
-
-
-
-
-
- Connect to Google
- {/if}
-
-
- {#if authData.connecting && authData.showCancelOption}
-
- Cancel connection
-
-
- Taking too long? You can cancel and try again.
-
- {/if}
-
- {/if}
-
- {#if authData.error}
-
-
-
-
-
- Connection Error
-
-
- {authData.error}
-
-
-
-
- {/if}
-
- {#if errors.auth}
-
{errors.auth}
- {/if}
-
-
-
+
{:else if currentStep === 1}
-
-
-
-
- Event Name *
-
-
- {#if errors.name}
-
{errors.name}
- {/if}
-
-
-
-
- Event Date *
-
-
- {#if errors.date}
-
{errors.date}
- {/if}
-
-
-
+
{:else if currentStep === 2}
-
-
-
-
Select Google Sheet
-
- {#if sheetsData.loading && sheetsData.availableSheets.length === 0}
-
- {#each Array(5) as _}
-
- {/each}
-
- {:else if sheetsData.availableSheets.length === 0}
-
-
No Google Sheets found.
-
- Refresh
-
-
- {:else}
-
- {#if !sheetsData.expandedSheetList && sheetsData.selectedSheet}
-
-
-
-
{sheetsData.selectedSheet.name}
-
- Modified: {new Date(sheetsData.selectedSheet.modifiedTime).toLocaleDateString()}
-
-
-
- Change
-
-
-
-
-
- {:else}
-
-
-
Available Sheets
- {#if sheetsData.selectedSheet}
-
- Collapse list
-
- {/if}
-
-
- {#each sheetsData.availableSheets as sheet}
-
selectSheet(sheet)}
- class="p-4 text-left border border-gray-200 rounded hover:border-blue-500 transition {
- sheetsData.selectedSheet?.id === sheet.id ? 'border-blue-500 bg-blue-50' : ''
- }"
- >
- {sheet.name}
-
- Modified: {new Date(sheet.modifiedTime).toLocaleDateString()}
-
-
- {/each}
-
- {/if}
-
- {/if}
-
- {#if errors.sheet}
-
{errors.sheet}
- {/if}
-
-
- {#if sheetsData.selectedSheet && sheetsData.sheetData.length > 0}
-
-
Column Mapping
-
-
-
-
Column Mapping Instructions:
-
- Select what each column represents by using the dropdown in each column header.
- Make sure to assign Name, Surname, Email, and Confirmation columns.
-
-
-
-
-
-
-
- {#each sheetsData.sheetData[0] || [] as header, index}
-
-
-
- Column {index + 1}
- ({header || 'Empty'})
-
-
e.stopPropagation()}
- onchange={(e) => {
- const value = e.target.value;
- if (value === "none") return;
-
- // Reset previous selection if this column was already mapped
- if (sheetsData.columnMapping.name === index + 1) sheetsData.columnMapping.name = 0;
- if (sheetsData.columnMapping.surname === index + 1) sheetsData.columnMapping.surname = 0;
- if (sheetsData.columnMapping.email === index + 1) sheetsData.columnMapping.email = 0;
- if (sheetsData.columnMapping.confirmation === index + 1) sheetsData.columnMapping.confirmation = 0;
-
- // Set new mapping
- if (value === "name") sheetsData.columnMapping.name = index + 1;
- else if (value === "surname") sheetsData.columnMapping.surname = index + 1;
- else if (value === "email") sheetsData.columnMapping.email = index + 1;
- else if (value === "confirmation") sheetsData.columnMapping.confirmation = index + 1;
- }}
- >
- Select data type
- Name
- Surname
- Email
- Confirmation
-
- {#if sheetsData.columnMapping.name === index + 1}
-
Name Column
- {:else if sheetsData.columnMapping.surname === index + 1}
-
Surname Column
- {:else if sheetsData.columnMapping.email === index + 1}
-
Email Column
- {:else if sheetsData.columnMapping.confirmation === index + 1}
-
Confirmation Column
- {/if}
-
-
- {/each}
-
-
-
- {#each sheetsData.sheetData.slice(0, 10) as row, rowIndex}
-
- {#each row as cell, cellIndex}
-
-
- {cell || ''}
-
-
- {/each}
-
- {/each}
-
-
-
-
Showing first 10 rows
-
- {/if}
-
- {#if sheetsData.loading && sheetsData.selectedSheet}
-
-
Loading sheet data...
-
- {/if}
-
- {#if errors.sheetData}
-
{errors.sheetData}
- {/if}
-
-
+
{:else if currentStep === 3}
-
-
-
-
- Email Subject *
-
-
- {#if errors.subject}
-
{errors.subject}
- {/if}
-
-
-
-
- Email Body *
-
-
- {#if errors.body}
-
{errors.body}
- {/if}
-
-
-
-
-
Preview
-
-
Subject: {emailData.subject || 'No subject'}
-
{emailData.body || 'No content'}
-
-
-
+
{/if}
{#if errors.submit}
@@ -763,33 +431,13 @@
-
-
- Previous
-
-
-
- {#if currentStep < totalSteps - 1}
-
- Next
-
- {:else}
-
- {loading ? 'Creating...' : 'Create Event'}
-
- {/if}
-
-
+
diff --git a/src/routes/private/events/event/new/components/EmailSettingsStep.svelte b/src/routes/private/events/event/new/components/EmailSettingsStep.svelte
new file mode 100644
index 0000000..560d9a5
--- /dev/null
+++ b/src/routes/private/events/event/new/components/EmailSettingsStep.svelte
@@ -0,0 +1,43 @@
+
+
+
+
+
+ Email Subject *
+
+
+ {#if errors.subject}
+
{errors.subject}
+ {/if}
+
+
+
+
+ Email Body *
+
+
+ {#if errors.body}
+
{errors.body}
+ {/if}
+
+
diff --git a/src/routes/private/events/event/new/components/EventDetailsStep.svelte b/src/routes/private/events/event/new/components/EventDetailsStep.svelte
new file mode 100644
index 0000000..3868340
--- /dev/null
+++ b/src/routes/private/events/event/new/components/EventDetailsStep.svelte
@@ -0,0 +1,44 @@
+
+
+
+
+
Event details
+
+
+ Event Name *
+
+
+ {#if errors.name}
+
{errors.name}
+ {/if}
+
+
+
+
+ Event Date *
+
+
+ {#if errors.date}
+
{errors.date}
+ {/if}
+
+
diff --git a/src/routes/private/events/event/new/components/GoogleAuthStep.svelte b/src/routes/private/events/event/new/components/GoogleAuthStep.svelte
new file mode 100644
index 0000000..a3f469f
--- /dev/null
+++ b/src/routes/private/events/event/new/components/GoogleAuthStep.svelte
@@ -0,0 +1,144 @@
+
+
+
+
+
Connect Your Google Account
+
+ To create events and import participants from Google Sheets, you need to connect your Google account.
+
+
+ {#if authData.checking}
+
+
+
Checking connection...
+
+ {:else if authData.isConnected}
+
+
+
+
+ Google account connected successfully!
+
+ {#if authData.userEmail}
+
+
+ {authData.userEmail}
+
+
+ {/if}
+
+ You can now access Google Sheets and Gmail features.
+
+
+
+
+
+
+ {:else}
+
+
+
+
+
+ Google account not connected
+
+
+ Please connect your Google account to continue with event creation.
+
+
+
+
+
+
+
+ {#if authData.connecting}
+
+ Connecting...
+ {:else}
+
+
+
+
+
+
+ Connect to Google
+ {/if}
+
+
+ {#if authData.connecting && authData.showCancelOption}
+
+ Cancel connection
+
+
+ Taking too long? You can cancel and try again.
+
+ {/if}
+
+ {/if}
+
+ {#if authData.error}
+
+
+
+
+
+ Connection Error
+
+
+ {authData.error}
+
+
+
+
+ {/if}
+
+ {#if errors.auth}
+
{errors.auth}
+ {/if}
+
+
diff --git a/src/routes/private/events/event/new/components/GoogleSheetsStep.svelte b/src/routes/private/events/event/new/components/GoogleSheetsStep.svelte
new file mode 100644
index 0000000..2dac6ec
--- /dev/null
+++ b/src/routes/private/events/event/new/components/GoogleSheetsStep.svelte
@@ -0,0 +1,213 @@
+
+
+
+
+
Select Google Sheet
+
+ {#if sheetsData.loading && sheetsData.availableSheets.length === 0}
+
+ {#each Array(5) as _}
+
+ {/each}
+
+ {:else if sheetsData.availableSheets.length === 0}
+
+
No Google Sheets found.
+
+ Refresh
+
+
+ {:else}
+
+ {#if !sheetsData.expandedSheetList && sheetsData.selectedSheet}
+
+
+
+
{sheetsData.selectedSheet.name}
+
+ Modified: {new Date(sheetsData.selectedSheet.modifiedTime).toLocaleDateString()}
+
+
+
+ Change
+
+
+
+
+
+ {:else}
+
+
+
Available Sheets
+ {#if sheetsData.selectedSheet}
+
+ Collapse list
+
+ {/if}
+
+
+ {#each sheetsData.availableSheets as sheet}
+
selectSheet(sheet)}
+ class="p-4 text-left border border-gray-200 rounded hover:border-blue-500 transition {
+ sheetsData.selectedSheet?.id === sheet.id ? 'border-blue-500 bg-blue-50' : ''
+ }"
+ >
+ {sheet.name}
+
+ Modified: {new Date(sheet.modifiedTime).toLocaleDateString()}
+
+
+ {/each}
+
+ {/if}
+
+ {/if}
+
+ {#if errors.sheet}
+
{errors.sheet}
+ {/if}
+
+
+ {#if sheetsData.selectedSheet && sheetsData.sheetData.length > 0}
+
+
Column Mapping
+
+
+
+
Column Mapping Instructions:
+
+ Select what each column represents by using the dropdown in each column header.
+ Make sure to assign Name, Surname, Email, and Confirmation columns.
+
+
+
+
+
+
+
+ {#each sheetsData.sheetData[0] || [] as header, index}
+
+
+
+ {header || `Empty Column ${index + 1}`}
+
+
e.stopPropagation()}
+ onchange={(e) => {
+ const value = e.target.value;
+ if (value === "none") return;
+
+ // Reset previous selection if this column was already mapped
+ if (sheetsData.columnMapping.name === index + 1) sheetsData.columnMapping.name = 0;
+ if (sheetsData.columnMapping.surname === index + 1) sheetsData.columnMapping.surname = 0;
+ if (sheetsData.columnMapping.email === index + 1) sheetsData.columnMapping.email = 0;
+ if (sheetsData.columnMapping.confirmation === index + 1) sheetsData.columnMapping.confirmation = 0;
+
+ // Set new mapping
+ if (value === "name") sheetsData.columnMapping.name = index + 1;
+ else if (value === "surname") sheetsData.columnMapping.surname = index + 1;
+ else if (value === "email") sheetsData.columnMapping.email = index + 1;
+ else if (value === "confirmation") sheetsData.columnMapping.confirmation = index + 1;
+ }}
+ >
+ Select data type
+ Name
+ Surname
+ Email
+ Confirmation
+
+
+ {#if sheetsData.columnMapping.name === index + 1}
+ Name Column
+ {:else if sheetsData.columnMapping.surname === index + 1}
+ Surname Column
+ {:else if sheetsData.columnMapping.email === index + 1}
+ Email Column
+ {:else if sheetsData.columnMapping.confirmation === index + 1}
+ Confirmation Column
+ {:else}
+ Not Mapped
+ {/if}
+
+
+
+ {/each}
+
+
+
+ {#each sheetsData.sheetData.slice(0, 10) as row, rowIndex}
+
+ {#each row as cell, cellIndex}
+
+
+ {cell || ''}
+
+
+ {/each}
+
+ {/each}
+
+
+
+
Showing first 10 rows
+
+ {/if}
+
+ {#if sheetsData.loading && sheetsData.selectedSheet}
+
+
Loading sheet data...
+
+ {/if}
+
+ {#if errors.sheetData}
+
{errors.sheetData}
+ {/if}
+
diff --git a/src/routes/private/events/event/new/components/StepNavigation.svelte b/src/routes/private/events/event/new/components/StepNavigation.svelte
new file mode 100644
index 0000000..207caba
--- /dev/null
+++ b/src/routes/private/events/event/new/components/StepNavigation.svelte
@@ -0,0 +1,42 @@
+
+
+
+
+ Previous
+
+
+
+ {#if currentStep < totalSteps - 1}
+
+ Next
+
+ {:else}
+
+ {loading ? 'Creating...' : 'Create Event'}
+
+ {/if}
+
+
diff --git a/src/routes/private/events/event/new/components/StepNavigator.svelte b/src/routes/private/events/event/new/components/StepNavigator.svelte
new file mode 100644
index 0000000..f26fb87
--- /dev/null
+++ b/src/routes/private/events/event/new/components/StepNavigator.svelte
@@ -0,0 +1,28 @@
+
+
+
+
+ {#each Array(totalSteps) as _, index}
+
+
+ {index + 1}
+
+ {#if index < totalSteps - 1}
+
+ {/if}
+
+ {/each}
+
+