84 lines
3.2 KiB
Svelte
84 lines
3.2 KiB
Svelte
<script lang="ts">
|
|
import { token, user, logout } from "$lib/stores/auth";
|
|
import { goto } from "$app/navigation";
|
|
import { page } from "$app/stores";
|
|
import { apiFetch } from "$lib/api/client";
|
|
|
|
let email = "";
|
|
let password = "";
|
|
let error = "";
|
|
|
|
async function handleLogin() {
|
|
try {
|
|
const data: any = await apiFetch("/auth/login", {
|
|
method: "POST",
|
|
body: JSON.stringify({ email, password }),
|
|
});
|
|
|
|
token.set(data.access_token);
|
|
user.set(data.user);
|
|
|
|
const redirect = $page.url.searchParams.get("redirect") || "/dashboard";
|
|
goto(redirect);
|
|
} catch (e: any) {
|
|
if (e.message?.includes('401')) {
|
|
error = "Invalid credentials";
|
|
} else {
|
|
error = "Failed to connect to server";
|
|
}
|
|
}
|
|
}
|
|
|
|
function handleLogout() {
|
|
logout();
|
|
goto("/login");
|
|
}
|
|
</script>
|
|
|
|
<div class="flex items-center justify-center min-h-screen bg-gray-100 p-4">
|
|
<div class="p-8 bg-white rounded shadow-md w-full max-w-md">
|
|
{#if $token}
|
|
<div class="text-center">
|
|
<h1 class="text-2xl font-bold mb-6">User Profile</h1>
|
|
<div class="bg-blue-50 p-4 rounded-lg mb-6 text-left">
|
|
<p class="text-sm text-gray-500 uppercase font-bold mb-1">Email</p>
|
|
<p class="text-lg mb-4">{$user?.email}</p>
|
|
|
|
<p class="text-sm text-gray-500 uppercase font-bold mb-1">Role</p>
|
|
<p class="text-lg mb-4 capitalize">{$user?.role}</p>
|
|
|
|
<p class="text-sm text-gray-500 uppercase font-bold mb-1">Organization ID</p>
|
|
<p class="text-xs font-mono text-gray-600">{$user?.organizationId}</p>
|
|
</div>
|
|
|
|
<div class="flex gap-4">
|
|
<a href="/dashboard" class="flex-1 bg-gray-100 text-gray-700 p-2 rounded hover:bg-gray-200 text-center font-semibold">Dashboard</a>
|
|
<button on:click={handleLogout} class="flex-1 bg-red-600 text-white p-2 rounded hover:bg-red-700 font-semibold">Sign Out</button>
|
|
</div>
|
|
</div>
|
|
{:else}
|
|
<h1 class="text-2xl font-bold mb-6 text-center">Login</h1>
|
|
{#if error}
|
|
<div class="bg-red-50 text-red-600 p-3 rounded mb-4 text-center text-sm">
|
|
{error}
|
|
</div>
|
|
{/if}
|
|
<form on:submit|preventDefault={handleLogin} class="space-y-4">
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-1" for="email">Email Address</label>
|
|
<input id="email" type="email" bind:value={email} class="w-full p-2 border rounded focus:ring-2 focus:ring-blue-500 outline-none" placeholder="name@example.com" required />
|
|
</div>
|
|
<div>
|
|
<label class="block text-gray-700 text-sm font-bold mb-1" for="password">Password</label>
|
|
<input id="password" type="password" bind:value={password} class="w-full p-2 border rounded focus:ring-2 focus:ring-blue-500 outline-none" placeholder="••••••••" required />
|
|
</div>
|
|
<button type="submit" class="w-full bg-blue-600 text-white p-2 rounded hover:bg-blue-700 font-semibold transition-colors">Sign In</button>
|
|
</form>
|
|
<div class="mt-6 text-center text-sm text-gray-500">
|
|
<p>Use seeded credentials:</p>
|
|
<p class="font-mono mt-1">admin@example.com / admin123</p>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|