feat: add admin settings UI and integrate dynamic configuration

Add settings page with 4 tabs (Logo, Company, Visibility, Theme) for
managing company branding, social links, sidebar section visibility, and
color themes. Integrate settings store globally so sidebar, footer,
header, and theme respond to admin configuration. Add active/dedicated
customer stat cards to dashboard. Wire up quick-call contacts and
Google review links from settings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 18:45:12 -05:00
parent 1a53e50d91
commit 203fbc2175
26 changed files with 871 additions and 205 deletions

View File

@@ -5,14 +5,18 @@ import { defineStore } from 'pinia'
import type { ThemeOption } from '../types/models'
const STORAGE_KEY = 'user_theme'
const DEFAULT_THEME = 'ocean'
const DEFAULT_THEME = 'dark'
export const AVAILABLE_THEMES: ThemeOption[] = [
{ name: 'ocean', label: 'Ocean', preview: '#ff6600' },
{ name: 'forest', label: 'Forest', preview: '#4ade80' },
{ name: 'sunset', label: 'Sunset', preview: '#fb923c' },
{ name: 'dark', label: 'Dark', preview: '#ff6600' },
{ name: 'vscode-dark', label: 'VS Code Dark', preview: '#569CD6' },
{ name: 'grok-dark', label: 'Grok Dark', preview: '#F05A28' },
{ name: 'arctic', label: 'Arctic', preview: '#06b6d4' },
{ name: 'midnight', label: 'Midnight', preview: '#a78bfa' },
{ name: 'high-contrast', label: 'High Contrast', preview: '#FFD700' },
{ name: 'atom-one-dark', label: 'Atom One Dark', preview: '#61AFEF' },
{ name: 'cobalt2', label: 'Cobalt2', preview: '#FFC600' },
{ name: 'jellyfish', label: 'Jellyfish', preview: '#FF6AC1' },
]
export const useThemeStore = defineStore('theme', () => {
@@ -29,15 +33,16 @@ export const useThemeStore = defineStore('theme', () => {
}
}
function initTheme() {
function initTheme(serverDefault?: string) {
// Validate stored theme is still valid
const storedTheme = localStorage.getItem(STORAGE_KEY)
const validTheme = AVAILABLE_THEMES.find(t => t.name === storedTheme)
if (validTheme) {
currentTheme.value = storedTheme!
} else {
currentTheme.value = DEFAULT_THEME
localStorage.setItem(STORAGE_KEY, DEFAULT_THEME)
const fallback = serverDefault || DEFAULT_THEME
currentTheme.value = fallback
localStorage.setItem(STORAGE_KEY, fallback)
}
document.documentElement.setAttribute('data-theme', currentTheme.value)
}