Cleanup for error notifications

This commit is contained in:
Roman Krček
2025-07-14 14:34:38 +02:00
parent 06f2553b42
commit b9db3d22a3
4 changed files with 76 additions and 87 deletions

View File

@@ -4,7 +4,7 @@
import type { GoogleSheet } from '$lib/google/sheets/types.ts';
import { goto } from '$app/navigation';
import { toast } from '$lib/stores/toast.js';
// Import Components
import GoogleAuthStep from './components/GoogleAuthStep.svelte';
import EventDetailsStep from './components/EventDetailsStep.svelte';
@@ -42,7 +42,7 @@
selectedSheet: null as GoogleSheet | null,
sheetData: [] as string[][],
columnMapping: {
name: 0, // Initialize to 0 (no column selected)
name: 0, // Initialize to 0 (no column selected)
surname: 0,
email: 0,
confirmation: 0
@@ -64,7 +64,7 @@
onMount(async () => {
// Check Google auth status on mount
await checkGoogleAuth();
if (currentStep === 2) {
await loadRecentSheets();
}
@@ -76,13 +76,13 @@
try {
const accessToken = localStorage.getItem('google_access_token');
const refreshToken = localStorage.getItem('google_refresh_token');
if (accessToken && refreshToken) {
// Check if token is still valid
const isValid = await isTokenValid(accessToken);
authData.isConnected = isValid;
authData.token = accessToken;
if (isValid) {
// Fetch user info
await fetchUserInfo(accessToken);
@@ -104,15 +104,16 @@
async function connectToGoogle() {
authData.error = '';
authData.connecting = true;
try {
// Open popup window for OAuth
const popup = window.open(
'/auth/google',
'google-auth',
'width=500,height=600,scrollbars=yes,resizable=yes,left=' +
Math.round(window.screen.width / 2 - 250) + ',top=' +
Math.round(window.screen.height / 2 - 300)
'width=500,height=600,scrollbars=yes,resizable=yes,left=' +
Math.round(window.screen.width / 2 - 250) +
',top=' +
Math.round(window.screen.height / 2 - 300)
);
if (!popup) {
@@ -127,12 +128,12 @@
// Store current timestamp to detect changes in localStorage
const startTimestamp = localStorage.getItem('google_auth_timestamp') || '0';
// Poll localStorage for auth completion
const pollInterval = setInterval(() => {
try {
const currentTimestamp = localStorage.getItem('google_auth_timestamp');
// If timestamp has changed, auth is complete
if (currentTimestamp && currentTimestamp !== startTimestamp) {
handleAuthSuccess();
@@ -141,24 +142,24 @@
console.error('Error checking auth timestamp:', e);
}
}, 500); // Poll every 500ms
// Common handler for authentication success
function handleAuthSuccess() {
if (authCompleted) return; // Prevent duplicate handling
authCompleted = true;
authData.connecting = false;
authData.showCancelOption = false;
// Clean up timers
clearInterval(pollInterval);
if (popupTimer) clearTimeout(popupTimer);
if (cancelTimeout) clearTimeout(cancelTimeout);
// Update auth state
setTimeout(checkGoogleAuth, 100);
}
// Clean up function to handle all cleanup in one place
const cleanUp = () => {
clearInterval(pollInterval);
@@ -190,19 +191,18 @@
cleanUp();
}
}, 60 * 1000); // Reduced from 3min to 1min
} catch (error) {
console.error('Error connecting to Google:', error);
authData.error = 'Failed to connect to Google';
authData.connecting = false;
}
}
function cancelGoogleAuth() {
authData.connecting = false;
authData.showCancelOption = false;
}
async function fetchUserInfo(accessToken: string) {
try {
// Use the new getUserInfo function from our lib
@@ -217,7 +217,7 @@
authData.userEmail = null;
}
}
async function disconnectGoogle() {
try {
// First revoke the token at Google using our API
@@ -225,16 +225,16 @@
if (accessToken) {
await revokeToken(accessToken);
}
// 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;
@@ -263,7 +263,7 @@
// Clear previous errors
errors = {};
let isValid = true;
if (currentStep === 0) {
if (!authData.isConnected) {
toast.error('Please connect your Google account to continue');
@@ -287,17 +287,17 @@
errors.sheet = 'Please select a Google Sheet';
isValid = false;
}
if (sheetsData.selectedSheet) {
// Validate column mappings
const { name, surname, email, confirmation } = sheetsData.columnMapping;
const missingColumns = [];
if (!name) missingColumns.push('Name');
if (!surname) missingColumns.push('Surname');
if (!email) missingColumns.push('Email');
if (!confirmation) missingColumns.push('Confirmation');
if (missingColumns.length > 0) {
const errorMsg = `Please map the following columns: ${missingColumns.join(', ')}`;
toast.error(errorMsg);
@@ -326,16 +326,16 @@
sheetsData.loading = true;
// Always expand the sheet list when loading new sheets
sheetsData.expandedSheetList = true;
try {
// Use the new unified API endpoint
const response = await fetch('/private/api/google/sheets/recent', {
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem('google_refresh_token')}`
Authorization: `Bearer ${localStorage.getItem('google_refresh_token')}`
}
});
if (response.ok) {
sheetsData.availableSheets = await response.json();
}
@@ -349,24 +349,24 @@
async function selectSheet(sheet: GoogleSheet) {
const sameSheet = sheetsData.selectedSheet?.id === sheet.id;
sheetsData.selectedSheet = sheet;
sheetsData.loading = true;
// Collapse sheet list when selecting a new sheet
if (!sameSheet) {
sheetsData.expandedSheetList = false;
}
try {
// Use the new unified API endpoint
const response = await fetch(`/private/api/google/sheets/${sheet.id}/data`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem('google_refresh_token')}`
Authorization: `Bearer ${localStorage.getItem('google_refresh_token')}`
}
});
if (response.ok) {
const data = await response.json();
sheetsData.sheetData = data.values || [];
@@ -378,7 +378,7 @@
sheetsData.loading = false;
}
}
// Toggle the sheet list expansion
function toggleSheetList() {
sheetsData.expandedSheetList = !sheetsData.expandedSheetList;
@@ -427,49 +427,45 @@
});
</script>
<div class="max-w-4xl mx-auto p-6">
<!-- Header -->
<StepNavigator {currentStep} {totalSteps} />
<!-- Header -->
<StepNavigator {currentStep} {totalSteps} />
<!-- Step Content -->
<div class="rounded-lg border border-gray-300 bg-white p-6 mb-4">
{#if currentStep === 0}
<GoogleAuthStep
bind:errors
onSuccess={(token) => {
authData.error = null;
authData.token = token;
authData.isConnected = true;
setTimeout(checkGoogleAuth, 100);
}}
onError={(error) => {
authData.error = error;
authData.isConnected = false;
}}
/>
{:else if currentStep === 1}
<EventDetailsStep bind:eventData />
{:else if currentStep === 2}
<GoogleSheetsStep bind:sheetsData bind:errors {loadRecentSheets} {selectSheet} {toggleSheetList} />
{:else if currentStep === 3}
<EmailSettingsStep bind:emailData bind:errors />
{/if}
{#if errors.submit}
<div class="mt-4 p-3 bg-red-50 border border-red-200 rounded">
<p class="text-sm text-red-600">{errors.submit}</p>
</div>
{/if}
</div>
<!-- Navigation -->
<StepNavigation
{currentStep}
{totalSteps}
{canProceed}
{loading}
{prevStep}
{nextStep}
{createEvent}
/>
<!-- Step Content -->
<div class="mb-4 rounded border border-gray-300 bg-white p-6">
{#if currentStep === 0}
<GoogleAuthStep
onSuccess={(token) => {
authData.error = null;
authData.token = token;
authData.isConnected = true;
setTimeout(checkGoogleAuth, 100);
}}
onError={(error) => {
authData.error = error;
authData.isConnected = false;
}}
/>
{:else if currentStep === 1}
<EventDetailsStep bind:eventData />
{:else if currentStep === 2}
<GoogleSheetsStep
bind:sheetsData
{loadRecentSheets}
{selectSheet}
{toggleSheetList}
/>
{:else if currentStep === 3}
<EmailSettingsStep bind:emailData />
{/if}
</div>
<!-- Navigation -->
<StepNavigation
{currentStep}
{totalSteps}
{canProceed}
{loading}
{prevStep}
{nextStep}
{createEvent}
/>

View File

@@ -54,7 +54,6 @@
Detected templates: {bodyTemplatesDetected.map((v) => v.name).join(', ')}
</p>
{/if}
<!-- Errors now shown as toast notifications -->
</div>
<div>

View File

@@ -21,7 +21,5 @@
onSuccess={onSuccess}
onError={onError}
/>
<!-- Error messages are now shown as toast notifications -->
</div>
</div>

View File

@@ -255,8 +255,6 @@
{/if}
</div>
{/if}
<!-- Error messages are now shown as toast notifications -->
</div>
{#if sheetsData.selectedSheet && sheetsData.sheetData.length > 0}
@@ -370,8 +368,6 @@
<div class="text-gray-600">Loading sheet data...</div>
</div>
{/if}
<!-- Error messages are now shown as toast notifications -->
</div>