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",
"papaparse": "^5.4.1",
"svelte-sonner": "^1.0.5",
"theme-change": "^2.5.0",
"xlsx": "^0.18.5",
"xlsx-js-style": "^1.2.0",
"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;
}
/* Tema Aqua (padrão roxo/azul) - customizado para garantir funcionamento */
html[data-theme='aqua'],
html[data-theme='aqua'] body,
[data-theme='aqua'] {
/* Tema Aqua (padrão roxo/azul) - redefinido como custom para garantir compatibilidade */
@plugin 'daisyui/theme' {
name: 'aqua';
default: true;
color-scheme: light;
--p: 217 91% 60%;
--pf: 217 91% 50%;
--pc: 0 0% 100%;
--s: 217 91% 60%;
--sf: 217 91% 50%;
--sc: 0 0% 100%;
--a: 217 91% 60%;
--af: 217 91% 50%;
--ac: 0 0% 100%;
--n: 217 20% 17%;
--nf: 217 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 217 20% 95%;
--b3: 217 20% 90%;
--bc: 217 20% 17%;
--in: 217 91% 60%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(217 91% 60%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(217 91% 60%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(217 91% 60%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(217 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(217 20% 95%);
--color-base-300: hsl(217 20% 90%);
--color-base-content: hsl(217 20% 17%);
--color-info: hsl(217 91% 60%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
/* Temas customizados para SGSE - Azul */
html[data-theme='sgse-blue'],
html[data-theme='sgse-blue'] body,
[data-theme='sgse-blue'] {
/* Temas customizados para SGSE */
/* Azul */
@plugin 'daisyui/theme' {
name: 'sgse-blue';
color-scheme: light;
--p: 217 91% 60%;
--pf: 217 91% 50%;
--pc: 0 0% 100%;
--s: 217 91% 60%;
--sf: 217 91% 50%;
--sc: 0 0% 100%;
--a: 217 91% 60%;
--af: 217 91% 50%;
--ac: 0 0% 100%;
--n: 217 20% 17%;
--nf: 217 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 217 20% 95%;
--b3: 217 20% 90%;
--bc: 217 20% 17%;
--in: 217 91% 60%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(217 91% 60%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(217 91% 60%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(217 91% 60%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(217 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(217 20% 95%);
--color-base-300: hsl(217 20% 90%);
--color-base-content: hsl(217 20% 17%);
--color-info: hsl(217 91% 60%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
/* Garantir que todas as variáveis CSS sejam aplicadas em todos os elementos */
html[data-theme] {
color-scheme: var(--color-scheme, light);
}
html[data-theme] * {
color-scheme: inherit;
}
html[data-theme='sgse-green'],
html[data-theme='sgse-green'] body,
[data-theme='sgse-green'] {
/* Verde */
@plugin 'daisyui/theme' {
name: 'sgse-green';
color-scheme: light;
--p: 142 76% 36%;
--pf: 142 76% 26%;
--pc: 0 0% 100%;
--s: 142 76% 36%;
--sf: 142 76% 26%;
--sc: 0 0% 100%;
--a: 142 76% 36%;
--af: 142 76% 26%;
--ac: 0 0% 100%;
--n: 142 20% 17%;
--nf: 142 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 142 20% 95%;
--b3: 142 20% 90%;
--bc: 142 20% 17%;
--in: 142 76% 36%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(142 76% 36%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(142 76% 36%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(142 76% 36%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(142 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(142 20% 95%);
--color-base-300: hsl(142 20% 90%);
--color-base-content: hsl(142 20% 17%);
--color-info: hsl(142 76% 36%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
html[data-theme='sgse-orange'],
html[data-theme='sgse-orange'] body,
[data-theme='sgse-orange'] {
/* Laranja */
@plugin 'daisyui/theme' {
name: 'sgse-orange';
color-scheme: light;
--p: 25 95% 53%;
--pf: 25 95% 43%;
--pc: 0 0% 100%;
--s: 25 95% 53%;
--sf: 25 95% 43%;
--sc: 0 0% 100%;
--a: 25 95% 53%;
--af: 25 95% 43%;
--ac: 0 0% 100%;
--n: 25 20% 17%;
--nf: 25 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 25 20% 95%;
--b3: 25 20% 90%;
--bc: 25 20% 17%;
--in: 25 95% 53%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(25 95% 53%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(25 95% 53%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(25 95% 53%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(25 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(25 20% 95%);
--color-base-300: hsl(25 20% 90%);
--color-base-content: hsl(25 20% 17%);
--color-info: hsl(25 95% 53%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
html[data-theme='sgse-red'],
html[data-theme='sgse-red'] body,
[data-theme='sgse-red'] {
/* Vermelho */
@plugin 'daisyui/theme' {
name: 'sgse-red';
color-scheme: light;
--p: 0 84% 60%;
--pf: 0 84% 50%;
--pc: 0 0% 100%;
--s: 0 84% 60%;
--sf: 0 84% 50%;
--sc: 0 0% 100%;
--a: 0 84% 60%;
--af: 0 84% 50%;
--ac: 0 0% 100%;
--n: 0 20% 17%;
--nf: 0 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 0 20% 95%;
--b3: 0 20% 90%;
--bc: 0 20% 17%;
--in: 0 84% 60%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(0 84% 60%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(0 84% 60%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(0 84% 60%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(0 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(0 20% 95%);
--color-base-300: hsl(0 20% 90%);
--color-base-content: hsl(0 20% 17%);
--color-info: hsl(0 84% 60%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
html[data-theme='sgse-pink'],
html[data-theme='sgse-pink'] body,
[data-theme='sgse-pink'] {
/* Rosa */
@plugin 'daisyui/theme' {
name: 'sgse-pink';
color-scheme: light;
--p: 330 81% 60%;
--pf: 330 81% 50%;
--pc: 0 0% 100%;
--s: 330 81% 60%;
--sf: 330 81% 50%;
--sc: 0 0% 100%;
--a: 330 81% 60%;
--af: 330 81% 50%;
--ac: 0 0% 100%;
--n: 330 20% 17%;
--nf: 330 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 330 20% 95%;
--b3: 330 20% 90%;
--bc: 330 20% 17%;
--in: 330 81% 60%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(330 81% 60%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(330 81% 60%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(330 81% 60%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(330 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(330 20% 95%);
--color-base-300: hsl(330 20% 90%);
--color-base-content: hsl(330 20% 17%);
--color-info: hsl(330 81% 60%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
html[data-theme='sgse-teal'],
html[data-theme='sgse-teal'] body,
[data-theme='sgse-teal'] {
/* Teal */
@plugin 'daisyui/theme' {
name: 'sgse-teal';
color-scheme: light;
--p: 173 80% 40%;
--pf: 173 80% 30%;
--pc: 0 0% 100%;
--s: 173 80% 40%;
--sf: 173 80% 30%;
--sc: 0 0% 100%;
--a: 173 80% 40%;
--af: 173 80% 30%;
--ac: 0 0% 100%;
--n: 173 20% 17%;
--nf: 173 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 173 20% 95%;
--b3: 173 20% 90%;
--bc: 173 20% 17%;
--in: 173 80% 40%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(173 80% 40%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(173 80% 40%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(173 80% 40%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(173 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(173 20% 95%);
--color-base-300: hsl(173 20% 90%);
--color-base-content: hsl(173 20% 17%);
--color-info: hsl(173 80% 40%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
html[data-theme='sgse-corporate'],
html[data-theme='sgse-corporate'] body,
[data-theme='sgse-corporate'] {
/* Corporativo (Dark Blue) */
@plugin 'daisyui/theme' {
name: 'sgse-corporate';
color-scheme: dark;
--p: 217 91% 60%;
--pf: 217 91% 50%;
--pc: 0 0% 100%;
--s: 217 91% 60%;
--sf: 217 91% 50%;
--sc: 0 0% 100%;
--a: 217 91% 60%;
--af: 217 91% 50%;
--ac: 0 0% 100%;
--n: 217 30% 15%;
--nf: 217 30% 8%;
--nc: 0 0% 100%;
--b1: 217 30% 10%;
--b2: 217 30% 15%;
--b3: 217 30% 20%;
--bc: 217 10% 90%;
--in: 217 91% 60%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(217 91% 60%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(217 91% 60%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(217 91% 60%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(217 30% 15%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(217 30% 10%);
--color-base-200: hsl(217 30% 15%);
--color-base-300: hsl(217 30% 20%);
--color-base-content: hsl(217 10% 90%);
--color-info: hsl(217 91% 60%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
/* Tema Light customizado para garantir funcionamento completo */
html[data-theme='light'],
html[data-theme='light'] body,
[data-theme='light'] {
/* Light */
@plugin 'daisyui/theme' {
name: 'light';
color-scheme: light;
--p: 217 91% 60%;
--pf: 217 91% 50%;
--pc: 0 0% 100%;
--s: 217 91% 60%;
--sf: 217 91% 50%;
--sc: 0 0% 100%;
--a: 217 91% 60%;
--af: 217 91% 50%;
--ac: 0 0% 100%;
--n: 217 20% 17%;
--nf: 217 20% 10%;
--nc: 0 0% 100%;
--b1: 0 0% 100%;
--b2: 217 20% 95%;
--b3: 217 20% 90%;
--bc: 217 20% 17%;
--in: 217 91% 60%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(217 91% 60%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(217 91% 60%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(217 91% 60%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(217 20% 17%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(0 0% 100%);
--color-base-200: hsl(217 20% 95%);
--color-base-300: hsl(217 20% 90%);
--color-base-content: hsl(217 20% 17%);
--color-info: hsl(217 91% 60%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
/* Tema Dark customizado para garantir funcionamento completo */
html[data-theme='dark'],
html[data-theme='dark'] body,
[data-theme='dark'] {
/* Dark */
@plugin 'daisyui/theme' {
name: 'dark';
color-scheme: dark;
--p: 217 91% 60%;
--pf: 217 91% 50%;
--pc: 0 0% 100%;
--s: 217 91% 60%;
--sf: 217 91% 50%;
--sc: 0 0% 100%;
--a: 217 91% 60%;
--af: 217 91% 50%;
--ac: 0 0% 100%;
--n: 217 30% 15%;
--nf: 217 30% 8%;
--nc: 0 0% 100%;
--b1: 217 30% 10%;
--b2: 217 30% 15%;
--b3: 217 30% 20%;
--bc: 217 10% 90%;
--in: 217 91% 60%;
--inc: 0 0% 100%;
--su: 142 76% 36%;
--suc: 0 0% 100%;
--wa: 38 92% 50%;
--wac: 0 0% 100%;
--er: 0 84% 60%;
--erc: 0 0% 100%;
--rounded-box: 1rem;
--rounded-btn: 0.5rem;
--rounded-badge: 1.9rem;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
--border-btn: 1px;
--tab-border: 1px;
--tab-radius: 0.5rem;
--color-primary: hsl(217 91% 60%);
--color-primary-content: hsl(0 0% 100%);
--color-secondary: hsl(217 91% 60%);
--color-secondary-content: hsl(0 0% 100%);
--color-accent: hsl(217 91% 60%);
--color-accent-content: hsl(0 0% 100%);
--color-neutral: hsl(217 30% 15%);
--color-neutral-content: hsl(0 0% 100%);
--color-base-100: hsl(217 30% 10%);
--color-base-200: hsl(217 30% 15%);
--color-base-300: hsl(217 30% 20%);
--color-base-content: hsl(217 10% 90%);
--color-info: hsl(217 91% 60%);
--color-info-content: hsl(0 0% 100%);
--color-success: hsl(142 76% 36%);
--color-success-content: hsl(0 0% 100%);
--color-warning: hsl(38 92% 50%);
--color-warning-content: hsl(0 0% 100%);
--color-error: hsl(0 84% 60%);
--color-error-content: hsl(0 0% 100%);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}

View File

@@ -111,8 +111,17 @@
(function () {
if (typeof document !== 'undefined') {
var html = document.documentElement;
if (!html.getAttribute('data-theme')) {
html.setAttribute('data-theme', 'aqua');
if (html && !html.getAttribute('data-theme')) {
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 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}
{@render right()}
{/if}

View File

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

View File

@@ -1,5 +1,6 @@
<script lang="ts">
import '../app.css';
import { onMount } from 'svelte';
import { createSvelteAuthClient } from '@mmailaender/convex-better-auth-svelte/svelte';
import { authClient } from '$lib/auth';
// Importar polyfill ANTES de qualquer outro código que possa usar Jitsi
@@ -7,6 +8,7 @@
import { useQuery } from 'convex-svelte';
import { api } from '@sgse-app/backend/convex/_generated/api';
import { aplicarTema, aplicarTemaPadrao } from '$lib/utils/temas';
import { themeChange } from 'theme-change';
const { children } = $props();
@@ -15,6 +17,36 @@
// Buscar usuário atual para aplicar tema
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
$effect(() => {
if (typeof document === 'undefined') return;
@@ -23,6 +55,13 @@
// Aguardar um pouco para garantir que o DOM está pronto
const timeoutId = setTimeout(() => {
const temaPersistido = obterTemaPersistido();
if (temaPersistido) {
// Prioridade do device (localStorage) mesmo para usuários logados
aplicarTemaDaisyUI(temaPersistido);
return;
}
if (currentUser?.data?.temaPreferido) {
// Usuário logado com tema preferido - aplicar tema salvo
aplicarTema(currentUser.data.temaPreferido);
@@ -40,6 +79,12 @@
// Aplicar tema padrão imediatamente ao carregar (antes de verificar usuário)
$effect(() => {
if (typeof document !== 'undefined') {
const temaPersistido = obterTemaPersistido();
if (temaPersistido) {
aplicarTemaDaisyUI(temaPersistido);
return;
}
// Se não há tema aplicado ainda, aplicar o padrão imediatamente
const htmlElement = document.documentElement;
if (!htmlElement.getAttribute('data-theme')) {

View File

@@ -58,6 +58,7 @@
"marked": "^17.0.1",
"papaparse": "^5.4.1",
"svelte-sonner": "^1.0.5",
"theme-change": "^2.5.0",
"xlsx": "^0.18.5",
"xlsx-js-style": "^1.2.0",
"zod": "^4.1.12",
@@ -132,7 +133,7 @@
"catalog": {
"@eslint/js": "^9.39.1",
"better-auth": "1.3.34",
"convex": "^1.28.2",
"convex": "^1.31.0",
"eslint": "^9.39.1",
"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=="],
"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=="],
"tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="],

View File

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