diff --git a/apps/web/package.json b/apps/web/package.json index f65d3bf..49a9403 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -40,7 +40,7 @@ "@sgse-app/backend": "*", "@tanstack/svelte-form": "^1.19.2", "@types/papaparse": "^5.3.14", - "better-auth": "^1.3.34", + "better-auth": "catalog:", "convex": "catalog:", "convex-svelte": "^0.0.11", "date-fns": "^4.1.0", diff --git a/apps/web/src/app.d.ts b/apps/web/src/app.d.ts index 24b0b67..6633a80 100644 --- a/apps/web/src/app.d.ts +++ b/apps/web/src/app.d.ts @@ -5,3 +5,5 @@ declare global { } } } + +export {}; diff --git a/apps/web/src/hooks.server.ts b/apps/web/src/hooks.server.ts index bb90b27..08c379c 100644 --- a/apps/web/src/hooks.server.ts +++ b/apps/web/src/hooks.server.ts @@ -1,6 +1,6 @@ import type { Handle } from "@sveltejs/kit"; -import { getToken } from "@mmailaender/convex-better-auth-svelte/sveltekit"; import { createAuth } from "@sgse-app/backend/convex/auth"; +import { getToken } from "@mmailaender/convex-better-auth-svelte/sveltekit"; export const handle: Handle = async ({ event, resolve }) => { event.locals.token = await getToken(createAuth, event.cookies); diff --git a/apps/web/src/routes/(dashboard)/+layout.server.ts b/apps/web/src/routes/(dashboard)/+layout.server.ts new file mode 100644 index 0000000..12b79a6 --- /dev/null +++ b/apps/web/src/routes/(dashboard)/+layout.server.ts @@ -0,0 +1,9 @@ +import { api } from "@sgse-app/backend/convex/_generated/api"; +import { createConvexHttpClient } from "@mmailaender/convex-better-auth-svelte/sveltekit"; + +export const load = async ({ locals }) => { + const client = createConvexHttpClient({ token: locals.token }); + + const currentUser = await client.query(api.auth.getCurrentUser, {}); + return { currentUser }; +}; diff --git a/apps/web/src/routes/(dashboard)/+page.svelte b/apps/web/src/routes/(dashboard)/+page.svelte index c3eb11c..5819f43 100644 --- a/apps/web/src/routes/(dashboard)/+page.svelte +++ b/apps/web/src/routes/(dashboard)/+page.svelte @@ -5,55 +5,72 @@ import { page } from "$app/stores"; import { goto } from "$app/navigation"; import { UserPlus, Mail } from "lucide-svelte"; + import { useAuth } from "@mmailaender/convex-better-auth-svelte/svelte"; + + let { data } = $props(); + + const auth = useAuth(); + const isLoading = $derived(auth.isLoading && !data.currentUser); + const isAuthenticated = $derived(auth.isAuthenticated || !!data.currentUser); + + $inspect({ isLoading, isAuthenticated }); // Queries para dados do dashboard const statsQuery = useQuery(api.dashboard.getStats, {}); const activityQuery = useQuery(api.dashboard.getRecentActivity, {}); - + // Queries para monitoramento em tempo real const statusSistemaQuery = useQuery(api.monitoramento.getStatusSistema, {}); - const atividadeBDQuery = useQuery(api.monitoramento.getAtividadeBancoDados, {}); - const distribuicaoQuery = useQuery(api.monitoramento.getDistribuicaoRequisicoes, {}); + const atividadeBDQuery = useQuery( + api.monitoramento.getAtividadeBancoDados, + {}, + ); + const distribuicaoQuery = useQuery( + api.monitoramento.getDistribuicaoRequisicoes, + {}, + ); // Estado para animações let mounted = $state(false); let currentTime = $state(new Date()); let showAlert = $state(false); - let alertType = $state<"auth_required" | "access_denied" | "invalid_token" | null>(null); + let alertType = $state< + "auth_required" | "access_denied" | "invalid_token" | null + >(null); let redirectRoute = $state(""); // Forçar atualização das queries de monitoramento a cada 1 segundo let refreshKey = $state(0); - + onMount(() => { mounted = true; - + // Verificar se há mensagem de erro na URL const urlParams = new URLSearchParams(window.location.search); const error = urlParams.get("error"); const route = urlParams.get("route") || urlParams.get("redirect") || ""; - + if (error) { alertType = error as any; redirectRoute = route; showAlert = true; - + // Limpar URL const newUrl = window.location.pathname; window.history.replaceState({}, "", newUrl); - + // Auto-fechar após 10 segundos setTimeout(() => { showAlert = false; }, 10000); } - + // Atualizar relógio e forçar refresh das queries a cada segundo const interval = setInterval(() => { currentTime = new Date(); refreshKey = (refreshKey + 1) % 1000; // Incrementar para forçar re-render }, 1000); - + return () => clearInterval(interval); }); @@ -67,25 +84,25 @@ return { title: "Autenticação Necessária", message: `Para acessar "${redirectRoute}", você precisa fazer login no sistema.`, - icon: "🔐" + icon: "🔐", }; case "access_denied": return { title: "Acesso Negado", message: `Você não tem permissão para acessar "${redirectRoute}". Entre em contato com a equipe de TI para solicitar acesso.`, - icon: "⛔" + icon: "⛔", }; case "invalid_token": return { title: "Sessão Expirada", message: "Sua sessão expirou. Por favor, faça login novamente.", - icon: "⏰" + icon: "⏰", }; default: return { title: "Aviso", message: "Ocorreu um erro. Tente novamente.", - icon: "⚠️" + icon: "⚠️", }; } } @@ -114,7 +131,13 @@ {#if showAlert} {@const alertData = getAlertMessage()} -
Total de Funcionários
++ Total de Funcionários +
Solicitações Pendentes
++ Solicitações Pendentes +
Símbolos Cadastrados
++ Símbolos Cadastrados +
- {statsQuery.data.cargoComissionado} CC / {statsQuery.data.funcaoGratificada} FG + {statsQuery.data.cargoComissionado} CC / {statsQuery.data + .funcaoGratificada} FG
Atividade (24h)
++ Atividade (24h) +
{activityQuery.data.funcionariosCadastrados24h} cadastros
- Atualizado a cada segundo • {new Date(status.ultimaAtualizacao).toLocaleTimeString('pt-BR')} + Atualizado a cada segundo • {new Date( + status.ultimaAtualizacao, + ).toLocaleTimeString("pt-BR")}
Usuários Online
-sessões ativas
++ Usuários Online +
++ sessões ativas +
Total Registros
-no banco de dados
++ Total Registros +
++ no banco de dados +
Tempo Resposta
-+ Tempo Resposta +
+média atual
Uso do Sistema
++ Uso do Sistema +
Entradas e saídas em tempo real (último minuto)
++ Entradas e saídas em tempo real (último minuto) +
- Última Atualização: {new Date().toLocaleDateString("pt-BR")} + Última Atualização: + {new Date().toLocaleDateString("pt-BR")}
Suporte: TI SGSE diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte index 9a5c7ba..86935d1 100644 --- a/apps/web/src/routes/+layout.svelte +++ b/apps/web/src/routes/+layout.svelte @@ -1,118 +1,12 @@