feat: Add 'atas' (minutes/records) management feature, and implement various improvements across UI, backend logic, and authentication.
This commit is contained in:
@@ -1,21 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import logo from '$lib/assets/logo_governo_PE.png';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { loginModalStore } from '$lib/stores/loginModal.svelte';
|
||||
import { useQuery, useConvexClient } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import NotificationBell from '$lib/components/chat/NotificationBell.svelte';
|
||||
import ChatWidget from '$lib/components/chat/ChatWidget.svelte';
|
||||
import PresenceManager from '$lib/components/chat/PresenceManager.svelte';
|
||||
|
||||
import { Menu, User, Home, UserPlus, XCircle, LogIn, Tag, Plus, Check } from 'lucide-svelte';
|
||||
import { authClient } from '$lib/auth';
|
||||
import { useConvexClient, useQuery } from 'convex-svelte';
|
||||
import { Check, Home, LogIn, Menu, Plus, Tag, User, UserPlus, XCircle } from 'lucide-svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { page } from '$app/state';
|
||||
import logo from '$lib/assets/logo_governo_PE.png';
|
||||
import { authClient } from '$lib/auth';
|
||||
import ChatWidget from '$lib/components/chat/ChatWidget.svelte';
|
||||
import NotificationBell from '$lib/components/chat/NotificationBell.svelte';
|
||||
import PresenceManager from '$lib/components/chat/PresenceManager.svelte';
|
||||
import { loginModalStore } from '$lib/stores/loginModal.svelte';
|
||||
import { obterIPPublico } from '$lib/utils/deviceInfo';
|
||||
|
||||
let { children }: { children: Snippet } = $props();
|
||||
const { children }: { children: Snippet } = $props();
|
||||
|
||||
const currentPath = $derived(page.url.pathname);
|
||||
|
||||
@@ -126,11 +125,11 @@
|
||||
|
||||
// Obter IP público e userAgent (rápido, não bloqueia)
|
||||
const userAgent = typeof navigator !== 'undefined' ? navigator.userAgent : undefined;
|
||||
|
||||
|
||||
// Obter IP público com timeout curto (não bloquear login)
|
||||
const ipPublicoPromise = obterIPPublico().catch(() => undefined);
|
||||
const ipPublicoTimeout = new Promise<undefined>((resolve) =>
|
||||
setTimeout(() => resolve(undefined), 2000) // Timeout de 2 segundos
|
||||
const ipPublicoTimeout = new Promise<undefined>(
|
||||
(resolve) => setTimeout(() => resolve(undefined), 2000) // Timeout de 2 segundos
|
||||
);
|
||||
const ipPublico = await Promise.race([ipPublicoPromise, ipPublicoTimeout]);
|
||||
|
||||
@@ -140,9 +139,7 @@
|
||||
const { obterLocalizacaoRapida } = await import('$lib/utils/deviceInfo');
|
||||
// Usar versão rápida com timeout curto (3 segundos máximo)
|
||||
const gpsPromise = obterLocalizacaoRapida();
|
||||
const gpsTimeout = new Promise<{}>((resolve) =>
|
||||
setTimeout(() => resolve({}), 3000)
|
||||
);
|
||||
const gpsTimeout = new Promise<{}>((resolve) => setTimeout(() => resolve({}), 3000));
|
||||
return await Promise.race([gpsPromise, gpsTimeout]);
|
||||
} catch (err) {
|
||||
console.warn('Erro ao obter GPS (não bloqueia login):', err);
|
||||
@@ -182,7 +179,7 @@
|
||||
enderecoGPS: localizacaoGPS.endereco,
|
||||
cidadeGPS: localizacaoGPS.cidade,
|
||||
estadoGPS: localizacaoGPS.estado,
|
||||
paisGPS: localizacaoGPS.pais,
|
||||
paisGPS: localizacaoGPS.pais
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Erro ao registrar tentativa de login falha:', err);
|
||||
@@ -199,7 +196,7 @@
|
||||
try {
|
||||
// Aguardar um pouco para o usuário ser sincronizado no Convex
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
|
||||
|
||||
// Tentar obter GPS se já estiver disponível (não esperar)
|
||||
let localizacaoGPS: any = {};
|
||||
try {
|
||||
@@ -210,10 +207,10 @@
|
||||
} catch {
|
||||
// Ignorar se GPS não estiver pronto
|
||||
}
|
||||
|
||||
|
||||
// Buscar o usuário no Convex usando getCurrentUser
|
||||
const usuario = await convexClient.query(api.auth.getCurrentUser, {});
|
||||
|
||||
|
||||
if (usuario && usuario._id) {
|
||||
await convexClient.mutation(api.logsLogin.registrarTentativaLogin, {
|
||||
usuarioId: usuario._id,
|
||||
@@ -227,7 +224,7 @@
|
||||
enderecoGPS: localizacaoGPS.endereco,
|
||||
cidadeGPS: localizacaoGPS.cidade,
|
||||
estadoGPS: localizacaoGPS.estado,
|
||||
paisGPS: localizacaoGPS.pais,
|
||||
paisGPS: localizacaoGPS.pais
|
||||
});
|
||||
} else {
|
||||
// Se não encontrou o usuário, registrar sem usuarioId (será atualizado depois)
|
||||
@@ -242,7 +239,7 @@
|
||||
enderecoGPS: localizacaoGPS.endereco,
|
||||
cidadeGPS: localizacaoGPS.cidade,
|
||||
estadoGPS: localizacaoGPS.estado,
|
||||
paisGPS: localizacaoGPS.pais,
|
||||
paisGPS: localizacaoGPS.pais
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -250,7 +247,7 @@
|
||||
// Não bloquear o login se houver erro ao registrar
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
closeLoginModal();
|
||||
goto(resolve('/'));
|
||||
} else {
|
||||
@@ -278,7 +275,7 @@
|
||||
<div class="flex-none lg:hidden">
|
||||
<label
|
||||
for="my-drawer-3"
|
||||
class="group relative flex h-14 w-14 cursor-pointer items-center justify-center overflow-hidden rounded-2xl bg-primary shadow-xl transition-all duration-300 hover:scale-105 hover:shadow-2xl"
|
||||
class="group bg-primary relative flex h-14 w-14 cursor-pointer items-center justify-center overflow-hidden rounded-2xl shadow-xl transition-all duration-300 hover:scale-105 hover:shadow-2xl"
|
||||
aria-label="Abrir menu"
|
||||
>
|
||||
<!-- Efeito de brilho no hover -->
|
||||
@@ -298,7 +295,7 @@
|
||||
<!-- Logo MODERNO do Governo -->
|
||||
<div class="avatar">
|
||||
<div
|
||||
class="group relative w-16 overflow-hidden rounded-2xl p-2 bg-base-100 border-2 border-primary/20 shadow-xl transition-all duration-300 hover:scale-105 lg:w-20"
|
||||
class="group bg-base-100 border-primary/20 relative w-16 overflow-hidden rounded-2xl border-2 p-2 shadow-xl transition-all duration-300 hover:scale-105 lg:w-20"
|
||||
>
|
||||
<!-- Efeito de brilho no hover -->
|
||||
<div
|
||||
@@ -341,13 +338,13 @@
|
||||
<button
|
||||
type="button"
|
||||
tabindex="0"
|
||||
class="group relative flex h-14 w-14 items-center justify-center overflow-hidden rounded-2xl bg-primary shadow-xl transition-all duration-300 hover:scale-105 hover:shadow-2xl"
|
||||
class="group bg-primary relative flex h-14 w-14 items-center justify-center overflow-hidden rounded-2xl shadow-xl transition-all duration-300 hover:scale-105 hover:shadow-2xl"
|
||||
aria-label="Menu do usuário"
|
||||
>
|
||||
<!-- Efeito de brilho no hover -->
|
||||
<div
|
||||
class="absolute inset-0 bg-linear-to-br from-white/0 to-white/20 opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
||||
> </div>
|
||||
></div>
|
||||
|
||||
<!-- Avatar/Foto do usuário ou ícone padrão -->
|
||||
{#if avatarUrlDoUsuario()}
|
||||
@@ -371,10 +368,10 @@
|
||||
></div>
|
||||
|
||||
<!-- Badge de status online -->
|
||||
<div
|
||||
class="bg-success absolute top-1 right-1 z-20 h-3 w-3 rounded-full border-2 border-white shadow-lg"
|
||||
style="animation: pulse-dot 2s ease-in-out infinite;"
|
||||
></div>
|
||||
<div
|
||||
class="bg-success absolute top-1 right-1 z-20 h-3 w-3 rounded-full border-2 border-white shadow-lg"
|
||||
style="animation: pulse-dot 2s ease-in-out infinite;"
|
||||
></div>
|
||||
</button>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
||||
<ul
|
||||
|
||||
Reference in New Issue
Block a user