Emp perfis #25
@@ -1,80 +1,77 @@
|
||||
<script lang="ts">
|
||||
import { useQuery } from "convex-svelte";
|
||||
import { api } from "@sgse-app/backend/convex/_generated/api";
|
||||
import { onMount } from "svelte";
|
||||
import { page } from "$app/stores";
|
||||
import type { Snippet } from "svelte";
|
||||
import { useQuery } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { onMount } from 'svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
let {
|
||||
children,
|
||||
requireAuth = true,
|
||||
allowedRoles = [],
|
||||
maxLevel = 3,
|
||||
redirectTo = "/",
|
||||
}: {
|
||||
children: Snippet;
|
||||
requireAuth?: boolean;
|
||||
allowedRoles?: string[];
|
||||
maxLevel?: number;
|
||||
redirectTo?: string;
|
||||
} = $props();
|
||||
let {
|
||||
children,
|
||||
requireAuth = true,
|
||||
allowedRoles = [],
|
||||
maxLevel = 3,
|
||||
redirectTo = '/'
|
||||
}: {
|
||||
children: Snippet;
|
||||
requireAuth?: boolean;
|
||||
allowedRoles?: string[];
|
||||
maxLevel?: number;
|
||||
redirectTo?: string;
|
||||
} = $props();
|
||||
|
||||
let isChecking = $state(true);
|
||||
let hasAccess = $state(false);
|
||||
const currentUser = useQuery(api.auth.getCurrentUser, {});
|
||||
let isChecking = $state(true);
|
||||
let hasAccess = $state(false);
|
||||
const currentUser = useQuery(api.auth.getCurrentUser, {});
|
||||
|
||||
onMount(() => {
|
||||
checkAccess();
|
||||
});
|
||||
onMount(() => {
|
||||
checkAccess();
|
||||
});
|
||||
|
||||
function checkAccess() {
|
||||
isChecking = true;
|
||||
function checkAccess() {
|
||||
isChecking = true;
|
||||
|
||||
// Aguardar um pouco para o authStore carregar do localStorage
|
||||
setTimeout(() => {
|
||||
// Verificar autenticação
|
||||
if (requireAuth && !currentUser?.data) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `${redirectTo}?error=auth_required&redirect=${encodeURIComponent(currentPath)}`;
|
||||
return;
|
||||
}
|
||||
// Aguardar um pouco para o authStore carregar do localStorage
|
||||
setTimeout(() => {
|
||||
// Verificar autenticação
|
||||
if (requireAuth && !currentUser?.data) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `${redirectTo}?error=auth_required&redirect=${encodeURIComponent(currentPath)}`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Verificar roles
|
||||
if (allowedRoles.length > 0 && currentUser?.data) {
|
||||
const hasRole = allowedRoles.includes(
|
||||
currentUser.data.role?.nome ?? "",
|
||||
);
|
||||
if (!hasRole) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `${redirectTo}?error=access_denied&route=${encodeURIComponent(currentPath)}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Verificar roles
|
||||
if (allowedRoles.length > 0 && currentUser?.data) {
|
||||
const hasRole = allowedRoles.includes(currentUser.data.role?.nome ?? '');
|
||||
if (!hasRole) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `${redirectTo}?error=access_denied&route=${encodeURIComponent(currentPath)}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Verificar nível
|
||||
if (
|
||||
currentUser?.data &&
|
||||
currentUser.data.role?.nivel &&
|
||||
currentUser.data.role.nivel > maxLevel
|
||||
) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `${redirectTo}?error=access_denied&route=${encodeURIComponent(currentPath)}`;
|
||||
return;
|
||||
}
|
||||
// Verificar nível
|
||||
if (
|
||||
currentUser?.data &&
|
||||
currentUser.data.role?.nivel &&
|
||||
currentUser.data.role.nivel > maxLevel
|
||||
) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `${redirectTo}?error=access_denied&route=${encodeURIComponent(currentPath)}`;
|
||||
return;
|
||||
}
|
||||
|
||||
hasAccess = true;
|
||||
isChecking = false;
|
||||
}, 100);
|
||||
}
|
||||
hasAccess = true;
|
||||
isChecking = false;
|
||||
}, 100);
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if isChecking}
|
||||
<div class="flex justify-center items-center min-h-screen">
|
||||
<div class="text-center">
|
||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||
<p class="mt-4 text-base-content/70">Verificando permissões...</p>
|
||||
</div>
|
||||
</div>
|
||||
<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 hasAccess}
|
||||
{@render children()}
|
||||
{@render children()}
|
||||
{/if}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import { resolve } from "$app/paths";
|
||||
import { UserPlus, Mail } from "lucide-svelte";
|
||||
import { useAuth } from "@mmailaender/convex-better-auth-svelte/svelte";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
@@ -128,6 +129,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<!-- Alerta de Acesso Negado / Autenticação -->
|
||||
{#if showAlert}
|
||||
@@ -823,6 +825,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
<style>
|
||||
@keyframes fadeIn {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { ShoppingCart, ShoppingBag, Plus } from "lucide-svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
<ul>
|
||||
@@ -41,4 +43,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Megaphone, Edit, Plus } from "lucide-svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
<ul>
|
||||
@@ -41,4 +43,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { BarChart3, ClipboardCheck, Plus, CheckCircle2, Clock, TrendingUp } from "lucide-svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<!-- Breadcrumb -->
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
@@ -86,4 +88,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { DollarSign, Building2, Plus, Calculator, TrendingUp, FileText } from "lucide-svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<!-- Breadcrumb -->
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
@@ -86,4 +88,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Scale, BookOpen, Plus } from "lucide-svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
<ul>
|
||||
@@ -41,4 +43,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { FileText, ClipboardCopy, Plus, Users, FileDoc } from "lucide-svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<!-- Breadcrumb -->
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
@@ -86,4 +88,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import AprovarAusencias from '$lib/components/AprovarAusencias.svelte';
|
||||
import CalendarioAusencias from '$lib/components/ausencias/CalendarioAusencias.svelte';
|
||||
import { generateAvatarGallery } from '$lib/utils/avatars';
|
||||
import ProtectedRoute from '$lib/components/ProtectedRoute.svelte';
|
||||
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import { X, Calendar } from 'lucide-svelte';
|
||||
import type { FunctionReturnType } from 'convex/server';
|
||||
@@ -365,6 +366,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="min-h-screen pb-12">
|
||||
<!-- BANNER HERO PREMIUM -->
|
||||
<div class="relative mb-8 overflow-hidden">
|
||||
@@ -2264,6 +2266,7 @@
|
||||
</dialog>
|
||||
{/if}
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
<!-- Modal Wizard Solicitação de Férias -->
|
||||
{#if mostrarWizard && funcionarioIdDisponivel}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Trophy, Award, Plus } from "lucide-svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
import ProtectedRoute from "$lib/components/ProtectedRoute.svelte";
|
||||
</script>
|
||||
|
||||
<ProtectedRoute>
|
||||
<main class="container mx-auto px-4 py-4">
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
<ul>
|
||||
@@ -41,4 +43,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</ProtectedRoute>
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
);
|
||||
</script>
|
||||
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={3}>
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={1}>
|
||||
<div class="container mx-auto max-w-7xl px-4 py-6">
|
||||
<!-- Header -->
|
||||
<div class="mb-8 flex items-center justify-between">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { resolve } from '$app/paths';
|
||||
</script>
|
||||
|
||||
<ProtectedRoute allowedRoles={['admin', 'ti']} maxLevel={1}>
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin']} maxLevel={1}>
|
||||
<!-- Breadcrumb -->
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={3}>
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={1}>
|
||||
<div class="container mx-auto max-w-7xl px-4 py-6">
|
||||
<!-- Mensagem de Feedback -->
|
||||
{#if mensagem}
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={2}>
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={1}>
|
||||
<main class="container mx-auto max-w-7xl px-4 py-6">
|
||||
<!-- Breadcrumb -->
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
|
||||
@@ -535,7 +535,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={3}>
|
||||
<ProtectedRoute allowedRoles={['ti_master', 'admin', 'ti_usuario']} maxLevel={1}>
|
||||
<div class="container mx-auto max-w-7xl px-4 py-6">
|
||||
<!-- Header -->
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
|
||||
Reference in New Issue
Block a user