Introduced a new API client in src/lib/api/ to handle requests securely. Refactored vendor pages to use this client. Updated authentication logic in layout and login pages.
128 lines
5.3 KiB
Svelte
Executable File
128 lines
5.3 KiB
Svelte
Executable File
<script lang="ts">
|
|
import { goto } from '$app/navigation';
|
|
import { user } from '$lib/states';
|
|
import { api } from '$lib/api';
|
|
import type { LoginRequest } from '$lib/api';
|
|
|
|
let username = '';
|
|
let password = '';
|
|
let errorMessage = '';
|
|
let isLoading = false;
|
|
|
|
async function handleSubmit() {
|
|
const loginData: LoginRequest = {
|
|
username,
|
|
password
|
|
};
|
|
|
|
isLoading = true;
|
|
errorMessage = '';
|
|
|
|
const result = await api.auth.login(loginData);
|
|
|
|
if (result.error) {
|
|
errorMessage = result.error;
|
|
} else if (result.data) {
|
|
// Update the user store
|
|
user.set(result.data.user);
|
|
// Redirect to vendor page after successful login
|
|
goto('/vendor');
|
|
}
|
|
|
|
isLoading = false;
|
|
}
|
|
</script>
|
|
|
|
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 via-white to-purple-50 px-4 sm:px-6 lg:px-8">
|
|
<div class="max-w-md w-full space-y-8">
|
|
<div class="bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
|
<div class="text-center">
|
|
<h2 class="text-3xl font-bold text-gray-900 mb-2">Welcome back</h2>
|
|
<p class="text-gray-600">Sign in to your account</p>
|
|
</div>
|
|
|
|
{#if errorMessage}
|
|
<div class="mt-6 bg-red-50 border border-red-200 rounded-lg p-4">
|
|
<div class="flex items-center">
|
|
<svg class="w-5 h-5 text-red-500 mr-3" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
|
|
</svg>
|
|
<p class="text-sm font-medium text-red-800">{errorMessage}</p>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
|
|
<form class="mt-8 space-y-6" on:submit|preventDefault={handleSubmit}>
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label for="username" class="block text-sm font-medium text-gray-700 mb-2">Username</label>
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<svg class="h-5 w-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd"></path>
|
|
</svg>
|
|
</div>
|
|
<input
|
|
id="username"
|
|
name="username"
|
|
type="text"
|
|
autocomplete="username"
|
|
required
|
|
bind:value={username}
|
|
class="block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-oil focus:border-transparent transition-all duration-200 bg-gray-50 focus:bg-white"
|
|
placeholder="Enter your username"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="password" class="block text-sm font-medium text-gray-700 mb-2">Password</label>
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<svg class="h-5 w-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
|
<path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"></path>
|
|
</svg>
|
|
</div>
|
|
<input
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
autocomplete="current-password"
|
|
required
|
|
bind:value={password}
|
|
class="block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-oil focus:border-transparent transition-all duration-200 bg-gray-50 focus:bg-white"
|
|
placeholder="Enter your password"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<button
|
|
type="submit"
|
|
disabled={isLoading}
|
|
class="group relative w-full flex justify-center py-3 px-4 border border-transparent text-sm font-medium rounded-lg text-white bg-orange-oil focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-oil transform hover:scale-105 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
|
|
>
|
|
{#if isLoading}
|
|
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
</svg>
|
|
Signing in...
|
|
{:else}
|
|
Sign in
|
|
{/if}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="mt-6 text-center">
|
|
<p class="text-sm text-gray-600">
|
|
Don't have an account?
|
|
<a href="/register" class="font-medium text-blue-600 hover:text-blue-500 transition-colors duration-200">Create one here</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|