From 349a7bb1e497599c870a8e5f4ed6faae53bb459f Mon Sep 17 00:00:00 2001 From: killer-cf Date: Wed, 12 Nov 2025 09:06:43 -0300 Subject: [PATCH 1/5] add project mcps --- .cursor/mcp.json | 19 ++++++++++ bun.lock | 1 + package.json | 92 ++++++++++++++++++++++++------------------------ 3 files changed, 66 insertions(+), 46 deletions(-) create mode 100644 .cursor/mcp.json diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 0000000..58841f4 --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,19 @@ +{ + "mcpServers": { + "svelte": { + "url": "https://mcp.svelte.dev/mcp" + }, + "context7": { + "url": "https://mcp.context7.com/mcp" + }, + "convex": { + "command": "npx", + "args": [ + "-y", + "convex@latest", + "mcp", + "start" + ] + } + } +} \ No newline at end of file diff --git a/bun.lock b/bun.lock index 0b14041..b026cf6 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "sgse-app", diff --git a/package.json b/package.json index 0146ab7..c2c84bd 100644 --- a/package.json +++ b/package.json @@ -1,47 +1,47 @@ { - "name": "sgse-app", - "private": true, - "type": "module", - "workspaces": { - "packages": [ - "apps/*", - "packages/*" - ], - "catalog": { - "convex": "^1.28.0", - "typescript": "^5.9.2", - "better-auth": "1.3.27", - "eslint": "^9.39.1", - "@eslint/js": "^9.39.1" - } - }, - "scripts": { - "check": "biome check --write .", - "dev": "turbo dev", - "build": "turbo build", - "check-types": "turbo check-types", - "dev:native": "turbo -F native dev", - "dev:web": "turbo -F web dev", - "dev:server": "turbo -F @sgse-app/backend dev", - "dev:setup": "turbo -F @sgse-app/backend dev:setup" - }, - "devDependencies": { - "eslint": "^9.39.1", - "globals": "^16.5.0", - "jiti": "^2.6.1", - "turbo": "^2.5.8", - "typescript-eslint": "^8.46.3", - "prettier": "^3.6.2", - "eslint-plugin-svelte": "^3.13.0", - "prettier-plugin-tailwindcss": "^0.7.1" - }, - "dependencies": { - "@tanstack/svelte-form": "^1.23.8", - "chart.js": "^4.5.1", - "lucide-svelte": "^0.552.0", - "prettier-plugin-svelte": "^3.4.0", - "svelte-chartjs": "^3.1.5", - "svelte-sonner": "^1.0.5" - }, - "packageManager": "bun@1.3.0" -} \ No newline at end of file + "name": "sgse-app", + "private": true, + "type": "module", + "workspaces": { + "packages": [ + "apps/*", + "packages/*" + ], + "catalog": { + "convex": "^1.28.0", + "typescript": "^5.9.2", + "better-auth": "1.3.27", + "eslint": "^9.39.1", + "@eslint/js": "^9.39.1" + } + }, + "scripts": { + "check": "biome check --write .", + "dev": "turbo dev", + "build": "turbo build", + "check-types": "turbo check-types", + "dev:native": "turbo -F native dev", + "dev:web": "turbo -F web dev", + "dev:server": "turbo -F @sgse-app/backend dev", + "dev:setup": "turbo -F @sgse-app/backend dev:setup" + }, + "devDependencies": { + "eslint": "^9.39.1", + "eslint-plugin-svelte": "^3.13.0", + "globals": "^16.5.0", + "jiti": "^2.6.1", + "prettier": "^3.6.2", + "prettier-plugin-tailwindcss": "^0.7.1", + "turbo": "^2.5.8", + "typescript-eslint": "^8.46.3" + }, + "dependencies": { + "@tanstack/svelte-form": "^1.23.8", + "chart.js": "^4.5.1", + "lucide-svelte": "^0.552.0", + "prettier-plugin-svelte": "^3.4.0", + "svelte-chartjs": "^3.1.5", + "svelte-sonner": "^1.0.5" + }, + "packageManager": "bun@1.3.0" +} From 9bb13b486e1d1107c1509568a2c49c397fae4d57 Mon Sep 17 00:00:00 2001 From: killer-cf Date: Wed, 12 Nov 2025 09:11:48 -0300 Subject: [PATCH 2/5] add sevelt rules --- .cursor/rules/svelte_rules.mdc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .cursor/rules/svelte_rules.mdc diff --git a/.cursor/rules/svelte_rules.mdc b/.cursor/rules/svelte_rules.mdc new file mode 100644 index 0000000..f5799b3 --- /dev/null +++ b/.cursor/rules/svelte_rules.mdc @@ -0,0 +1,28 @@ +--- +description: Ajuda para escrever e editar aquivos svelte +alwaysApply: false +--- + +You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively: + +## Available MCP Tools: + +### 1. list-sections + +Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths. +When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections. + +### 2. get-documentation + +Retrieves full documentation content for specific sections. Accepts single or multiple sections. +After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task. + +### 3. svelte-autofixer + +Analyzes Svelte code and returns issues and suggestions. +You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned. + +### 4. playground-link + +Generates a Svelte Playground link with the provided code. +After completing the code, ask the user if they want a playground link. Only call this tool after user confirmation and NEVER if code was written to files in their project. From 1c56d71d43341fd4f2e235975bc710ff57c55fd2 Mon Sep 17 00:00:00 2001 From: killer-cf Date: Wed, 12 Nov 2025 10:24:45 -0300 Subject: [PATCH 3/5] refactor: update Svelte and TypeScript rules for improved application behavior - Set Svelte rules to always apply for consistent usage. - Adjust TypeScript rules to exclude .tsx files and ensure clarity in type safety guidelines. - Cleaned up formatting and examples for better readability and understanding. --- .cursor/rules/svelte_rules.mdc | 3 +- .cursor/rules/typescript_rules.mdc | 46 ++++++++++++++++++------------ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/.cursor/rules/svelte_rules.mdc b/.cursor/rules/svelte_rules.mdc index f5799b3..ee805b2 100644 --- a/.cursor/rules/svelte_rules.mdc +++ b/.cursor/rules/svelte_rules.mdc @@ -1,6 +1,5 @@ --- -description: Ajuda para escrever e editar aquivos svelte -alwaysApply: false +alwaysApply: true --- You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively: diff --git a/.cursor/rules/typescript_rules.mdc b/.cursor/rules/typescript_rules.mdc index 2eafacb..a5743ad 100644 --- a/.cursor/rules/typescript_rules.mdc +++ b/.cursor/rules/typescript_rules.mdc @@ -1,6 +1,7 @@ --- description: Guidelines for TypeScript usage, including type safety rules and Convex query typing -globs: **/*.ts,**/*.tsx,**/*.svelte +globs: **/*.ts,**/*.svelte +alwaysApply: false --- # TypeScript Guidelines @@ -8,6 +9,7 @@ globs: **/*.ts,**/*.tsx,**/*.svelte ## Type Safety Rules ### Avoid `any` Type + - **NEVER** use the `any` type in production code - The only exception is in test files (files matching `*.test.ts`, `*.test.tsx`, `*.spec.ts`, `*.spec.tsx`) - Instead of `any`, use: @@ -20,44 +22,48 @@ globs: **/*.ts,**/*.tsx,**/*.svelte ### Examples **❌ Bad:** + ```typescript function processData(data: any) { - return data.value; + return data.value; } ``` **✅ Good:** + ```typescript function processData(data: { value: string }) { - return data.value; + return data.value; } // Or with generics function processData(data: T) { - return data.value; + return data.value; } // Or with unknown and type guards function processData(data: unknown) { - if (typeof data === 'object' && data !== null && 'value' in data) { - return (data as { value: string }).value; - } - throw new Error('Invalid data'); + if (typeof data === 'object' && data !== null && 'value' in data) { + return (data as { value: string }).value; + } + throw new Error('Invalid data'); } ``` **✅ Exception (tests only):** + ```typescript // test.ts or *.spec.ts it('should handle any input', () => { - const input: any = getMockData(); - expect(process(input)).toBeDefined(); + const input: any = getMockData(); + expect(process(input)).toBeDefined(); }); ``` ## Convex Query Typing ### Frontend Query Usage + - **DO NOT** create manual type definitions for Convex query results in the frontend - Convex queries already return properly typed results based on their `returns` validator - The TypeScript types are automatically inferred from the query's return validator @@ -66,17 +72,19 @@ it('should handle any input', () => { ### Examples **❌ Bad:** + ```typescript // Don't manually type the result type UserListResult = Array<{ - _id: Id<"users">; - name: string; + _id: Id<'users'>; + name: string; }>; const users: UserListResult = useQuery(api.users.list); ``` **✅ Good:** + ```typescript // Let TypeScript infer the type from the query const users = useQuery(api.users.list); @@ -84,24 +92,26 @@ const users = useQuery(api.users.list); // You can still use it with type inference if (users !== undefined) { - users.forEach(user => { - // TypeScript knows user._id is Id<"users"> and user.name is string - console.log(user.name); - }); + users.forEach((user) => { + // TypeScript knows user._id is Id<"users"> and user.name is string + console.log(user.name); + }); } ``` **✅ Good (with explicit type if needed for clarity):** + ```typescript // Only if you need to export or explicitly annotate for documentation -import type { FunctionReturnType } from "convex/server"; -import type { api } from "./convex/_generated/api"; +import type { FunctionReturnType } from 'convex/server'; +import type { api } from './convex/_generated/api'; type UserListResult = FunctionReturnType; const users = useQuery(api.users.list); ``` ### Best Practices + - Trust Convex's type inference - it's based on your schema and validators - If you need type annotations, use `FunctionReturnType` from Convex's type utilities - Only create manual types if you're doing complex transformations that need intermediate types From 90bc5771ae8c873eb2957afb74ccc69513a8eb66 Mon Sep 17 00:00:00 2001 From: killer-cf Date: Wed, 12 Nov 2025 10:24:56 -0300 Subject: [PATCH 4/5] refactor: enhance role management and permissions handling - Introduced a new mutation for creating roles with validation and slugification of names. - Updated existing queries to improve role retrieval and error handling. - Enhanced permission copying functionality when creating new roles. - Improved code organization and readability by restructuring functions and adding type annotations. --- .../ti/painel-permissoes/+page.svelte | 1598 ++++++++--------- .../routes/(dashboard)/ti/times/+page.svelte | 1581 ++++++++-------- packages/backend/convex/roles.ts | 134 +- 3 files changed, 1668 insertions(+), 1645 deletions(-) diff --git a/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte b/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte index 8424660..1929feb 100644 --- a/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte +++ b/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte @@ -1,848 +1,836 @@ - - - + + + - -
-
-
- - - -
-
-

