|
5 | 5 | import WorkerHealth from '$lib/components/dash/WorkerHealth.svelte'; |
6 | 6 | import WorkflowStatus from '$lib/components/dash/WorkflowStatus.svelte'; |
7 | 7 | import DeploymentTimeline from '$lib/components/dash/DeploymentTimeline.svelte'; |
| 8 | + import { page } from '$app/stores'; |
| 9 | + import { goto } from '$app/navigation'; |
8 | 10 |
|
9 | 11 | let { data } = $props(); |
10 | 12 |
|
|
14 | 16 | const isError = $derived(data.status !== 200 || d.error); |
15 | 17 |
|
16 | 18 | type Tab = 'seo' | 'infra' | 'workflows' | 'security'; |
17 | | - let activeTab: Tab = $state('seo'); |
| 19 | + const validTabs: Tab[] = ['seo', 'infra', 'workflows', 'security']; |
| 20 | + const activeTab: Tab = $derived.by(() => { |
| 21 | + const t = $page.url.searchParams.get('tab'); |
| 22 | + return validTabs.includes(t as Tab) ? (t as Tab) : 'seo'; |
| 23 | + }); |
| 24 | +
|
| 25 | + function buildParams(overrides: Record<string, string>): string { |
| 26 | + const entries: [string, string][] = []; |
| 27 | + for (const [k, v] of $page.url.searchParams.entries()) { |
| 28 | + if (!(k in overrides)) entries.push([k, v]); |
| 29 | + } |
| 30 | + for (const [k, v] of Object.entries(overrides)) { |
| 31 | + entries.push([k, v]); |
| 32 | + } |
| 33 | + return entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&'); |
| 34 | + } |
| 35 | +
|
| 36 | + function switchTab(tab: Tab) { |
| 37 | + void goto(`/dash?${buildParams({ tab })}`, { replaceState: true, noScroll: true }); |
| 38 | + } |
| 39 | +
|
| 40 | + function dayLink(d: number): string { |
| 41 | + return `/dash?${buildParams({ days: String(d), tab: 'infra' })}`; |
| 42 | + } |
18 | 43 |
|
19 | 44 | function cqStatusDot(summary: { pagesWithIssues: number }): string { |
20 | 45 | if (summary.pagesWithIssues === 0) return 'bg-emerald-500'; |
|
87 | 112 | {activeTab === tab.id |
88 | 113 | ? 'bg-white text-accent-900 shadow-sm dark:bg-accent-700 dark:text-accent-100' |
89 | 114 | : 'text-accent-600 hover:text-accent-900 dark:text-accent-400 dark:hover:text-accent-200'}" |
90 | | - onclick={() => { |
91 | | - activeTab = tab.id as Tab; |
92 | | - }} |
| 115 | + onclick={() => switchTab(tab.id as Tab)} |
93 | 116 | > |
94 | 117 | {tab.label} |
95 | 118 | </button> |
|
667 | 690 | <div class="flex gap-1 rounded-md bg-accent-100 p-0.5 dark:bg-accent-800"> |
668 | 691 | {#each [1, 7, 14, 30] as d (d)} |
669 | 692 | <a |
670 | | - href="/dash?days={d}" |
| 693 | + href={dayLink(d)} |
671 | 694 | class="rounded px-2 py-1 text-xs font-medium transition-colors |
672 | 695 | {infra.days === d |
673 | 696 | ? 'bg-white text-accent-900 shadow-sm dark:bg-accent-700 dark:text-accent-100' |
674 | 697 | : 'text-accent-500 hover:text-accent-800 dark:text-accent-400 dark:hover:text-accent-200'}" |
675 | | - onclick={() => { |
676 | | - activeTab = 'infra'; |
677 | | - }} |
678 | 698 | > |
679 | 699 | {d}d |
680 | 700 | </a> |
|
0 commit comments