Files
homefeed/frontend/src/routes/admin/settings/+page.svelte
T
Claude 6d5d74b9bb Add PoE2 sidebar module: currency exchange watchlist
Tracks Path of Exile 2 currency values via poe.ninja's public economy
API, mirroring the existing Weather/Stocks sidebar modules. Always
follows the current challenge league (auto-detected, no admin picker).
Admin browses and picks currencies from a live list rather than typing
symbols, since currency ids are opaque. Change % is a 7-day window,
labeled accordingly to avoid the same interval ambiguity Stocks had.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014c1L8ghNBFjfiH64UMViP8
2026-07-25 01:54:55 +00:00

106 lines
3.1 KiB
Svelte

<script lang="ts">
import type { PageData } from './$types';
import MergeTab from '$lib/components/admin/MergeTab.svelte';
import SourcesTab from '$lib/components/admin/SourcesTab.svelte';
import ModelsTab from '$lib/components/admin/ModelsTab.svelte';
import RetentionTab from '$lib/components/admin/RetentionTab.svelte';
import EventsTab from '$lib/components/admin/EventsTab.svelte';
import WeatherTab from '$lib/components/admin/WeatherTab.svelte';
import StocksTab from '$lib/components/admin/StocksTab.svelte';
import BookmarksTab from '$lib/components/admin/BookmarksTab.svelte';
import Poe2Tab from '$lib/components/admin/Poe2Tab.svelte';
import ConnectionsTab from '$lib/components/admin/ConnectionsTab.svelte';
import LogsTab from '$lib/components/admin/LogsTab.svelte';
let { data }: { data: PageData } = $props();
const tabs = [
{ id: 'merge', label: 'Merge' },
{ id: 'sources', label: 'Sources' },
{ id: 'models', label: 'Models' },
{ id: 'retention', label: 'Retention' },
{ id: 'events', label: 'Tracked events' },
{ id: 'weather', label: 'Weather' },
{ id: 'stocks', label: 'Stocks' },
{ id: 'bookmarks', label: 'Bookmarks' },
{ id: 'poe2', label: 'PoE2' },
{ id: 'connections', label: 'Connections' },
{ id: 'logs', label: 'Logs' }
];
let active = $state('merge');
</script>
<div class="head">
<span class="title">Admin</span>
<nav class="tabs">
{#each tabs as tab}
<button class="tab" class:active={active === tab.id} onclick={() => (active = tab.id)}>
{tab.label}
</button>
{/each}
</nav>
</div>
<div class="content">
{#if active === 'merge'}
<MergeTab settings={data.settings} />
{:else if active === 'sources'}
<SourcesTab sources={data.sources} categories={data.settings.categoryPriority} />
{:else if active === 'models'}
<ModelsTab settings={data.settings} models={data.models} aiStatus={data.aiStatus} />
{:else if active === 'retention'}
<RetentionTab settings={data.settings} />
{:else if active === 'events'}
<EventsTab events={data.events} sources={data.sources} />
{:else if active === 'weather'}
<WeatherTab settings={data.settings} />
{:else if active === 'stocks'}
<StocksTab tickers={data.stockTickers} />
{:else if active === 'bookmarks'}
<BookmarksTab bookmarks={data.bookmarks} />
{:else if active === 'poe2'}
<Poe2Tab settings={data.settings} watchlist={data.poe2Watchlist} />
{:else if active === 'connections'}
<ConnectionsTab settings={data.settings} aiStatus={data.aiStatus} telegramStatus={data.telegramStatus} />
{:else if active === 'logs'}
<LogsTab logs={data.logs} />
{/if}
</div>
<style>
.head {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 20px;
}
.title {
font-family: var(--font-voice);
font-size: 24px;
font-weight: 500;
}
.tabs {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.tab {
font-size: 12px;
padding: 5px 12px;
border: none;
background: transparent;
color: var(--text-secondary);
border-radius: var(--radius);
}
.tab.active {
background: var(--pill-bg);
color: var(--pill-text);
}
.content {
max-width: 720px;
}
</style>