MemPrepMate / src /lib /components /LoginForm.svelte
Christian Kniep
new webapp
1fff71f
<script lang="ts">
import { initiateOAuthLogin } from '$lib/services/auth';
import { ENABLE_MOCK_AUTH } from '$lib/utils/constants';
let loading = false;
let error: string | null = null;
async function handleLogin() {
loading = true;
error = null;
try {
await initiateOAuthLogin();
// OAuth will redirect, mock auth will complete
} catch (err) {
error = err instanceof Error ? err.message : 'Login failed';
console.error('Login error:', err);
} finally {
loading = false;
}
}
</script>
<div class="login-form card shadow-sm">
<div class="card-body p-3 p-md-4">
<div class="text-center mb-3 mb-md-4">
<i class="bi bi-chat-dots-fill text-primary login-icon"></i>
<h2 class="mt-3 fs-4 fs-md-3">Welcome to PrepMate</h2>
<p class="text-muted mb-0 fs-6">Sign in to manage your chat sessions</p>
</div>
{#if error}
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle-fill me-2"></i>
{error}
<button
type="button"
class="btn-close"
aria-label="Close"
on:click={() => (error = null)}
></button>
</div>
{/if}
<div class="d-grid gap-3">
<button
type="button"
class="btn btn-primary btn-lg"
on:click={handleLogin}
disabled={loading}
>
{#if loading}
<span class="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"
></span>
{:else}
<i class="bi bi-box-arrow-in-right me-2"></i>
{/if}
{ENABLE_MOCK_AUTH ? 'Login (Mock)' : 'Login with HuggingFace'}
</button>
</div>
{#if ENABLE_MOCK_AUTH}
<div class="alert alert-warning mt-3 mb-0" role="alert">
<i class="bi bi-info-circle-fill me-2"></i>
<strong>Development Mode:</strong> Using mock authentication
</div>
{/if}
</div>
</div>
<style>
.login-form {
max-width: 100%;
margin: 0 auto;
}
.login-icon {
font-size: 2.5rem;
}
/* Mobile optimizations */
@media (max-width: 576px) {
.login-icon {
font-size: 2rem;
}
}
/* Larger screens */
@media (min-width: 768px) {
.login-icon {
font-size: 3rem;
}
}
</style>