All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 22s
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)
55 lines
1.8 KiB
Svelte
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>
|