Emp perfis #25

Merged
killer-cf merged 4 commits from emp-perfis into master 2025-11-15 00:58:00 +00:00
24 changed files with 1356 additions and 1399 deletions
Showing only changes of commit b503045b41 - Show all commits

View File

@@ -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}

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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}

View File

@@ -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>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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}

View File

@@ -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">

View File

@@ -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">