More styling

This commit is contained in:
Roman Krček
2025-07-08 16:59:20 +02:00
parent 608ab81b23
commit 88492e4992
6 changed files with 83 additions and 172 deletions

View File

@@ -77,13 +77,13 @@
<button <button
onclick={handleDisconnect} onclick={handleDisconnect}
class="text-sm text-red-600 hover:text-red-800 flex items-center gap-1 whitespace-nowrap mt-1 sm:mt-0" class="flex items-center gap-2 rounded-full bg-red-100 px-3 py-1 border border-red-300 hover:bg-red-200 transition-colors whitespace-nowrap"
aria-label="Disconnect from Google" aria-label="Disconnect from Google"
> >
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0 text-red-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg> </svg>
Disconnect <span class="text-sm font-medium text-red-800">Disconnect</span>
</button> </button>
</div> </div>
{:else} {:else}

View File

@@ -180,16 +180,18 @@
{/if} {/if}
</div> </div>
<!-- Bottom actions --> <!-- Bottom actions - Mobile optimized -->
<div class="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 flex items-center gap-4"> <div class="fixed bottom-0 left-0 right-0 z-50 bg-white border-t border-gray-300 shadow-lg pb-safe">
<!-- Search bar --> <!-- Search bar and New Event button layout -->
<div class="relative mr-4"> <div class="max-w-2xl mx-auto px-4 py-3 flex flex-col sm:flex-row gap-3 sm:items-center">
<!-- Search bar - Full width on mobile, adaptive on desktop -->
<div class="relative flex-grow">
<input <input
type="text" type="text"
bind:value={searchTerm} bind:value={searchTerm}
oninput={handleSearchInput} oninput={handleSearchInput}
placeholder="Search events..." placeholder="Search events..."
class="w-64 pl-10 pr-4 py-3 rounded-full border border-gray-300 bg-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" class="w-full pl-10 pr-10 py-2.5 rounded-lg border border-gray-300 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/> />
<div class="absolute left-3 top-1/2 -translate-y-1/2"> <div class="absolute left-3 top-1/2 -translate-y-1/2">
{#if isSearching} {#if isSearching}
@@ -216,11 +218,20 @@
{/if} {/if}
</div> </div>
<!-- New Event button --> <!-- New Event button - Adaptive width -->
<a <a
href="/private/events/event/new" href="/private/events/event/new"
class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-8 rounded-full border border-gray-300 transition whitespace-nowrap" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2.5 px-6 rounded-lg transition text-center whitespace-nowrap sm:flex-shrink-0"
> >
<span class="flex items-center justify-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
New Event New Event
</span>
</a> </a>
</div>
</div> </div>
<!-- Add padding to bottom of content to prevent overlap with fixed bottom bar -->
<div class="h-24"></div>

View File

@@ -417,7 +417,19 @@
<!-- Step Content --> <!-- Step Content -->
<div class="rounded-lg border border-gray-300 bg-white p-6 mb-4"> <div class="rounded-lg border border-gray-300 bg-white p-6 mb-4">
{#if currentStep === 0} {#if currentStep === 0}
<GoogleAuthStep bind:authData bind:errors {connectToGoogle} {cancelGoogleAuth} {disconnectGoogle} /> <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} {:else if currentStep === 1}
<EventDetailsStep bind:eventData bind:errors /> <EventDetailsStep bind:eventData bind:errors />
{:else if currentStep === 2} {:else if currentStep === 2}

View File

@@ -1,19 +1,11 @@
<script lang="ts"> <script lang="ts">
import GoogleAuthButton from '$lib/components/GoogleAuthButton.svelte';
// Props // Props
let { authData, errors, connectToGoogle, cancelGoogleAuth, disconnectGoogle } = $props<{ let { errors, onSuccess, onError } = $props<{
authData: {
isConnected: boolean;
checking: boolean;
connecting: boolean;
showCancelOption: boolean;
token: string | null;
error: string | null;
userEmail: string | null;
};
errors: Record<string, string>; errors: Record<string, string>;
connectToGoogle: () => Promise<void>; onSuccess?: (token: string) => void;
cancelGoogleAuth: () => void; onError?: (error: string) => void;
disconnectGoogle: () => Promise<void>;
}>(); }>();
</script> </script>
@@ -24,121 +16,17 @@
To create events and import participants from Google Sheets, you need to connect your Google account. To create events and import participants from Google Sheets, you need to connect your Google account.
</p> </p>
{#if authData.checking} <GoogleAuthButton
<div class="flex justify-center items-center space-x-2"> size="large"
<div class="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600"></div> variant="primary"
<span class="text-gray-600">Checking connection...</span> onSuccess={onSuccess}
</div> onError={onError}
{:else if authData.isConnected} />
<div class="rounded-lg bg-green-50 border border-green-200 p-4 mb-4">
<div class="flex items-center justify-start">
<div class="justify-start flex flex-col items-start">
<p class="text-sm font-medium text-green-800">
Google account connected successfully!
</p>
{#if authData.userEmail}
<div class="flex items-center mt-2 bg-white rounded-full px-3 py-1 border border-green-300">
<p class="text-sm font-medium text-gray-700">
{authData.userEmail}
</p>
</div>
{/if}
<p class="text-sm text-green-700 mt-2">
You can now access Google Sheets and Gmail features.
</p>
</div>
</div>
<div class="mt-4 flex justify-end"> {#if errors.google}
<button <div class="mt-4 text-sm text-red-600">
onclick={disconnectGoogle} {errors.google}
class="text-sm text-red-600 hover:text-red-800 flex items-center"
aria-label="Disconnect Google account"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
Disconnect
</button>
</div> </div>
</div>
{:else}
<div class="rounded-lg bg-yellow-50 border border-yellow-200 p-4 mb-4">
<div class="flex items-center justify-start">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3 justify-start flex flex-col items-start">
<p class="text-sm font-medium text-yellow-800">
Google account not connected
</p>
<p class="text-sm text-yellow-700 mt-1">
Please connect your Google account to continue with event creation.
</p>
</div>
</div>
</div>
<div class="flex flex-col gap-3">
<button
onclick={connectToGoogle}
disabled={authData.connecting}
class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition disabled:opacity-50 disabled:cursor-not-allowed"
aria-label="Connect to Google account"
>
{#if authData.connecting}
<div class="w-5 h-5 mr-2 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
Connecting...
{:else}
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24">
<path fill="currentColor" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
<path fill="currentColor" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
<path fill="currentColor" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
<path fill="currentColor" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
</svg>
Connect to Google
{/if}
</button>
{#if authData.connecting && authData.showCancelOption}
<button
onclick={cancelGoogleAuth}
class="text-sm text-gray-600 hover:text-gray-900"
aria-label="Cancel Google authentication"
>
Cancel connection
</button>
<p class="text-xs text-gray-500 mt-1">
Taking too long? You can cancel and try again.
</p>
{/if}
</div>
{/if}
{#if authData.error}
<div class="mt-4 rounded-lg bg-red-50 border border-red-200 p-4">
<div class="flex items-center">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<p class="text-sm font-medium text-red-800">
Connection Error
</p>
<p class="text-sm text-red-700 mt-1">
{authData.error}
</p>
</div>
</div>
</div>
{/if}
{#if errors.auth}
<p class="mt-2 text-sm text-red-600">{errors.auth}</p>
{/if} {/if}
</div> </div>
</div> </div>

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { page } from '$app/stores'; import { page } from '$app/stores';
import GoogleAuthButton from './components/GoogleAuthButton.svelte'; import GoogleAuthButton from '$lib/components/GoogleAuthButton.svelte';
let { data } = $props(); let { data } = $props();