Initial commit: Second Brain Platform
Complete platform with unified design system and real API integration. Apps: Dashboard, Fitness, Budget, Inventory, Trips, Reader, Media, Settings Infrastructure: SvelteKit + Python gateway + Docker Compose
This commit is contained in:
9
frontend-v2/src/routes/(auth)/+layout.svelte
Normal file
9
frontend-v2/src/routes/(auth)/+layout.svelte
Normal file
@@ -0,0 +1,9 @@
|
||||
<script lang="ts">
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Login — Platform</title>
|
||||
</svelte:head>
|
||||
|
||||
{@render children()}
|
||||
128
frontend-v2/src/routes/(auth)/login/+page.svelte
Normal file
128
frontend-v2/src/routes/(auth)/login/+page.svelte
Normal file
@@ -0,0 +1,128 @@
|
||||
<script lang="ts">
|
||||
import { platformAuth } from '$lib/api/client';
|
||||
import { page } from '$app/state';
|
||||
|
||||
let username = $state('');
|
||||
let password = $state('');
|
||||
let error = $state('');
|
||||
let loading = $state(false);
|
||||
|
||||
async function handleLogin(e: Event) {
|
||||
e.preventDefault();
|
||||
error = '';
|
||||
loading = true;
|
||||
try {
|
||||
const res = await platformAuth.login(username, password);
|
||||
if (res.error) {
|
||||
error = res.error;
|
||||
} else {
|
||||
const redirectTo = page.url.searchParams.get('redirect') || '/';
|
||||
window.location.href = redirectTo;
|
||||
}
|
||||
} catch {
|
||||
error = 'Unable to connect to server';
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="login-wrapper">
|
||||
<div class="login-card">
|
||||
<div class="login-logo">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="24" height="24"><path d="M3 7l6-3 6 3 6-3v13l-6 3-6-3-6 3V7z"/><path d="M9 4v13"/><path d="M15 7v13"/></svg>
|
||||
Platform
|
||||
</div>
|
||||
<div class="login-subtitle">Sign in to your account</div>
|
||||
|
||||
<form onsubmit={handleLogin}>
|
||||
{#if error}
|
||||
<div class="login-error">{error}</div>
|
||||
{/if}
|
||||
|
||||
<div class="login-field">
|
||||
<label class="login-label" for="username">Username</label>
|
||||
<input
|
||||
id="username"
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="Enter username"
|
||||
bind:value={username}
|
||||
autocomplete="username"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="login-field">
|
||||
<label class="login-label" for="password">Password</label>
|
||||
<input
|
||||
id="password"
|
||||
class="input"
|
||||
type="password"
|
||||
placeholder="Enter password"
|
||||
bind:value={password}
|
||||
autocomplete="current-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button class="btn-primary full" type="submit" disabled={loading}>
|
||||
{loading ? 'Signing in...' : 'Sign in'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.login-wrapper {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
background: var(--canvas);
|
||||
}
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 380px;
|
||||
background: var(--card);
|
||||
border-radius: var(--radius);
|
||||
padding: 32px;
|
||||
box-shadow: var(--card-shadow);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.login-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 600;
|
||||
color: var(--text-1);
|
||||
}
|
||||
.login-subtitle {
|
||||
text-align: center;
|
||||
font-size: var(--text-base);
|
||||
color: var(--text-3);
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.login-field {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.login-label {
|
||||
display: block;
|
||||
font-size: var(--text-sm);
|
||||
font-weight: 500;
|
||||
color: var(--text-2);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.login-error {
|
||||
font-size: var(--text-sm);
|
||||
color: var(--error);
|
||||
background: var(--error-bg);
|
||||
padding: 10px 14px;
|
||||
border-radius: var(--radius-sm);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user