Files
ClickerZ/Frontend/src/routes/login/+page.svelte
Tetardtek f6bff6e389
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 22s
feat: migrate frontend React 18 → Svelte 5 + SvelteKit
Core logic portable (economy, balance, cosmetics, migrateSave) — zero rewrite.
136 tests green, identiques. Backend inchangé.

- Svelte 5 runes stores (game, auth, toast) remplacent Zustand
- SvelteKit adapter-static SPA (dist/ output, fallback index.html)
- Tailwind v4 conservé, design system .gp-* porté
- Transitions natives : slide, fly, scale, fade sur toute l'UI
- Sidebar tabbée (Production/Evolution/Collection) + CollapsiblePanel
- Mobile bottom sheet avec FAB toggle + backdrop blur
- Click particles réactifs Svelte (plus de DOM impératif)
- TadpoleSprite bounce + glow ring au clic
- Guide refait en accordéon, Achievements avec filtres
- a11y : focus-visible, Escape modals, aria-current, aria-labels
- CI/CD adapté (tests + build + rsync)
- Build 504K (vs ~1.2MB React)
2026-03-28 20:03:21 +01:00

55 lines
1.8 KiB
Svelte

<script lang="ts">
import { goto } from '$app/navigation';
import { fly, scale } from 'svelte/transition';
import { quintOut, backOut } from 'svelte/easing';
import { authStore } from '$lib/stores/auth.svelte';
import { buildAuthUrl, saveVerifier } from '$lib/oauth';
const PROVIDERS = [
{ id: 'discord', label: 'Discord', emoji: '🎮', color: '#5865F2' },
{ id: 'github', label: 'GitHub', emoji: '🐙', color: '#333' },
{ id: 'google', label: 'Google', emoji: '🌐', color: '#4285f4' },
{ id: 'twitch', label: 'Twitch', emoji: '🎬', color: '#9146FF' },
];
$effect(() => {
if (authStore.user) goto('/', { replaceState: true });
});
async function handleLogin(provider: string) {
const redirectUri = `${window.location.origin}/callback`;
const { url, verifier } = await buildAuthUrl(redirectUri, provider);
saveVerifier(verifier);
window.location.href = url;
}
</script>
<svelte:head>
<title>Connexion — Clickerz</title>
</svelte:head>
<section>
<div class="containererror">
<div in:scale={{ duration: 400, start: 0.7, easing: backOut }}>
<img src="/svg/tadpole.svg" alt="" class="w-24 h-24 mx-auto mb-2 opacity-60" />
</div>
<h1 in:fly={{ y: 20, delay: 100, duration: 400, easing: quintOut }}>Connexion</h1>
<p class="message" in:fly={{ y: 15, delay: 200, duration: 400, easing: quintOut }}>
Connecte-toi pour sauvegarder ta progression.
</p>
<div class="flex flex-col gap-3 mt-6 w-full max-w-xs mx-auto">
{#each PROVIDERS as p, i}
<button
class="btn-return flex items-center justify-center gap-2 py-3! text-base!"
onclick={() => handleLogin(p.id)}
type="button"
in:fly={{ y: 20, delay: 300 + i * 80, duration: 300, easing: quintOut }}
>
<span class="text-xl">{p.emoji}</span>
Continuer avec {p.label}
</button>
{/each}
</div>
</div>
</section>