95 lines
3.2 KiB
Svelte
95 lines
3.2 KiB
Svelte
<script lang="ts">
|
|
import { login } from "$lib/auth";
|
|
import { goto } from "$app/navigation";
|
|
|
|
let username = $state("");
|
|
let password = $state("");
|
|
let error = $state<string | null>(null);
|
|
let loading = $state(false);
|
|
|
|
async function submit(e: SubmitEvent) {
|
|
e.preventDefault();
|
|
error = null;
|
|
loading = true;
|
|
try {
|
|
await login(username, password);
|
|
goto("/");
|
|
} catch (err: any) {
|
|
error = err.message;
|
|
} finally {
|
|
loading = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Connexion — Containarr</title>
|
|
</svelte:head>
|
|
|
|
<div class="min-h-screen bg-abyss-900 bg-grid-faint bg-grid flex items-center justify-center p-4">
|
|
<div class="w-full max-w-[360px]">
|
|
|
|
<!-- Logo -->
|
|
<div class="flex flex-col items-center gap-3 mb-8">
|
|
<img src="/icon-192.png" alt="Containarr" class="w-14 h-14 rounded-2xl shadow-glow-emerald" />
|
|
<div class="text-center">
|
|
<h1 class="text-lg font-semibold text-slate-100 tracking-tight">Containarr</h1>
|
|
<p class="text-xs text-slate-600 mt-0.5">Gestionnaire de containers Docker</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Card -->
|
|
<form onsubmit={submit} class="card p-6 space-y-4">
|
|
|
|
{#if error}
|
|
<div class="flex items-center gap-2 px-3 py-2.5 rounded-lg bg-signal-red/10
|
|
border border-signal-red/20 text-signal-red text-xs">
|
|
<svg class="w-3.5 h-3.5 shrink-0" fill="currentColor" viewBox="0 0 20 20">
|
|
<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>
|
|
{error}
|
|
</div>
|
|
{/if}
|
|
|
|
<div class="space-y-1">
|
|
<label class="block text-xs font-medium text-slate-500" for="username">Utilisateur</label>
|
|
<input
|
|
id="username"
|
|
type="text"
|
|
bind:value={username}
|
|
autocomplete="username"
|
|
required
|
|
class="w-full bg-abyss-700 border border-white/[0.08] rounded-lg px-3 py-2.5 text-sm
|
|
text-slate-100 placeholder-slate-700 outline-none
|
|
focus:border-emerald/60 focus:ring-1 focus:ring-emerald/30 transition-all"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-1">
|
|
<label class="block text-xs font-medium text-slate-500" for="password">Mot de passe</label>
|
|
<input
|
|
id="password"
|
|
type="password"
|
|
bind:value={password}
|
|
autocomplete="current-password"
|
|
required
|
|
class="w-full bg-abyss-700 border border-white/[0.08] rounded-lg px-3 py-2.5 text-sm
|
|
text-slate-100 placeholder-slate-700 outline-none
|
|
focus:border-emerald/60 focus:ring-1 focus:ring-emerald/30 transition-all"
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
disabled={loading}
|
|
class="w-full mt-2 bg-emerald hover:bg-emerald-bright disabled:opacity-50
|
|
text-white text-sm font-medium py-2.5 rounded-lg transition-colors
|
|
shadow-glow-emerald"
|
|
>
|
|
{loading ? "Connexion…" : "Se connecter"}
|
|
</button>
|
|
</form>
|
|
|
|
</div>
|
|
</div>
|