- Gerenciar Perfis & Permissões de Acesso -

-

- Configure as permissões de acesso aos menus do sistema por função -

-
- - -
-
+ +
+
+
+ + + +
+
+

+ Gerenciar Perfis & Permissões de Acesso +

+

+ Configure as permissões de acesso aos menus do sistema por função +

+
+ + +
+
- - {#if mensagem} -
- {#if mensagem.tipo === "success"} - - - - {:else} - - - - {/if} - {mensagem.texto} -
- {/if} + + {#if mensagem} +
+ {#if mensagem.tipo === 'success'} + + + + {:else} + + + + {/if} + {mensagem.texto} +
+ {/if} - -
-
-
- -
- -
- - - - -
-
+ +
+
+
+ +
+ +
+ + + + +
+
- -
- - -
-
+ +
+ + +
+
- {#if busca || filtroRole} -
- Filtros ativos: - {#if busca} -
- Busca: {busca} - -
- {/if} - {#if filtroRole} -
- Perfil filtrado - -
- {/if} -
- {/if} -
-
+ {#if busca || filtroRole} +
+ Filtros ativos: + {#if busca} +
+ Busca: {busca} + +
+ {/if} + {#if filtroRole} +
+ Perfil filtrado + +
+ {/if} +
+ {/if} +
+
- -
- - - -
-

Como funciona o sistema de permissões:

-
-
-

Tipos de Permissão:

-
    -
  • - • Acessar: Visualizar menu e acessar página -
  • -
  • Consultar: Ver dados (requer "Acessar")
  • -
  • - • Gravar: Criar/editar/excluir (requer "Consultar") -
  • -
-
-
-

Perfis Especiais:

-
    -
  • Admin e TI: Acesso total automático
  • -
  • Dashboard: Público para todos
  • -
  • - • Perfil Customizado: Permissões personalizadas -
  • -
-
-
-
-
+ +
+ + + +
+

Como funciona o sistema de permissões:

+
+
+

Tipos de Permissão:

+
    +
  • + • Acessar: Visualizar menu e acessar página +
  • +
  • Consultar: Ver dados (requer "Acessar")
  • +
  • + • Gravar: Criar/editar/excluir (requer "Consultar") +
  • +
+
+
+

Perfis Especiais:

+
    +
  • Admin: Acesso total automático
  • +
  • TI Master: Controle administrativo completo
  • +
  • Dashboard: Público para todos
  • +
+
+
+
+
- - {#if rolesQuery.isLoading || catalogoQuery.isLoading} -
- -
- {:else if rolesQuery.error} -
- - - - Erro ao carregar perfis: {rolesQuery.error.message} -
- {:else if rolesQuery.data && catalogoQuery.data} - {#if rolesFiltradas.length === 0} -
-
- - - -

Nenhum resultado encontrado

-

- {busca - ? `Não foram encontrados perfis com "${busca}"` - : "Nenhum perfil corresponde aos filtros aplicados"} -

- -
-
- {/if} + + {#if rolesQuery.isLoading || catalogoQuery.isLoading} +
+ +
+ {:else if rolesQuery.error} +
+ + + + Erro ao carregar perfis: {rolesQuery.error.message} +
+ {:else if rolesQuery.data && catalogoQuery.data} + {#if rolesFiltradas.length === 0} +
+
+ + + +

Nenhum resultado encontrado

+

+ {busca + ? `Não foram encontrados perfis com "${busca}"` + : 'Nenhum perfil corresponde aos filtros aplicados'} +

+ +
+
+ {/if} - {#each rolesFiltradas as roleRow} - {@const roleId = roleRow._id} -
-
-
-
-
-

{roleRow.descricao}

-
- Nível {roleRow.nivel} -
- {#if roleRow.nivel <= 1} -
- - - - Acesso Total -
- {/if} -
-

- {roleRow.nome} -

-
-
- -
-
+ {#each rolesFiltradas as roleRow (roleRow._id)} + {@const roleId = roleRow._id} +
+
+
+
+
+

{roleRow.descricao}

+
+ Nível {roleRow.nivel} +
+ {#if roleRow.nivel <= 1} +
+ + + + Acesso Total +
+ {/if} +
+

+ {roleRow.nome} +

+
+
- {#if roleRow.nivel <= 1} -
- - - -
-

Perfil Administrativo

-
- Este perfil possui acesso total ao sistema automaticamente, - sem necessidade de configuração manual. -
-
-
- {:else if catalogoQuery.data} -
- {#each catalogoQuery.data as item} - {@const recursoExpandido = isRecursoExpandido( - roleId, - item.recurso, - )} -
- - + {#if roleRow.nivel <= 1} +
+ + + +
+

Perfil Administrativo

+
+ Este perfil possui acesso total ao sistema automaticamente, sem necessidade de + configuração manual. +
+
+
+ {:else if catalogoQuery.data} +
+ {#each catalogoQuery.data as item (item.recurso)} + {@const recursoExpandido = isRecursoExpandido(roleId, item.recurso)} +
+ + - - {#if recursoExpandido} -
-
- {#each ["ver", "listar", "criar", "editar", "excluir"] as acao} - - {/each} -
-
- {/if} -
- {/each} -
- {/if} -
-
- {/each} - {/if} + + {#if recursoExpandido} +
+
+ {#each ['ver', 'listar', 'criar', 'editar', 'excluir'] as acao (acao)} + + {/each} +
+
+ {/if} +
+ {/each} +
+ {/if} +
+
+ {/each} + {/if} - - {#if modalGerenciarPerfisAberto} - - + + + {/if}
diff --git a/apps/web/src/routes/(dashboard)/ti/times/+page.svelte b/apps/web/src/routes/(dashboard)/ti/times/+page.svelte index f342979..38f7b96 100644 --- a/apps/web/src/routes/(dashboard)/ti/times/+page.svelte +++ b/apps/web/src/routes/(dashboard)/ti/times/+page.svelte @@ -1,873 +1,818 @@ - -
- - + +
+ + - -
-
-
-
- - - -
-
-

- Gestão de Times -

-

- Organize funcionários em equipes e defina gestores -

-
-
-
- - -
-
-
+ +
+
+
+
+ + + +
+
+

Gestão de Times

+

+ Organize funcionários em equipes e defina gestores +

+
+
+
+ + +
+
+
- - {#if modoEdicao} -
-
-

- {timeEmEdicao ? "Editar Time" : "Novo Time"} -

+ + {#if modoEdicao} +
+
+

+ {timeEmEdicao ? 'Editar Time' : 'Novo Time'} +

-
-
- - -
+
+
+ + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- -
- {#each coresDisponiveis as cor} - - {/each} -
-
-
+
+ +
+ {#each coresDisponiveis as cor (cor)} + + {/each} +
+
+
-
- - -
-
-
- {/if} +
+ + +
+
+
+ {/if} - - {#if carregando} -
- -
- {:else} -
- {#each times.filter((t: TimeComDetalhes) => t.ativo) as time} -
-
-
-
-
-

{time.nome}

-
- -
+ + {#if carregando} +
+ +
+ {:else} +
+ {#each times.filter((t: TimeComDetalhes) => t.ativo) as time (time._id)} +
+
+
+
+
+

{time.nome}

+
+ +
-

- {time.descricao || "Sem descrição"} -

+

+ {time.descricao || 'Sem descrição'} +

-
+
-
-
- - - - Gestor: - {time.gestor?.nome || "Não definido"} -
-
- - - - Membros: - {time.totalMembros || 0} -
-
+
+
+ + + + Gestor: + {time.gestor?.nome || 'Não definido'} +
+
+ + + + Membros: + {time.totalMembros || 0} +
+
-
- -
-
-
- {/each} +
+ +
+
+
+ {/each} - {#if times.filter((t: TimeComDetalhes) => t.ativo).length === 0} -
-
- - - -

Nenhum time cadastrado

-

- Clique em "Novo Time" para criar seu primeiro time -

-
-
- {/if} -
- {/if} + {#if times.filter((t: TimeComDetalhes) => t.ativo).length === 0} +
+
+ + + +

Nenhum time cadastrado

+

+ Clique em "Novo Time" para criar seu primeiro time +

+
+
+ {/if} +
+ {/if} - - {#if mostrarModalMembros && timeParaMembros} - - + + + {/if} - - {#if mostrarConfirmacaoExclusao && timeParaExcluir} - - - - - {/if} -
+ + {#if mostrarConfirmacaoExclusao && timeParaExcluir} + + + + + {/if} +
diff --git a/packages/backend/convex/roles.ts b/packages/backend/convex/roles.ts index 6f9d25f..f21547e 100644 --- a/packages/backend/convex/roles.ts +++ b/packages/backend/convex/roles.ts @@ -1,35 +1,125 @@ -import { v } from "convex/values"; -import { query } from "./_generated/server"; +import { v } from 'convex/values'; +import { query, mutation } from './_generated/server'; +import type { Id } from './_generated/dataModel'; +import { getCurrentUserFunction } from './auth'; /** * Listar todas as roles */ export const listar = query({ - args: {}, - handler: async (ctx) => { - return await ctx.db.query("roles").collect(); - }, + args: {}, + handler: async (ctx) => { + return await ctx.db.query('roles').collect(); + } }); /** * Buscar role por ID */ export const buscarPorId = query({ - args: { - roleId: v.id("roles"), - }, - returns: v.union( - v.object({ - _id: v.id("roles"), - nome: v.string(), - descricao: v.string(), - nivel: v.number(), - setor: v.optional(v.string()), - }), - v.null() - ), - handler: async (ctx, args) => { - return await ctx.db.get(args.roleId); - }, + args: { + roleId: v.id('roles') + }, + returns: v.union( + v.object({ + _id: v.id('roles'), + nome: v.string(), + descricao: v.string(), + nivel: v.number(), + setor: v.optional(v.string()) + }), + v.null() + ), + handler: async (ctx, args) => { + return await ctx.db.get(args.roleId); + } }); +const slugify = (value: string) => + value + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .trim() + .toLowerCase() + .replace(/[^a-z0-9]+/g, '_') + .replace(/^_+|_+$/g, '') + .replace(/_{2,}/g, '_'); + +export const criar = mutation({ + args: { + nome: v.string(), + descricao: v.string(), + nivel: v.number(), + setor: v.optional(v.string()), + copiarDeRoleId: v.optional(v.id('roles')) + }, + returns: v.union( + v.object({ sucesso: v.literal(true), roleId: v.id('roles') }), + v.object({ sucesso: v.literal(false), erro: v.string() }) + ), + handler: async (ctx, args) => { + const usuarioAtual = await getCurrentUserFunction(ctx); + if (!usuarioAtual) { + return { sucesso: false as const, erro: 'nao_autenticado' }; + } + + const roleAtual = await ctx.db.get(usuarioAtual.roleId); + if (!roleAtual || roleAtual.nivel > 1) { + return { sucesso: false as const, erro: 'sem_permissao' }; + } + + const nomeNormalizado = slugify(args.nome); + if (!nomeNormalizado) { + return { sucesso: false as const, erro: 'nome_invalido' }; + } + + const existente = await ctx.db + .query('roles') + .withIndex('by_nome', (q) => q.eq('nome', nomeNormalizado)) + .unique(); + + if (existente) { + return { sucesso: false as const, erro: 'nome_ja_utilizado' }; + } + + let permissoesParaCopiar: Array> = []; + + if (args.copiarDeRoleId) { + const roleOrigem = await ctx.db.get(args.copiarDeRoleId); + if (!roleOrigem) { + return { sucesso: false as const, erro: 'role_origem_nao_encontrada' }; + } + + const permissoesOrigem = await ctx.db + .query('rolePermissoes') + .withIndex('by_role', (q) => q.eq('roleId', args.copiarDeRoleId!)) + .collect(); + + permissoesParaCopiar = permissoesOrigem.map((item) => item.permissaoId); + } + + const nivelAjustado = Math.min(Math.max(Math.round(args.nivel), 0), 10); + const setor = args.setor?.trim(); + + const roleId = await ctx.db.insert('roles', { + nome: nomeNormalizado, + descricao: args.descricao.trim() || args.nome.trim(), + nivel: nivelAjustado, + setor: setor && setor.length > 0 ? setor : undefined, + customizado: true, + criadoPor: usuarioAtual._id, + editavel: true + }); + + if (permissoesParaCopiar.length > 0) { + for (const permissaoId of permissoesParaCopiar) { + await ctx.db.insert('rolePermissoes', { + roleId, + permissaoId + }); + } + } + + return { sucesso: true as const, roleId }; + } +}); From da26a21f7eb782d3579f4752fbca3e635ef487da Mon Sep 17 00:00:00 2001 From: killer-cf Date: Wed, 12 Nov 2025 11:59:53 -0300 Subject: [PATCH 5/5] refactor: update permissions and clean up Svelte component - Removed outdated information about the permissions system from the Svelte component. - Added new actions for resource management in the backend, including 'aprovar_ausencias' and 'aprovar_ferias'. - Cleaned up console logs in the user retrieval function for better performance and security. --- .../ti/painel-permissoes/+page.svelte | 42 ------------------- packages/backend/convex/permissoesAcoes.ts | 11 ++++- packages/backend/convex/usuarios.ts | 3 -- 3 files changed, 10 insertions(+), 46 deletions(-) diff --git a/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte b/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte index 1929feb..f4225cb 100644 --- a/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte +++ b/apps/web/src/routes/(dashboard)/ti/painel-permissoes/+page.svelte @@ -428,48 +428,6 @@ - -
- - - -
-

Como funciona o sistema de permissões:

-
-
-

Tipos de Permissão:

-
    -
  • - • Acessar: Visualizar menu e acessar página -
  • -
  • Consultar: Ver dados (requer "Acessar")
  • -
  • - • Gravar: Criar/editar/excluir (requer "Consultar") -
  • -
-
-
-

Perfis Especiais:

-
    -
  • Admin: Acesso total automático
  • -
  • TI Master: Controle administrativo completo
  • -
  • Dashboard: Público para todos
  • -
-
-
-
-
- {#if rolesQuery.isLoading || catalogoQuery.isLoading}
diff --git a/packages/backend/convex/permissoesAcoes.ts b/packages/backend/convex/permissoesAcoes.ts index 762507b..f9f0b3c 100644 --- a/packages/backend/convex/permissoesAcoes.ts +++ b/packages/backend/convex/permissoesAcoes.ts @@ -8,7 +8,16 @@ import { getCurrentUserFunction } from './auth'; export const CATALOGO_RECURSOS = [ { recurso: 'funcionarios', - acoes: ['dashboard', 'ver', 'listar', 'criar', 'editar', 'excluir'] + acoes: [ + 'dashboard', + 'ver', + 'listar', + 'criar', + 'editar', + 'excluir', + 'aprovar_ausencias', + 'aprovar_ferias' + ] }, { recurso: 'simbolos', diff --git a/packages/backend/convex/usuarios.ts b/packages/backend/convex/usuarios.ts index b045cdb..cd62bac 100644 --- a/packages/backend/convex/usuarios.ts +++ b/packages/backend/convex/usuarios.ts @@ -562,15 +562,12 @@ export const obterPerfil = query({ ), handler: async (ctx) => { const usuarioAutenticado = await getCurrentUserFunction(ctx); - console.log('Usuario autenticado:', usuarioAutenticado); if (!usuarioAutenticado) { return null; } const usuarioAtual = usuarioAutenticado; - console.log('✅ Usuário encontrado:', usuarioAtual.nome); - // Buscar fotoPerfil URL se existir let fotoPerfilUrl = null; if (usuarioAtual.fotoPerfil) {