From 4faf279c3e396d480362d9f58b050cda1d9f1a40 Mon Sep 17 00:00:00 2001 From: killer-cf Date: Sat, 13 Dec 2025 20:05:27 -0300 Subject: [PATCH 1/2] feat: refine login page functionality by adding validation, improving error handling, and enhancing user feedback mechanisms --- apps/web/src/lib/components/ui/Button.svelte | 128 +++++++++ apps/web/src/lib/components/ui/Input.svelte | 174 +++++++++++ apps/web/src/lib/components/ui/Select.svelte | 287 +++++++++++++++++++ 3 files changed, 589 insertions(+) create mode 100644 apps/web/src/lib/components/ui/Button.svelte create mode 100644 apps/web/src/lib/components/ui/Input.svelte create mode 100644 apps/web/src/lib/components/ui/Select.svelte diff --git a/apps/web/src/lib/components/ui/Button.svelte b/apps/web/src/lib/components/ui/Button.svelte new file mode 100644 index 0000000..e7ab5d8 --- /dev/null +++ b/apps/web/src/lib/components/ui/Button.svelte @@ -0,0 +1,128 @@ + + + diff --git a/apps/web/src/lib/components/ui/Input.svelte b/apps/web/src/lib/components/ui/Input.svelte new file mode 100644 index 0000000..f170a9d --- /dev/null +++ b/apps/web/src/lib/components/ui/Input.svelte @@ -0,0 +1,174 @@ + + + +
+ + {label} + + {@render right?.()} +
+ +
+ {#if left} +
+
+ {@render left()} +
+
+ {/if} + + + + {#if right} +
+
+ {@render right()} +
+
+ {/if} +
+ + {#if helperText && !error} + + {helperText} + + {/if} + + {#if error} + + {error} + + {/if} +
diff --git a/apps/web/src/lib/components/ui/Select.svelte b/apps/web/src/lib/components/ui/Select.svelte new file mode 100644 index 0000000..d94f806 --- /dev/null +++ b/apps/web/src/lib/components/ui/Select.svelte @@ -0,0 +1,287 @@ + + + +
+ + {label} + + {@render labelRight?.()} +
+ + + + +
+ {#if triggerLeft} + + {@render triggerLeft()} + + {/if} + +
+ +
+ {#if canClear} + + + + {/if} + + + +
+
+
+ + + + +
+ {#if hasGroups} + {#each groups as [groupLabel, groupItems] (groupLabel)} + + + {groupLabel} + + {#each groupItems as item (item.value)} + + {item.label} + + + + + {/each} + + {/each} + {:else} + {#each items as item (item.value)} + + {item.label} + + + + + {/each} + {/if} +
+
+
+
+ + +
+ + {#if helperText && !error} + + {helperText} + + {/if} + + {#if error} + + {error} + + {/if} +
From c272ca05e88ac0b6f3003011fc49ebd3a87fa33e Mon Sep 17 00:00:00 2001 From: killer-cf Date: Mon, 15 Dec 2025 09:01:56 -0300 Subject: [PATCH 2/2] feat: implement theme persistence and selection in header component, enhancing user experience with localStorage integration --- apps/web/src/lib/components/Header.svelte | 41 +++++++++++++++++ .../dashboard/DashboardHeaderActions.svelte | 3 -- apps/web/src/lib/utils/temas.ts | 46 +++++++++++++++++++ 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/apps/web/src/lib/components/Header.svelte b/apps/web/src/lib/components/Header.svelte index e5e7e3e..e9dece8 100644 --- a/apps/web/src/lib/components/Header.svelte +++ b/apps/web/src/lib/components/Header.svelte @@ -2,6 +2,8 @@ import { resolve } from '$app/paths'; import logo from '$lib/assets/logo_governo_PE.png'; import type { Snippet } from 'svelte'; + import { onMount } from 'svelte'; + import { aplicarTemaDaisyUI } from '$lib/utils/temas'; type HeaderProps = { left?: Snippet; @@ -9,6 +11,43 @@ }; const { left, right }: HeaderProps = $props(); + + let themeSelectEl: HTMLSelectElement | null = null; + + function safeGetThemeLS(): string | null { + try { + const t = localStorage.getItem('theme'); + return t && t.trim() ? t : null; + } catch { + return null; + } + } + + onMount(() => { + const persisted = safeGetThemeLS(); + if (persisted) { + // Sincroniza UI + HTML com o valor persistido (evita select ficar "aqua" indevido) + if (themeSelectEl && themeSelectEl.value !== persisted) { + themeSelectEl.value = persisted; + } + aplicarTemaDaisyUI(persisted); + } + }); + + function onThemeChange(e: Event) { + const nextValue = (e.currentTarget as HTMLSelectElement | null)?.value ?? null; + + // Se o theme-change não atualizar (caso comum após login/logout), + // garantimos aqui a persistência + aplicação imediata. + if (nextValue) { + try { + localStorage.setItem('theme', nextValue); + } catch { + // ignore + } + aplicarTemaDaisyUI(nextValue); + } + }