Files
sgse-app/apps/web/src/lib/components/ActionGuard.svelte

72 lines
1.9 KiB
Svelte

<script lang="ts">
import { useQuery } from 'convex-svelte';
import { api } from '@sgse-app/backend/convex/_generated/api';
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
import { loginModalStore } from '$lib/stores/loginModal.svelte';
import { TriangleAlert } from 'lucide-svelte';
interface Props {
recurso: string;
acao: string;
children?: any;
}
let { recurso, acao, children }: Props = $props();
let verificando = $state(true);
let permitido = $state(false);
// Usuário atual
const currentUser = useQuery(api.auth.getCurrentUser, {});
let permissaoQuery = $derived(
currentUser?.data
? useQuery(api.permissoesAcoes.verificarAcao, {
usuarioId: currentUser.data._id as Id<'usuarios'>,
recurso,
acao
})
: null
);
$effect(() => {
if (!currentUser?.data) {
verificando = false;
permitido = false;
const currentPath = window.location.pathname;
loginModalStore.open(currentPath);
return;
}
if (permissaoQuery?.error) {
verificando = false;
permitido = false;
} else if (permissaoQuery && !permissaoQuery.isLoading) {
// Backend retorna null quando permitido
verificando = false;
permitido = true;
}
});
</script>
{#if verificando}
<div class="flex min-h-screen items-center justify-center">
<div class="text-center">
<span class="loading loading-spinner loading-lg text-primary"></span>
<p class="text-base-content/70 mt-4">Verificando permissões...</p>
</div>
</div>
{:else if permitido}
{@render children?.()}
{:else}
<div class="flex min-h-screen items-center justify-center">
<div class="text-center">
<div class="bg-error/10 mb-4 inline-block rounded-full p-4">
<TriangleAlert class="text-error h-16 w-16" strokeWidth={2} />
</div>
<h2 class="text-base-content mb-2 text-2xl font-bold">Acesso Negado</h2>
<p class="text-base-content/70">Você não tem permissão para acessar esta ação.</p>
</div>
</div>
{/if}