91 lines
2.4 KiB
Svelte
91 lines
2.4 KiB
Svelte
<script lang="ts">
|
|
import { goto } from '$app/navigation';
|
|
|
|
let identifier = $state('');
|
|
let password = $state('');
|
|
let error = $state('');
|
|
let loading = $state(false);
|
|
|
|
async function handleSubmit() {
|
|
loading = true;
|
|
error = '';
|
|
|
|
try {
|
|
const res = await fetch('/api/auth/login', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ username: identifier, password })
|
|
});
|
|
|
|
const data = await res.json();
|
|
|
|
if (!res.ok) {
|
|
error = data.error || 'Login failed';
|
|
return;
|
|
}
|
|
|
|
localStorage.setItem('token', data.data.token);
|
|
|
|
if (data.data.user.role === 'admin') {
|
|
goto('/');
|
|
} else {
|
|
goto('/auth/dashboard');
|
|
}
|
|
} catch (e) {
|
|
error = 'Connection error';
|
|
} finally {
|
|
loading = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="min-h-screen flex items-center justify-center bg-base-200" data-theme="light">
|
|
<div class="card bg-base-100 shadow-xl w-full max-w-md">
|
|
<div class="card-body">
|
|
<h1 class="text-2xl font-bold text-center mb-2">IMC</h1>
|
|
<p class="text-center text-base-content/60 mb-6">Mail Server Administration</p>
|
|
|
|
{#if error}
|
|
<div class="alert alert-error mb-4">
|
|
<span>{error}</span>
|
|
</div>
|
|
{/if}
|
|
|
|
<form onsubmit={(e) => { e.preventDefault(); handleSubmit(); }} class="space-y-4">
|
|
<fieldset class="fieldset">
|
|
<legend class="fieldset-legend">Username</legend>
|
|
<input
|
|
type="text"
|
|
class="input input-bordered w-full"
|
|
bind:value={identifier}
|
|
placeholder="user@example.org or username"
|
|
required
|
|
autocomplete="username"
|
|
autofocus
|
|
/>
|
|
</fieldset>
|
|
|
|
<fieldset class="fieldset">
|
|
<legend class="fieldset-legend">Password</legend>
|
|
<input
|
|
type="password"
|
|
class="input input-bordered w-full"
|
|
bind:value={password}
|
|
placeholder="Enter password"
|
|
required
|
|
autocomplete="current-password"
|
|
/>
|
|
</fieldset>
|
|
|
|
<button type="submit" class="btn btn-primary w-full" disabled={loading}>
|
|
{#if loading}
|
|
<span class="loading loading-spinner loading-sm"></span>
|
|
Signing in...
|
|
{:else}
|
|
Sign In
|
|
{/if}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|