feat: add theme selection functionality and update theme management in the application, including new themes and improved persistence handling

This commit is contained in:
2025-12-13 17:09:15 -03:00
parent c068715fc1
commit 9e45a43910
8 changed files with 407 additions and 396 deletions

View File

@@ -60,6 +60,7 @@
"marked": "^17.0.1", "marked": "^17.0.1",
"papaparse": "^5.4.1", "papaparse": "^5.4.1",
"svelte-sonner": "^1.0.5", "svelte-sonner": "^1.0.5",
"theme-change": "^2.5.0",
"xlsx": "^0.18.5", "xlsx": "^0.18.5",
"xlsx-js-style": "^1.2.0", "xlsx-js-style": "^1.2.0",
"zod": "^4.1.12" "zod": "^4.1.12"

View File

@@ -21,405 +21,345 @@
@apply border-error bg-base-100 hover:bg-error/60 active:bg-error text-error flex items-center justify-center gap-2 rounded-xl border px-4 py-2 text-center font-medium transition-colors hover:text-white active:text-white; @apply border-error bg-base-100 hover:bg-error/60 active:bg-error text-error flex items-center justify-center gap-2 rounded-xl border px-4 py-2 text-center font-medium transition-colors hover:text-white active:text-white;
} }
/* Tema Aqua (padrão roxo/azul) - customizado para garantir funcionamento */ /* Tema Aqua (padrão roxo/azul) - redefinido como custom para garantir compatibilidade */
html[data-theme='aqua'], @plugin 'daisyui/theme' {
html[data-theme='aqua'] body, name: 'aqua';
[data-theme='aqua'] { default: true;
color-scheme: light; color-scheme: light;
--p: 217 91% 60%; --color-primary: hsl(217 91% 60%);
--pf: 217 91% 50%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(217 91% 60%);
--s: 217 91% 60%; --color-secondary-content: hsl(0 0% 100%);
--sf: 217 91% 50%; --color-accent: hsl(217 91% 60%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 217 91% 60%; --color-neutral: hsl(217 20% 17%);
--af: 217 91% 50%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 217 20% 17%; --color-base-200: hsl(217 20% 95%);
--nf: 217 20% 10%; --color-base-300: hsl(217 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(217 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(217 91% 60%);
--b2: 217 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 217 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 217 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 217 91% 60%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
/* Temas customizados para SGSE - Azul */ /* Temas customizados para SGSE */
html[data-theme='sgse-blue'],
html[data-theme='sgse-blue'] body, /* Azul */
[data-theme='sgse-blue'] { @plugin 'daisyui/theme' {
name: 'sgse-blue';
color-scheme: light; color-scheme: light;
--p: 217 91% 60%; --color-primary: hsl(217 91% 60%);
--pf: 217 91% 50%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(217 91% 60%);
--s: 217 91% 60%; --color-secondary-content: hsl(0 0% 100%);
--sf: 217 91% 50%; --color-accent: hsl(217 91% 60%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 217 91% 60%; --color-neutral: hsl(217 20% 17%);
--af: 217 91% 50%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 217 20% 17%; --color-base-200: hsl(217 20% 95%);
--nf: 217 20% 10%; --color-base-300: hsl(217 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(217 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(217 91% 60%);
--b2: 217 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 217 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 217 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 217 91% 60%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
/* Garantir que todas as variáveis CSS sejam aplicadas em todos os elementos */ /* Verde */
html[data-theme] { @plugin 'daisyui/theme' {
color-scheme: var(--color-scheme, light); name: 'sgse-green';
}
html[data-theme] * {
color-scheme: inherit;
}
html[data-theme='sgse-green'],
html[data-theme='sgse-green'] body,
[data-theme='sgse-green'] {
color-scheme: light; color-scheme: light;
--p: 142 76% 36%; --color-primary: hsl(142 76% 36%);
--pf: 142 76% 26%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(142 76% 36%);
--s: 142 76% 36%; --color-secondary-content: hsl(0 0% 100%);
--sf: 142 76% 26%; --color-accent: hsl(142 76% 36%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 142 76% 36%; --color-neutral: hsl(142 20% 17%);
--af: 142 76% 26%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 142 20% 17%; --color-base-200: hsl(142 20% 95%);
--nf: 142 20% 10%; --color-base-300: hsl(142 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(142 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(142 76% 36%);
--b2: 142 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 142 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 142 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 142 76% 36%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
html[data-theme='sgse-orange'], /* Laranja */
html[data-theme='sgse-orange'] body, @plugin 'daisyui/theme' {
[data-theme='sgse-orange'] { name: 'sgse-orange';
color-scheme: light; color-scheme: light;
--p: 25 95% 53%; --color-primary: hsl(25 95% 53%);
--pf: 25 95% 43%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(25 95% 53%);
--s: 25 95% 53%; --color-secondary-content: hsl(0 0% 100%);
--sf: 25 95% 43%; --color-accent: hsl(25 95% 53%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 25 95% 53%; --color-neutral: hsl(25 20% 17%);
--af: 25 95% 43%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 25 20% 17%; --color-base-200: hsl(25 20% 95%);
--nf: 25 20% 10%; --color-base-300: hsl(25 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(25 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(25 95% 53%);
--b2: 25 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 25 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 25 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 25 95% 53%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
html[data-theme='sgse-red'], /* Vermelho */
html[data-theme='sgse-red'] body, @plugin 'daisyui/theme' {
[data-theme='sgse-red'] { name: 'sgse-red';
color-scheme: light; color-scheme: light;
--p: 0 84% 60%; --color-primary: hsl(0 84% 60%);
--pf: 0 84% 50%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(0 84% 60%);
--s: 0 84% 60%; --color-secondary-content: hsl(0 0% 100%);
--sf: 0 84% 50%; --color-accent: hsl(0 84% 60%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 0 84% 60%; --color-neutral: hsl(0 20% 17%);
--af: 0 84% 50%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 0 20% 17%; --color-base-200: hsl(0 20% 95%);
--nf: 0 20% 10%; --color-base-300: hsl(0 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(0 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(0 84% 60%);
--b2: 0 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 0 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 0 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 0 84% 60%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
html[data-theme='sgse-pink'], /* Rosa */
html[data-theme='sgse-pink'] body, @plugin 'daisyui/theme' {
[data-theme='sgse-pink'] { name: 'sgse-pink';
color-scheme: light; color-scheme: light;
--p: 330 81% 60%; --color-primary: hsl(330 81% 60%);
--pf: 330 81% 50%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(330 81% 60%);
--s: 330 81% 60%; --color-secondary-content: hsl(0 0% 100%);
--sf: 330 81% 50%; --color-accent: hsl(330 81% 60%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 330 81% 60%; --color-neutral: hsl(330 20% 17%);
--af: 330 81% 50%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 330 20% 17%; --color-base-200: hsl(330 20% 95%);
--nf: 330 20% 10%; --color-base-300: hsl(330 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(330 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(330 81% 60%);
--b2: 330 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 330 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 330 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 330 81% 60%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
html[data-theme='sgse-teal'], /* Teal */
html[data-theme='sgse-teal'] body, @plugin 'daisyui/theme' {
[data-theme='sgse-teal'] { name: 'sgse-teal';
color-scheme: light; color-scheme: light;
--p: 173 80% 40%; --color-primary: hsl(173 80% 40%);
--pf: 173 80% 30%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(173 80% 40%);
--s: 173 80% 40%; --color-secondary-content: hsl(0 0% 100%);
--sf: 173 80% 30%; --color-accent: hsl(173 80% 40%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 173 80% 40%; --color-neutral: hsl(173 20% 17%);
--af: 173 80% 30%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 173 20% 17%; --color-base-200: hsl(173 20% 95%);
--nf: 173 20% 10%; --color-base-300: hsl(173 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(173 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(173 80% 40%);
--b2: 173 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 173 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 173 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 173 80% 40%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
html[data-theme='sgse-corporate'], /* Corporativo (Dark Blue) */
html[data-theme='sgse-corporate'] body, @plugin 'daisyui/theme' {
[data-theme='sgse-corporate'] { name: 'sgse-corporate';
color-scheme: dark; color-scheme: dark;
--p: 217 91% 60%; --color-primary: hsl(217 91% 60%);
--pf: 217 91% 50%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(217 91% 60%);
--s: 217 91% 60%; --color-secondary-content: hsl(0 0% 100%);
--sf: 217 91% 50%; --color-accent: hsl(217 91% 60%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 217 91% 60%; --color-neutral: hsl(217 30% 15%);
--af: 217 91% 50%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(217 30% 10%);
--n: 217 30% 15%; --color-base-200: hsl(217 30% 15%);
--nf: 217 30% 8%; --color-base-300: hsl(217 30% 20%);
--nc: 0 0% 100%; --color-base-content: hsl(217 10% 90%);
--b1: 217 30% 10%; --color-info: hsl(217 91% 60%);
--b2: 217 30% 15%; --color-info-content: hsl(0 0% 100%);
--b3: 217 30% 20%; --color-success: hsl(142 76% 36%);
--bc: 217 10% 90%; --color-success-content: hsl(0 0% 100%);
--in: 217 91% 60%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
/* Tema Light customizado para garantir funcionamento completo */ /* Light */
html[data-theme='light'], @plugin 'daisyui/theme' {
html[data-theme='light'] body, name: 'light';
[data-theme='light'] {
color-scheme: light; color-scheme: light;
--p: 217 91% 60%; --color-primary: hsl(217 91% 60%);
--pf: 217 91% 50%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(217 91% 60%);
--s: 217 91% 60%; --color-secondary-content: hsl(0 0% 100%);
--sf: 217 91% 50%; --color-accent: hsl(217 91% 60%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 217 91% 60%; --color-neutral: hsl(217 20% 17%);
--af: 217 91% 50%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(0 0% 100%);
--n: 217 20% 17%; --color-base-200: hsl(217 20% 95%);
--nf: 217 20% 10%; --color-base-300: hsl(217 20% 90%);
--nc: 0 0% 100%; --color-base-content: hsl(217 20% 17%);
--b1: 0 0% 100%; --color-info: hsl(217 91% 60%);
--b2: 217 20% 95%; --color-info-content: hsl(0 0% 100%);
--b3: 217 20% 90%; --color-success: hsl(142 76% 36%);
--bc: 217 20% 17%; --color-success-content: hsl(0 0% 100%);
--in: 217 91% 60%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }
/* Tema Dark customizado para garantir funcionamento completo */ /* Dark */
html[data-theme='dark'], @plugin 'daisyui/theme' {
html[data-theme='dark'] body, name: 'dark';
[data-theme='dark'] {
color-scheme: dark; color-scheme: dark;
--p: 217 91% 60%; --color-primary: hsl(217 91% 60%);
--pf: 217 91% 50%; --color-primary-content: hsl(0 0% 100%);
--pc: 0 0% 100%; --color-secondary: hsl(217 91% 60%);
--s: 217 91% 60%; --color-secondary-content: hsl(0 0% 100%);
--sf: 217 91% 50%; --color-accent: hsl(217 91% 60%);
--sc: 0 0% 100%; --color-accent-content: hsl(0 0% 100%);
--a: 217 91% 60%; --color-neutral: hsl(217 30% 15%);
--af: 217 91% 50%; --color-neutral-content: hsl(0 0% 100%);
--ac: 0 0% 100%; --color-base-100: hsl(217 30% 10%);
--n: 217 30% 15%; --color-base-200: hsl(217 30% 15%);
--nf: 217 30% 8%; --color-base-300: hsl(217 30% 20%);
--nc: 0 0% 100%; --color-base-content: hsl(217 10% 90%);
--b1: 217 30% 10%; --color-info: hsl(217 91% 60%);
--b2: 217 30% 15%; --color-info-content: hsl(0 0% 100%);
--b3: 217 30% 20%; --color-success: hsl(142 76% 36%);
--bc: 217 10% 90%; --color-success-content: hsl(0 0% 100%);
--in: 217 91% 60%; --color-warning: hsl(38 92% 50%);
--inc: 0 0% 100%; --color-warning-content: hsl(0 0% 100%);
--su: 142 76% 36%; --color-error: hsl(0 84% 60%);
--suc: 0 0% 100%; --color-error-content: hsl(0 0% 100%);
--wa: 38 92% 50%; --radius-selector: 0.5rem;
--wac: 0 0% 100%; --radius-field: 0.5rem;
--er: 0 84% 60%; --radius-box: 1rem;
--erc: 0 0% 100%; --size-selector: 0.25rem;
--rounded-box: 1rem; --size-field: 0.25rem;
--rounded-btn: 0.5rem; --border: 1px;
--rounded-badge: 1.9rem; --depth: 1;
--animation-btn: 0.25s; --noise: 0;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
} }

View File

@@ -111,8 +111,17 @@
(function () { (function () {
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
var html = document.documentElement; var html = document.documentElement;
if (!html.getAttribute('data-theme')) { if (html && !html.getAttribute('data-theme')) {
html.setAttribute('data-theme', 'aqua'); var tema = null;
try {
// theme-change usa por padrão a chave "theme"
tema = localStorage.getItem('theme');
} catch (e) {
tema = null;
}
// Fallback para o tema padrão se não houver persistência
html.setAttribute('data-theme', tema || 'aqua');
} }
} }
})(); })();

View File

@@ -35,6 +35,23 @@
</div> </div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<select
class="select select-sm bg-base-100 border-base-300 w-40"
aria-label="Selecionar tema"
data-choose-theme
>
<option value="aqua">Aqua</option>
<option value="sgse-blue">Azul</option>
<option value="sgse-green">Verde</option>
<option value="sgse-orange">Laranja</option>
<option value="sgse-red">Vermelho</option>
<option value="sgse-pink">Rosa</option>
<option value="sgse-teal">Verde-água</option>
<option value="sgse-corporate">Corporativo</option>
<option value="light">Claro</option>
<option value="dark">Escuro</option>
</select>
{#if right} {#if right}
{@render right()} {@render right()}
{/if} {/if}

View File

@@ -153,20 +153,15 @@ export function aplicarTema(temaId: TemaId | string | null | undefined): void {
const nomeDaisyUI = obterNomeDaisyUI(temaId || 'purple'); const nomeDaisyUI = obterNomeDaisyUI(temaId || 'purple');
const htmlElement = document.documentElement; const htmlElement = document.documentElement;
const bodyElement = document.body;
if (htmlElement) { if (htmlElement) {
// Remover todos os atributos data-theme existentes primeiro // Remover todos os atributos data-theme existentes primeiro
htmlElement.removeAttribute('data-theme'); htmlElement.removeAttribute('data-theme');
if (bodyElement) { // Evita que `body[data-theme]` sobrescreva o tema do `<html>`
bodyElement.removeAttribute('data-theme'); if (document.body) document.body.removeAttribute('data-theme');
}
// Aplicar o novo tema // Aplicar o novo tema
htmlElement.setAttribute('data-theme', nomeDaisyUI); htmlElement.setAttribute('data-theme', nomeDaisyUI);
if (bodyElement) {
bodyElement.setAttribute('data-theme', nomeDaisyUI);
}
// Forçar reflow para garantir que o CSS seja aplicado // Forçar reflow para garantir que o CSS seja aplicado
void htmlElement.offsetHeight; void htmlElement.offsetHeight;
@@ -230,20 +225,21 @@ export function obterCoresDoTema(): {
} }
const htmlElement = document.documentElement; const htmlElement = document.documentElement;
const getComputedStyle = (varName: string): string => { const readCssVar = (varName: string): string => {
return getComputedStyle(htmlElement).getPropertyValue(varName).trim() || ''; return window.getComputedStyle(htmlElement).getPropertyValue(varName).trim() || '';
}; };
// Tentar obter variáveis CSS do DaisyUI // DaisyUI v5: variáveis `--color-*`
const primary = getComputedStyle('--p') || '#667eea'; // Fallback para v4/legado: variáveis curtas `--p`, `--suc`, etc.
const success = getComputedStyle('--suc') || '#10b981'; const primary = readCssVar('--color-primary') || readCssVar('--p') || '#667eea';
const error = getComputedStyle('--er') || '#ef4444'; const success = readCssVar('--color-success') || readCssVar('--suc') || '#10b981';
const warning = getComputedStyle('--wa') || '#f59e0b'; const error = readCssVar('--color-error') || readCssVar('--er') || '#ef4444';
const info = getComputedStyle('--in') || '#3b82f6'; const warning = readCssVar('--color-warning') || readCssVar('--wa') || '#f59e0b';
const baseContent = getComputedStyle('--bc') || '#1f2937'; const info = readCssVar('--color-info') || readCssVar('--in') || '#3b82f6';
const base100 = getComputedStyle('--b1') || '#ffffff'; const baseContent = readCssVar('--color-base-content') || readCssVar('--bc') || '#1f2937';
const base200 = getComputedStyle('--b2') || '#f3f4f6'; const base100 = readCssVar('--color-base-100') || readCssVar('--b1') || '#ffffff';
const base300 = getComputedStyle('--b3') || '#e5e7eb'; const base200 = readCssVar('--color-base-200') || readCssVar('--b2') || '#f3f4f6';
const base300 = readCssVar('--color-base-300') || readCssVar('--b3') || '#e5e7eb';
return { return {
primary: primary || '#667eea', primary: primary || '#667eea',

View File

@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import '../app.css'; import '../app.css';
import { onMount } from 'svelte';
import { createSvelteAuthClient } from '@mmailaender/convex-better-auth-svelte/svelte'; import { createSvelteAuthClient } from '@mmailaender/convex-better-auth-svelte/svelte';
import { authClient } from '$lib/auth'; import { authClient } from '$lib/auth';
// Importar polyfill ANTES de qualquer outro código que possa usar Jitsi // Importar polyfill ANTES de qualquer outro código que possa usar Jitsi
@@ -7,6 +8,7 @@
import { useQuery } from 'convex-svelte'; import { useQuery } from 'convex-svelte';
import { api } from '@sgse-app/backend/convex/_generated/api'; import { api } from '@sgse-app/backend/convex/_generated/api';
import { aplicarTema, aplicarTemaPadrao } from '$lib/utils/temas'; import { aplicarTema, aplicarTemaPadrao } from '$lib/utils/temas';
import { themeChange } from 'theme-change';
const { children } = $props(); const { children } = $props();
@@ -15,6 +17,36 @@
// Buscar usuário atual para aplicar tema // Buscar usuário atual para aplicar tema
const currentUser = useQuery(api.auth.getCurrentUser, {}); const currentUser = useQuery(api.auth.getCurrentUser, {});
function obterTemaPersistido(): string | null {
if (typeof window === 'undefined') return null;
try {
const tema = window.localStorage.getItem('theme');
return tema && tema.trim() ? tema : null;
} catch {
return null;
}
}
function aplicarTemaDaisyUI(tema: string): void {
if (typeof document === 'undefined') return;
const htmlElement = document.documentElement;
htmlElement.setAttribute('data-theme', tema);
// Evita que `body[data-theme]` sobrescreva o tema do `<html>`
if (document.body) document.body.removeAttribute('data-theme');
}
onMount(() => {
// Habilita `data-set-theme` e `data-choose-theme` e persiste em localStorage ("theme")
// Em Svelte, precisamos passar `false` para não depender de `DOMContentLoaded`
themeChange(false);
// Garante que o tema persistido no device tenha prioridade
const temaPersistido = obterTemaPersistido();
if (temaPersistido) {
aplicarTemaDaisyUI(temaPersistido);
}
});
// Aplicar tema quando o usuário for carregado // Aplicar tema quando o usuário for carregado
$effect(() => { $effect(() => {
if (typeof document === 'undefined') return; if (typeof document === 'undefined') return;
@@ -23,6 +55,13 @@
// Aguardar um pouco para garantir que o DOM está pronto // Aguardar um pouco para garantir que o DOM está pronto
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
const temaPersistido = obterTemaPersistido();
if (temaPersistido) {
// Prioridade do device (localStorage) mesmo para usuários logados
aplicarTemaDaisyUI(temaPersistido);
return;
}
if (currentUser?.data?.temaPreferido) { if (currentUser?.data?.temaPreferido) {
// Usuário logado com tema preferido - aplicar tema salvo // Usuário logado com tema preferido - aplicar tema salvo
aplicarTema(currentUser.data.temaPreferido); aplicarTema(currentUser.data.temaPreferido);
@@ -40,6 +79,12 @@
// Aplicar tema padrão imediatamente ao carregar (antes de verificar usuário) // Aplicar tema padrão imediatamente ao carregar (antes de verificar usuário)
$effect(() => { $effect(() => {
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
const temaPersistido = obterTemaPersistido();
if (temaPersistido) {
aplicarTemaDaisyUI(temaPersistido);
return;
}
// Se não há tema aplicado ainda, aplicar o padrão imediatamente // Se não há tema aplicado ainda, aplicar o padrão imediatamente
const htmlElement = document.documentElement; const htmlElement = document.documentElement;
if (!htmlElement.getAttribute('data-theme')) { if (!htmlElement.getAttribute('data-theme')) {

View File

@@ -58,6 +58,7 @@
"marked": "^17.0.1", "marked": "^17.0.1",
"papaparse": "^5.4.1", "papaparse": "^5.4.1",
"svelte-sonner": "^1.0.5", "svelte-sonner": "^1.0.5",
"theme-change": "^2.5.0",
"xlsx": "^0.18.5", "xlsx": "^0.18.5",
"xlsx-js-style": "^1.2.0", "xlsx-js-style": "^1.2.0",
"zod": "^4.1.12", "zod": "^4.1.12",
@@ -132,7 +133,7 @@
"catalog": { "catalog": {
"@eslint/js": "^9.39.1", "@eslint/js": "^9.39.1",
"better-auth": "1.3.34", "better-auth": "1.3.34",
"convex": "^1.28.2", "convex": "^1.31.0",
"eslint": "^9.39.1", "eslint": "^9.39.1",
"typescript": "^5.9.2", "typescript": "^5.9.2",
}, },
@@ -1461,6 +1462,8 @@
"text-segmentation": ["text-segmentation@1.0.3", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw=="], "text-segmentation": ["text-segmentation@1.0.3", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw=="],
"theme-change": ["theme-change@2.5.0", "", {}, "sha512-B/UdsgdHAGhSKHTAQnxg/etN0RaMDpehuJmZIjLMDVJ6DGIliRHGD6pODi1CXLQAN9GV0GSyB3G6yCuK05PkPQ=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
"tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="], "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="],

View File

@@ -48,5 +48,5 @@
"svelte-chartjs": "^3.1.5", "svelte-chartjs": "^3.1.5",
"svelte-sonner": "^1.0.7" "svelte-sonner": "^1.0.7"
}, },
"packageManager": "bun@1.3.0" "packageManager": "bun@1.3.4"
} }