feat(notify-bridge): phase 7 - frontend restructuring

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>
This commit is contained in:
2026-03-19 23:53:37 +03:00
parent 7f99c895a4
commit 9dfd1b79cd
12 changed files with 274 additions and 3 deletions
+34
View File
@@ -0,0 +1,34 @@
<script lang="ts">
import { t } from '$lib/i18n/index.svelte.ts';
import { api } from '$lib/api.ts';
import { onMount } from 'svelte';
let targets = $state<any[]>([]);
let loading = $state(true);
onMount(async () => {
try { targets = await api.get('/targets'); } catch {}
loading = false;
});
</script>
<div class="p-6 max-w-5xl mx-auto">
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold">{t('nav.targets')}</h1>
</div>
{#if loading}
<p class="text-muted-foreground">{t('common.loading')}</p>
{:else if targets.length === 0}
<p class="text-muted-foreground text-center py-16">{t('common.noData')}</p>
{:else}
<div class="grid gap-4 md:grid-cols-2 stagger-children">
{#each targets as target}
<div class="p-4 bg-card rounded-xl border border-border">
<h3 class="font-semibold">{target.name}</h3>
<p class="text-xs text-muted-foreground capitalize">{target.type}</p>
</div>
{/each}
</div>
{/if}
</div>