feat: Add 'atas' (minutes/records) management feature, and implement various improvements across UI, backend logic, and authentication.
This commit is contained in:
@@ -1,183 +1,177 @@
|
||||
import { browser } from "$app/environment";
|
||||
import { goto } from "$app/navigation";
|
||||
import type { Id } from "@sgse-app/backend/convex/betterAuth/_generated/dataModel";
|
||||
import type { Id } from '@sgse-app/backend/convex/betterAuth/_generated/dataModel';
|
||||
import { browser } from '$app/environment';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
interface Usuario {
|
||||
_id: string;
|
||||
matricula: string;
|
||||
nome: string;
|
||||
email: string;
|
||||
funcionarioId?: Id<"funcionarios">;
|
||||
role: {
|
||||
_id: string;
|
||||
nome: string;
|
||||
nivel: number;
|
||||
setor?: string;
|
||||
};
|
||||
primeiroAcesso: boolean;
|
||||
avatar?: string;
|
||||
fotoPerfil?: string;
|
||||
fotoPerfilUrl?: string | null;
|
||||
_id: string;
|
||||
matricula: string;
|
||||
nome: string;
|
||||
email: string;
|
||||
funcionarioId?: Id<'funcionarios'>;
|
||||
role: {
|
||||
_id: string;
|
||||
nome: string;
|
||||
nivel: number;
|
||||
setor?: string;
|
||||
};
|
||||
primeiroAcesso: boolean;
|
||||
avatar?: string;
|
||||
fotoPerfil?: string;
|
||||
fotoPerfilUrl?: string | null;
|
||||
}
|
||||
|
||||
interface AuthState {
|
||||
usuario: Usuario | null;
|
||||
token: string | null;
|
||||
carregando: boolean;
|
||||
usuario: Usuario | null;
|
||||
token: string | null;
|
||||
carregando: boolean;
|
||||
}
|
||||
|
||||
class AuthStore {
|
||||
private state = $state<AuthState>({
|
||||
usuario: null,
|
||||
token: null,
|
||||
carregando: true,
|
||||
});
|
||||
private state = $state<AuthState>({
|
||||
usuario: null,
|
||||
token: null,
|
||||
carregando: true
|
||||
});
|
||||
|
||||
constructor() {
|
||||
if (browser) {
|
||||
this.carregarDoLocalStorage();
|
||||
}
|
||||
}
|
||||
constructor() {
|
||||
if (browser) {
|
||||
this.carregarDoLocalStorage();
|
||||
}
|
||||
}
|
||||
|
||||
get usuario() {
|
||||
return this.state.usuario;
|
||||
}
|
||||
get usuario() {
|
||||
return this.state.usuario;
|
||||
}
|
||||
|
||||
get token() {
|
||||
return this.state.token;
|
||||
}
|
||||
get token() {
|
||||
return this.state.token;
|
||||
}
|
||||
|
||||
get carregando() {
|
||||
return this.state.carregando;
|
||||
}
|
||||
get carregando() {
|
||||
return this.state.carregando;
|
||||
}
|
||||
|
||||
get autenticado() {
|
||||
return !!this.state.usuario && !!this.state.token;
|
||||
}
|
||||
get autenticado() {
|
||||
return !!this.state.usuario && !!this.state.token;
|
||||
}
|
||||
|
||||
get isAdmin() {
|
||||
return this.state.usuario?.role.nivel === 0;
|
||||
}
|
||||
get isAdmin() {
|
||||
return this.state.usuario?.role.nivel === 0;
|
||||
}
|
||||
|
||||
get isTI() {
|
||||
return this.state.usuario?.role.nome === "ti" || this.isAdmin;
|
||||
}
|
||||
get isTI() {
|
||||
return this.state.usuario?.role.nome === 'ti' || this.isAdmin;
|
||||
}
|
||||
|
||||
get isRH() {
|
||||
return this.state.usuario?.role.nome === "rh" || this.isAdmin;
|
||||
}
|
||||
get isRH() {
|
||||
return this.state.usuario?.role.nome === 'rh' || this.isAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* FASE 2: Login dual - suporta tanto sistema customizado quanto Better Auth
|
||||
* Por enquanto, mantém sistema customizado. Better Auth será adicionado depois.
|
||||
*/
|
||||
login(usuario: Usuario, token: string) {
|
||||
this.state.usuario = usuario;
|
||||
this.state.token = token;
|
||||
this.state.carregando = false;
|
||||
/**
|
||||
* FASE 2: Login dual - suporta tanto sistema customizado quanto Better Auth
|
||||
* Por enquanto, mantém sistema customizado. Better Auth será adicionado depois.
|
||||
*/
|
||||
login(usuario: Usuario, token: string) {
|
||||
this.state.usuario = usuario;
|
||||
this.state.token = token;
|
||||
this.state.carregando = false;
|
||||
|
||||
if (browser) {
|
||||
localStorage.setItem("auth_token", token);
|
||||
localStorage.setItem("auth_usuario", JSON.stringify(usuario));
|
||||
|
||||
// FASE 2: Preparar para Better Auth (ainda não ativo)
|
||||
// Quando Better Auth estiver configurado, também salvaremos sessão do Better Auth aqui
|
||||
if (import.meta.env.DEV) {
|
||||
console.log("✅ [AuthStore] Login realizado:", {
|
||||
usuario: usuario.nome,
|
||||
email: usuario.email,
|
||||
sistema: "customizado" // Será "better-auth" quando migrado
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FASE 2: Login via Better Auth (preparado para futuro)
|
||||
* Por enquanto não implementado, será usado quando Better Auth estiver completo
|
||||
*/
|
||||
async loginWithBetterAuth(email: string, senha: string) {
|
||||
// TODO: Implementar quando Better Auth estiver pronto
|
||||
// const { authClient } = await import("$lib/auth");
|
||||
// const result = await authClient.signIn.email({ email, password: senha });
|
||||
// if (result.data) {
|
||||
// // Obter perfil do usuário do Convex
|
||||
// // this.login(usuario, result.data.session.token);
|
||||
// }
|
||||
throw new Error("Better Auth ainda não configurado. Use login customizado.");
|
||||
}
|
||||
if (browser) {
|
||||
localStorage.setItem('auth_token', token);
|
||||
localStorage.setItem('auth_usuario', JSON.stringify(usuario));
|
||||
|
||||
logout() {
|
||||
this.state.usuario = null;
|
||||
this.state.token = null;
|
||||
this.state.carregando = false;
|
||||
// FASE 2: Preparar para Better Auth (ainda não ativo)
|
||||
// Quando Better Auth estiver configurado, também salvaremos sessão do Better Auth aqui
|
||||
if (import.meta.env.DEV) {
|
||||
console.log('✅ [AuthStore] Login realizado:', {
|
||||
usuario: usuario.nome,
|
||||
email: usuario.email,
|
||||
sistema: 'customizado' // Será "better-auth" quando migrado
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
localStorage.removeItem("auth_token");
|
||||
localStorage.removeItem("auth_usuario");
|
||||
goto("/");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* FASE 2: Login via Better Auth (preparado para futuro)
|
||||
* Por enquanto não implementado, será usado quando Better Auth estiver completo
|
||||
*/
|
||||
async loginWithBetterAuth(email: string, senha: string) {
|
||||
// TODO: Implementar quando Better Auth estiver pronto
|
||||
// const { authClient } = await import("$lib/auth");
|
||||
// const result = await authClient.signIn.email({ email, password: senha });
|
||||
// if (result.data) {
|
||||
// // Obter perfil do usuário do Convex
|
||||
// // this.login(usuario, result.data.session.token);
|
||||
// }
|
||||
throw new Error('Better Auth ainda não configurado. Use login customizado.');
|
||||
}
|
||||
|
||||
setCarregando(carregando: boolean) {
|
||||
this.state.carregando = carregando;
|
||||
}
|
||||
logout() {
|
||||
this.state.usuario = null;
|
||||
this.state.token = null;
|
||||
this.state.carregando = false;
|
||||
|
||||
async refresh() {
|
||||
if (!browser || !this.state.token) return;
|
||||
if (browser) {
|
||||
localStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('auth_usuario');
|
||||
goto('/');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Importação dinâmica do convex para evitar problemas de SSR
|
||||
const { ConvexHttpClient } = await import("convex/browser");
|
||||
const { api } = await import("@sgse-app/backend/convex/_generated/api");
|
||||
setCarregando(carregando: boolean) {
|
||||
this.state.carregando = carregando;
|
||||
}
|
||||
|
||||
const client = new ConvexHttpClient(import.meta.env.VITE_CONVEX_URL);
|
||||
client.setAuth(this.state.token);
|
||||
async refresh() {
|
||||
if (!browser || !this.state.token) return;
|
||||
|
||||
const usuarioAtualizado = await client.query(
|
||||
api.usuarios.obterPerfil,
|
||||
{}
|
||||
);
|
||||
try {
|
||||
// Importação dinâmica do convex para evitar problemas de SSR
|
||||
const { ConvexHttpClient } = await import('convex/browser');
|
||||
const { api } = await import('@sgse-app/backend/convex/_generated/api');
|
||||
|
||||
if (usuarioAtualizado) {
|
||||
// Preservar role e primeiroAcesso do estado atual
|
||||
this.state.usuario = {
|
||||
...usuarioAtualizado,
|
||||
role: this.state.usuario?.role || {
|
||||
_id: "",
|
||||
nome: "Usuário",
|
||||
nivel: 999,
|
||||
},
|
||||
primeiroAcesso: this.state.usuario?.primeiroAcesso ?? false,
|
||||
};
|
||||
const client = new ConvexHttpClient(import.meta.env.VITE_CONVEX_URL);
|
||||
client.setAuth(this.state.token);
|
||||
|
||||
localStorage.setItem(
|
||||
"auth_usuario",
|
||||
JSON.stringify(this.state.usuario)
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Erro ao atualizar perfil:", error);
|
||||
}
|
||||
}
|
||||
const usuarioAtualizado = await client.query(api.usuarios.obterPerfil, {});
|
||||
|
||||
private carregarDoLocalStorage() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const usuarioStr = localStorage.getItem("auth_usuario");
|
||||
if (usuarioAtualizado) {
|
||||
// Preservar role e primeiroAcesso do estado atual
|
||||
this.state.usuario = {
|
||||
...usuarioAtualizado,
|
||||
role: this.state.usuario?.role || {
|
||||
_id: '',
|
||||
nome: 'Usuário',
|
||||
nivel: 999
|
||||
},
|
||||
primeiroAcesso: this.state.usuario?.primeiroAcesso ?? false
|
||||
};
|
||||
|
||||
if (token && usuarioStr) {
|
||||
try {
|
||||
const usuario = JSON.parse(usuarioStr);
|
||||
this.state.usuario = usuario;
|
||||
this.state.token = token;
|
||||
} catch (error) {
|
||||
console.error("Erro ao carregar usuário do localStorage:", error);
|
||||
this.logout();
|
||||
}
|
||||
}
|
||||
localStorage.setItem('auth_usuario', JSON.stringify(this.state.usuario));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erro ao atualizar perfil:', error);
|
||||
}
|
||||
}
|
||||
|
||||
this.state.carregando = false;
|
||||
}
|
||||
private carregarDoLocalStorage() {
|
||||
const token = localStorage.getItem('auth_token');
|
||||
const usuarioStr = localStorage.getItem('auth_usuario');
|
||||
|
||||
if (token && usuarioStr) {
|
||||
try {
|
||||
const usuario = JSON.parse(usuarioStr);
|
||||
this.state.usuario = usuario;
|
||||
this.state.token = token;
|
||||
} catch (error) {
|
||||
console.error('Erro ao carregar usuário do localStorage:', error);
|
||||
this.logout();
|
||||
}
|
||||
}
|
||||
|
||||
this.state.carregando = false;
|
||||
}
|
||||
}
|
||||
|
||||
export const authStore = new AuthStore();
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* Store para gerenciar estado das chamadas de áudio/vídeo
|
||||
*/
|
||||
|
||||
import { writable, derived, get } from 'svelte/store';
|
||||
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import { derived, get, writable } from 'svelte/store';
|
||||
import type { JitsiApi } from '$lib/types/jitsi';
|
||||
|
||||
export interface ParticipanteChamada {
|
||||
@@ -62,22 +62,13 @@ const estadoInicial: EstadoChamada = {
|
||||
export const callState = writable<EstadoChamada>(estadoInicial);
|
||||
|
||||
// Store para indicar se há chamada ativa
|
||||
export const chamadaAtiva = derived(
|
||||
callState,
|
||||
($state) => $state.chamadaId !== null
|
||||
);
|
||||
export const chamadaAtiva = derived(callState, ($state) => $state.chamadaId !== null);
|
||||
|
||||
// Store para indicar se está conectado
|
||||
export const estaConectado = derived(
|
||||
callState,
|
||||
($state) => $state.estaConectado
|
||||
);
|
||||
export const estaConectado = derived(callState, ($state) => $state.estaConectado);
|
||||
|
||||
// Store para indicar se está gravando
|
||||
export const gravando = derived(
|
||||
callState,
|
||||
($state) => $state.gravando
|
||||
);
|
||||
export const gravando = derived(callState, ($state) => $state.gravando);
|
||||
|
||||
// Funções para atualizar o estado
|
||||
|
||||
@@ -109,12 +100,12 @@ export function inicializarChamada(
|
||||
*/
|
||||
export function finalizarChamada(): void {
|
||||
const estadoAtual = get(callState);
|
||||
|
||||
|
||||
// Liberar recursos
|
||||
if (estadoAtual.streamLocal) {
|
||||
estadoAtual.streamLocal.getTracks().forEach((track) => track.stop());
|
||||
}
|
||||
|
||||
|
||||
callState.set(estadoInicial);
|
||||
}
|
||||
|
||||
@@ -184,14 +175,12 @@ export function atualizarParticipantes(participantes: ParticipanteChamada[]): vo
|
||||
export function adicionarParticipante(participante: ParticipanteChamada): void {
|
||||
callState.update((state) => {
|
||||
// Verificar se já existe
|
||||
const existe = state.participantes.some(
|
||||
(p) => p.usuarioId === participante.usuarioId
|
||||
);
|
||||
|
||||
const existe = state.participantes.some((p) => p.usuarioId === participante.usuarioId);
|
||||
|
||||
if (existe) {
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
...state,
|
||||
participantes: [...state.participantes, participante]
|
||||
@@ -205,9 +194,7 @@ export function adicionarParticipante(participante: ParticipanteChamada): void {
|
||||
export function removerParticipante(usuarioId: Id<'usuarios'>): void {
|
||||
callState.update((state) => ({
|
||||
...state,
|
||||
participantes: state.participantes.filter(
|
||||
(p) => p.usuarioId !== usuarioId
|
||||
)
|
||||
participantes: state.participantes.filter((p) => p.usuarioId !== usuarioId)
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -299,7 +286,7 @@ export function setStreamLocal(stream: MediaStream | null): void {
|
||||
if (state.streamLocal) {
|
||||
state.streamLocal.getTracks().forEach((track) => track.stop());
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
...state,
|
||||
streamLocal: stream
|
||||
@@ -320,4 +307,3 @@ export function obterEstadoAtual(): EstadoChamada {
|
||||
export function resetarEstado(): void {
|
||||
finalizarChamada();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +1,52 @@
|
||||
import { writable } from "svelte/store";
|
||||
import type { Doc, Id } from "@sgse-app/backend/convex/_generated/dataModel";
|
||||
import type { Doc, Id } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export type TicketDetalhe = {
|
||||
ticket: Doc<"tickets">;
|
||||
interactions: Doc<"ticketInteractions">[];
|
||||
ticket: Doc<'tickets'>;
|
||||
interactions: Doc<'ticketInteractions'>[];
|
||||
};
|
||||
|
||||
function createChamadosStore() {
|
||||
const tickets = writable<Array<Doc<"tickets">>>([]);
|
||||
const detalhes = writable<Record<string, TicketDetalhe>>({});
|
||||
const carregando = writable(false);
|
||||
const tickets = writable<Array<Doc<'tickets'>>>([]);
|
||||
const detalhes = writable<Record<string, TicketDetalhe>>({});
|
||||
const carregando = writable(false);
|
||||
|
||||
function setTickets(lista: Array<Doc<"tickets">>) {
|
||||
tickets.set(lista);
|
||||
}
|
||||
function setTickets(lista: Array<Doc<'tickets'>>) {
|
||||
tickets.set(lista);
|
||||
}
|
||||
|
||||
function upsertTicket(ticket: Doc<"tickets">) {
|
||||
tickets.update((current) => {
|
||||
const existente = current.findIndex((t) => t._id === ticket._id);
|
||||
if (existente >= 0) {
|
||||
const copia = [...current];
|
||||
copia[existente] = ticket;
|
||||
return copia;
|
||||
}
|
||||
return [ticket, ...current];
|
||||
});
|
||||
}
|
||||
function upsertTicket(ticket: Doc<'tickets'>) {
|
||||
tickets.update((current) => {
|
||||
const existente = current.findIndex((t) => t._id === ticket._id);
|
||||
if (existente >= 0) {
|
||||
const copia = [...current];
|
||||
copia[existente] = ticket;
|
||||
return copia;
|
||||
}
|
||||
return [ticket, ...current];
|
||||
});
|
||||
}
|
||||
|
||||
function setDetalhe(ticketId: Id<"tickets">, detalhe: TicketDetalhe) {
|
||||
detalhes.update((mapa) => ({
|
||||
...mapa,
|
||||
[ticketId]: detalhe,
|
||||
}));
|
||||
}
|
||||
function setDetalhe(ticketId: Id<'tickets'>, detalhe: TicketDetalhe) {
|
||||
detalhes.update((mapa) => ({
|
||||
...mapa,
|
||||
[ticketId]: detalhe
|
||||
}));
|
||||
}
|
||||
|
||||
function setCarregando(flag: boolean) {
|
||||
carregando.set(flag);
|
||||
}
|
||||
function setCarregando(flag: boolean) {
|
||||
carregando.set(flag);
|
||||
}
|
||||
|
||||
return {
|
||||
tickets,
|
||||
detalhes,
|
||||
carregando,
|
||||
setTickets,
|
||||
upsertTicket,
|
||||
setDetalhe,
|
||||
setCarregando,
|
||||
};
|
||||
return {
|
||||
tickets,
|
||||
detalhes,
|
||||
carregando,
|
||||
setTickets,
|
||||
upsertTicket,
|
||||
setDetalhe,
|
||||
setCarregando
|
||||
};
|
||||
}
|
||||
|
||||
export const chamadosStore = createChamadosStore();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
|
||||
// Store para a conversa ativa
|
||||
export const conversaAtiva = writable<Id<"conversas"> | null>(null);
|
||||
export const conversaAtiva = writable<Id<'conversas'> | null>(null);
|
||||
|
||||
// Store para o estado do chat (aberto/minimizado/fechado)
|
||||
export const chatAberto = writable<boolean>(false);
|
||||
@@ -13,30 +13,29 @@ export const notificacoesCount = writable<number>(0);
|
||||
|
||||
// Funções auxiliares
|
||||
export function abrirChat() {
|
||||
chatAberto.set(true);
|
||||
chatMinimizado.set(false);
|
||||
chatAberto.set(true);
|
||||
chatMinimizado.set(false);
|
||||
}
|
||||
|
||||
export function fecharChat() {
|
||||
chatAberto.set(false);
|
||||
chatMinimizado.set(false);
|
||||
conversaAtiva.set(null);
|
||||
chatAberto.set(false);
|
||||
chatMinimizado.set(false);
|
||||
conversaAtiva.set(null);
|
||||
}
|
||||
|
||||
export function minimizarChat() {
|
||||
chatMinimizado.set(true);
|
||||
chatMinimizado.set(true);
|
||||
}
|
||||
|
||||
export function maximizarChat() {
|
||||
chatMinimizado.set(false);
|
||||
chatMinimizado.set(false);
|
||||
}
|
||||
|
||||
export function abrirConversa(conversaId: Id<"conversas">) {
|
||||
conversaAtiva.set(conversaId);
|
||||
abrirChat();
|
||||
export function abrirConversa(conversaId: Id<'conversas'>) {
|
||||
conversaAtiva.set(conversaId);
|
||||
abrirChat();
|
||||
}
|
||||
|
||||
export function voltarParaLista() {
|
||||
conversaAtiva.set(null);
|
||||
conversaAtiva.set(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,64 +1,63 @@
|
||||
/**
|
||||
* Helper para garantir que o token seja passado para todas requisições Convex
|
||||
*
|
||||
*
|
||||
* Este store reativa garante que quando o token mudar no authStore,
|
||||
* todos os clientes Convex sejam atualizados automaticamente.
|
||||
*/
|
||||
|
||||
import { authStore } from "./auth.svelte";
|
||||
import { browser } from "$app/environment";
|
||||
import { PUBLIC_CONVEX_URL } from "$env/static/public";
|
||||
import { browser } from '$app/environment';
|
||||
import { PUBLIC_CONVEX_URL } from '$env/static/public';
|
||||
import { authStore } from './auth.svelte';
|
||||
|
||||
let convexClients = new Set<any>();
|
||||
const convexClients = new Set<any>();
|
||||
|
||||
/**
|
||||
* Registrar um cliente Convex para receber atualizações de token
|
||||
*/
|
||||
export function registerConvexClient(client: any) {
|
||||
if (!browser) return;
|
||||
|
||||
convexClients.add(client);
|
||||
|
||||
// Configurar token inicial
|
||||
if (authStore.token && client.setAuth) {
|
||||
client.setAuth(authStore.token);
|
||||
}
|
||||
|
||||
// Retornar função de limpeza
|
||||
return () => {
|
||||
convexClients.delete(client);
|
||||
};
|
||||
if (!browser) return;
|
||||
|
||||
convexClients.add(client);
|
||||
|
||||
// Configurar token inicial
|
||||
if (authStore.token && client.setAuth) {
|
||||
client.setAuth(authStore.token);
|
||||
}
|
||||
|
||||
// Retornar função de limpeza
|
||||
return () => {
|
||||
convexClients.delete(client);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Atualizar token em todos clientes registrados
|
||||
*/
|
||||
function updateAllClients() {
|
||||
if (!browser) return;
|
||||
|
||||
const token = authStore.token;
|
||||
convexClients.forEach((client) => {
|
||||
if (client && typeof client.setAuth === "function") {
|
||||
if (token) {
|
||||
client.setAuth(token);
|
||||
} else {
|
||||
client.clearAuth?.();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!browser) return;
|
||||
|
||||
const token = authStore.token;
|
||||
convexClients.forEach((client) => {
|
||||
if (client && typeof client.setAuth === 'function') {
|
||||
if (token) {
|
||||
client.setAuth(token);
|
||||
} else {
|
||||
client.clearAuth?.();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Observar mudanças no token e atualizar clientes
|
||||
if (browser) {
|
||||
// Usar uma abordagem reativa simples
|
||||
let lastToken: string | null = null;
|
||||
|
||||
setInterval(() => {
|
||||
const currentToken = authStore.token;
|
||||
if (currentToken !== lastToken) {
|
||||
lastToken = currentToken;
|
||||
updateAllClients();
|
||||
}
|
||||
}, 500); // Verificar a cada 500ms
|
||||
}
|
||||
// Usar uma abordagem reativa simples
|
||||
let lastToken: string | null = null;
|
||||
|
||||
setInterval(() => {
|
||||
const currentToken = authStore.token;
|
||||
if (currentToken !== lastToken) {
|
||||
lastToken = currentToken;
|
||||
updateAllClients();
|
||||
}
|
||||
}, 500); // Verificar a cada 500ms
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import { browser } from "$app/environment";
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
/**
|
||||
* Store global para controlar o modal de login
|
||||
*/
|
||||
class LoginModalStore {
|
||||
showModal = $state(false);
|
||||
redirectAfterLogin = $state<string | null>(null);
|
||||
showModal = $state(false);
|
||||
redirectAfterLogin = $state<string | null>(null);
|
||||
|
||||
open(redirectTo?: string) {
|
||||
this.showModal = true;
|
||||
this.redirectAfterLogin = redirectTo || null;
|
||||
}
|
||||
open(redirectTo?: string) {
|
||||
this.showModal = true;
|
||||
this.redirectAfterLogin = redirectTo || null;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.showModal = false;
|
||||
this.redirectAfterLogin = null;
|
||||
}
|
||||
close() {
|
||||
this.showModal = false;
|
||||
this.redirectAfterLogin = null;
|
||||
}
|
||||
}
|
||||
|
||||
export const loginModalStore = new LoginModalStore();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user