refactor: comprehensive consistency review — UI/UX, code quality, functional parity

Fix 19 issues across 3 priority tiers found during full-codebase review:

CRITICAL:
- Fix undefined --color-secondary CSS variable causing invisible UI elements
- Fix Google Photos command templates using nonexistent asset.originalFileName
- Fix scheduler template variable docs (tracker_name → schedule_name)
- Add missing admin guard on notification template update endpoint

HIGH:
- Fix 5 hardcoded English strings missing i18n (MultiEntitySelect, actions,
  settings, TelegramBotTab, users)
- Replace 17 raw <button> elements with shared <Button> component
- Replace 5 raw error divs with shared <ErrorBanner> component
- Refactor webhook handler duplication into shared _dispatch_webhook_event()
- Add 30+ provider-specific fields to TrackingConfig TypeScript type
- Add default TrackingConfig seeds for immich and google_photos
- Add provider-specific command variable docs (Gitea, Planka, NUT, GP, Webhook)

MEDIUM:
- Replace hardcoded hex colors and Tailwind classes with CSS variable tokens
- Remove dead code (unused imports, orphaned check_notification_tracker)
- Fix Svelte 5 patterns ($state for _prevProviderId, remove unnecessary as any)
- Fix inconsistent POST response shape (targets now returns full response)
- Fix Google Photos template dead asset.year branches, clarify album_url docs
This commit is contained in:
2026-03-31 23:27:35 +03:00
parent 6113a0039c
commit 6e51164f8e
29 changed files with 501 additions and 309 deletions
@@ -19,6 +19,7 @@
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
import { highlightFromUrl } from '$lib/highlight';
import { globalProviderFilter } from '$lib/stores/provider-filter.svelte';
import ErrorBanner from '$lib/components/ErrorBanner.svelte';
import type { CommandConfig } from '$lib/types';
function templateName(id: number | null): string {
@@ -161,7 +162,7 @@
{#if showForm}
<Card class="mb-6">
{#if error}<div class="bg-[var(--color-error-bg)] text-[var(--color-error-fg)] text-sm rounded-md p-3 mb-4">{error}</div>{/if}
{#if error}<ErrorBanner message={error} />{/if}
<form onsubmit={saveConfig} class="space-y-4">
<div>
<label for="cfg-name" class="block text-sm font-medium mb-1">{t('commandConfig.name')}</label>
@@ -230,10 +231,9 @@
</div>
{/if}
<button type="submit" disabled={submitting}
class="px-4 py-2 bg-[var(--color-primary)] text-[var(--color-primary-foreground)] rounded-md text-sm font-medium hover:opacity-90 disabled:opacity-50">
<Button type="submit" disabled={submitting}>
{submitting ? t('common.loading') : (editing ? t('common.save') : t('common.create'))}
</button>
</Button>
</form>
</Card>
{/if}
@@ -268,7 +268,7 @@
<span style="color: var(--color-primary);"><MdiIcon name={cfg.icon || 'mdiConsoleLine'} size={20} /></span>
<p class="font-medium">{cfg.name}</p>
<span class="text-xs px-1.5 py-0.5 rounded bg-[var(--color-muted)] text-[var(--color-muted-foreground)] font-mono">{cfg.provider_type}</span>
<span class="text-xs px-1.5 py-0.5 rounded bg-emerald-500/10 text-emerald-500 font-mono">
<span class="text-xs px-1.5 py-0.5 rounded bg-[var(--color-success-bg)] text-[var(--color-success-fg)] font-mono">
{(cfg.enabled_commands || []).length} {t('commandConfig.commands')}
</span>
</div>