Planificateur « Suggérer » : 4 stratégies (smart / meilleurs d'abord / équilibré / juste ce qu'il faut), compétences+niveaux par tech (édition inline), niveau requis par compétence + par job, carte des tournées (1 couleur/tech, domicile→arrêts, sélecteur de jour), fenêtre de dispatch auj.+demain (dates sélectionnées), règle week-end + placeholder « en attente du quart », clustering + lasso + filtre-date sur la carte, accès rapide « À assigner » (badge). Boîte : liste /conversations allégée (45 Mo → ~1 Mo, 17×) + messages chargés à l'ouverture. Rapports : cache SWR sur revenue-explorer (22×). Session : keep-alive + timeout fetch global + authFetch durci → fin des rechargements manuels. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
82 lines
4.5 KiB
JavaScript
82 lines
4.5 KiB
JavaScript
// Éditeur de thème : regroupe les couleurs PRINCIPALES de l'app (variables --ops-*) en un seul endroit,
|
|
// avec presets (défaut indigo actuel + palette de marque Gigafibre extraite de gigafibre.ca), aperçu live et persistance.
|
|
// But : réduire/uniformiser les couleurs. Chaque token pilote une variable CSS --ops-* (+ miroir Quasar --q-* pour que
|
|
// les composants Quasar suivent). N.B. les ~2000 hex EN DUR dans les pages ne suivent PAS encore (migration séparée).
|
|
import { ref } from 'vue'
|
|
|
|
export const THEME_GROUPS = [
|
|
{ title: 'Marque', hint: "L'accent : boutons, liens, sélections, mises en valeur.", tokens: [
|
|
{ var: '--ops-accent', label: 'Accent (couleur de marque)', quasar: '--q-primary' },
|
|
] },
|
|
{ title: 'Sombre', hint: 'Barre latérale + tableau Dispatch.', tokens: [
|
|
{ var: '--ops-sidebar-bg', label: 'Fond sombre', mirror: '--ops-primary' },
|
|
] },
|
|
{ title: 'Surfaces', hint: 'Fonds, cartes, bordures.', tokens: [
|
|
{ var: '--ops-bg', label: 'Fond de page', mirror: '--ops-bg-light' },
|
|
{ var: '--ops-surface', label: 'Cartes / surfaces' },
|
|
{ var: '--ops-border', label: 'Bordures' },
|
|
{ var: '--ops-bg-hover', label: 'Survol / sélection' },
|
|
] },
|
|
{ title: 'Texte', tokens: [
|
|
{ var: '--ops-text', label: 'Texte principal' },
|
|
{ var: '--ops-text-muted', label: 'Texte discret' },
|
|
] },
|
|
{ title: 'États sémantiques', hint: 'Rôles unifiés (badges, boutons, icônes, notifications) — migrés depuis amber/orange/red/blue.', tokens: [
|
|
{ var: '--ops-success', label: 'Succès — payé, actif, complété', quasar: '--q-positive' },
|
|
{ var: '--ops-warning', label: 'Attention — en attente, priorité moyenne', quasar: '--q-warning' },
|
|
{ var: '--ops-danger', label: 'Erreur — destructif, en retard, urgent', quasar: '--q-negative' },
|
|
{ var: '--ops-info', label: 'Info — liens externes, en cours', quasar: '--q-info' },
|
|
] },
|
|
]
|
|
|
|
// Palettes. `default` = MODERNE (inspirée des refs zentry/marque : vert + near-black + off-white + teinte verte + gris),
|
|
// alignée sur css/app.scss. `vif` = vert lime éclatant (#22c11f de la ref — superbe mais texte blanc moins contrasté sur boutons).
|
|
// `indigo` = ancienne palette (legacy).
|
|
export const PRESETS = {
|
|
default: {
|
|
'--ops-accent': '#16a34a', '--ops-sidebar-bg': '#0d0d0d',
|
|
'--ops-bg': '#f4f5f2', '--ops-surface': '#ffffff', '--ops-border': '#e5e7e2', '--ops-bg-hover': '#dcf5d3',
|
|
'--ops-text': '#0d0d0d', '--ops-text-muted': '#6b7280',
|
|
'--ops-success': '#16a34a', '--ops-warning': '#f59e0b', '--ops-danger': '#ef4444', '--ops-info': '#2563eb',
|
|
},
|
|
vif: {
|
|
'--ops-accent': '#22c11f', '--ops-sidebar-bg': '#0d0d0d',
|
|
'--ops-bg': '#f4f5f2', '--ops-surface': '#ffffff', '--ops-border': '#e5e7e2', '--ops-bg-hover': '#cceecc',
|
|
'--ops-text': '#0d0d0d', '--ops-text-muted': '#6b7280',
|
|
'--ops-success': '#16a34a', '--ops-warning': '#f59e0b', '--ops-danger': '#ef4444', '--ops-info': '#2563eb',
|
|
},
|
|
indigo: {
|
|
'--ops-accent': '#6366f1', '--ops-sidebar-bg': '#111422',
|
|
'--ops-bg': '#f8fafc', '--ops-surface': '#ffffff', '--ops-border': '#e2e8f0', '--ops-bg-hover': '#eef2ff',
|
|
'--ops-text': '#1e293b', '--ops-text-muted': '#64748b',
|
|
'--ops-success': '#10b981', '--ops-warning': '#f59e0b', '--ops-danger': '#ef4444', '--ops-info': '#3b82f6',
|
|
},
|
|
}
|
|
|
|
const KEY = 'ops_theme_v1'
|
|
export const themeVars = ref({})
|
|
export function allTokens () { return THEME_GROUPS.flatMap(g => g.tokens) }
|
|
|
|
// Applique un jeu de couleurs en direct : pose les variables --ops-* (+ miroirs Quasar/alias) sur :root.
|
|
export function applyTheme (vars) {
|
|
const root = document.documentElement
|
|
for (const t of allTokens()) {
|
|
const v = vars[t.var]; if (!v) continue
|
|
root.style.setProperty(t.var, v)
|
|
if (t.mirror) root.style.setProperty(t.mirror, v)
|
|
if (t.quasar) root.style.setProperty(t.quasar, v)
|
|
}
|
|
themeVars.value = { ...vars }
|
|
}
|
|
|
|
// Valeurs effectives courantes (override appliqué OU valeur CSS calculée OU défaut).
|
|
export function currentValues () {
|
|
const cs = getComputedStyle(document.documentElement); const out = {}
|
|
for (const t of allTokens()) out[t.var] = (themeVars.value[t.var] || cs.getPropertyValue(t.var).trim() || PRESETS.default[t.var])
|
|
return out
|
|
}
|
|
|
|
export function saveTheme (vars) { try { localStorage.setItem(KEY, JSON.stringify(vars)) } catch (e) {} applyTheme(vars) }
|
|
export function resetTheme () { try { localStorage.removeItem(KEY) } catch (e) {} applyTheme(PRESETS.default) }
|
|
export function loadSavedTheme () { try { const s = localStorage.getItem(KEY); if (s) applyTheme(JSON.parse(s)) } catch (e) {} }
|