9dfd1b79cd
Notify Bridge frontend with SvelteKit 2 + Svelte 5 + Tailwind CSS v4: - Auth: login page, setup page, auth state management with $state runes - Theme: dark/light toggle with localStorage persistence - i18n: EN/RU translations with reactive $state-based t() function - Routes: dashboard, providers, trackers, targets, tracking-configs, template-configs, telegram-bots, users (stubs for configs pages) - Providers page: list with card grid, "Add Provider" button - API client: JWT auth, auto-redirect on 401, typed request helpers - Branding: "Notify Bridge" throughout, Observatory theme colors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
49 lines
1.7 KiB
Svelte
49 lines
1.7 KiB
Svelte
<script lang="ts">
|
|
import { t } from '$lib/i18n/index.svelte.ts';
|
|
import { setup } from '$lib/auth.svelte.ts';
|
|
|
|
let username = $state('');
|
|
let password = $state('');
|
|
let error = $state('');
|
|
let loading = $state(false);
|
|
|
|
async function handleSetup() {
|
|
error = '';
|
|
loading = true;
|
|
try {
|
|
await setup(username, password);
|
|
window.location.href = '/';
|
|
} catch (e: any) {
|
|
error = e.message || 'Setup failed';
|
|
} finally {
|
|
loading = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="min-h-screen flex items-center justify-center">
|
|
<div class="w-full max-w-md p-8 bg-card rounded-2xl border border-border shadow-lg animate-fade-slide-in">
|
|
<h1 class="text-2xl font-bold text-center mb-2">{t('app.name')}</h1>
|
|
<p class="text-center text-muted-foreground mb-6">Create your admin account</p>
|
|
|
|
<form onsubmit={(e) => { e.preventDefault(); handleSetup(); }} class="space-y-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-muted-foreground mb-1">{t('auth.username')}</label>
|
|
<input type="text" bind:value={username} class="w-full px-3 py-2 border border-border rounded-[var(--radius)]" required />
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-muted-foreground mb-1">{t('auth.password')}</label>
|
|
<input type="password" bind:value={password} class="w-full px-3 py-2 border border-border rounded-[var(--radius)]" required minlength="6" />
|
|
</div>
|
|
|
|
{#if error}
|
|
<p class="text-sm text-destructive">{error}</p>
|
|
{/if}
|
|
|
|
<button type="submit" disabled={loading} class="w-full py-2.5 bg-primary text-primary-foreground rounded-[var(--radius)] font-medium hover:opacity-90 transition-opacity disabled:opacity-50">
|
|
{loading ? t('common.loading') : t('auth.setup')}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|