diff --git a/apps/web/package.json b/apps/web/package.json
index 05356ec..3657380 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -28,6 +28,7 @@
"@mmailaender/convex-better-auth-svelte": "^0.2.0",
"@sgse-app/backend": "workspace:*",
"@tanstack/svelte-form": "^1.19.2",
+ "better-auth": "^1.3.29",
"convex": "catalog:",
"convex-svelte": "^0.0.11",
"zod": "^4.0.17"
diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/+page.svelte
index 0935f1a..fdf04dc 100644
--- a/apps/web/src/routes/(dashboard)/recursos-humanos/+page.svelte
+++ b/apps/web/src/routes/(dashboard)/recursos-humanos/+page.svelte
@@ -1 +1,39 @@
-
Recursos Humanos
+
+
+
diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/+page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/[funcionarioId]/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/[funcionarioId]/+page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/cadastro/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/funcionarios/cadastro/+page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/simbolos/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/simbolos/+page.svelte
new file mode 100644
index 0000000..8306e5b
--- /dev/null
+++ b/apps/web/src/routes/(dashboard)/recursos-humanos/simbolos/+page.svelte
@@ -0,0 +1,21 @@
+
+
+
+
Simbolos
+
+ {#each simbolosQuery.data as simbolo}
+
+
{simbolo.nome}
+
{simbolo.vencValor}
+
{simbolo.repValor}
+
{simbolo.descricao}
+
+ {:else}
+
Nenhum simbolo encontrado
+ {/each}
+
diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/simbolos/cadastro/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/simbolos/cadastro/+page.svelte
new file mode 100644
index 0000000..f014519
--- /dev/null
+++ b/apps/web/src/routes/(dashboard)/recursos-humanos/simbolos/cadastro/+page.svelte
@@ -0,0 +1,381 @@
+
+
+
diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte
index ad2eb10..72b7726 100644
--- a/apps/web/src/routes/+layout.svelte
+++ b/apps/web/src/routes/+layout.svelte
@@ -1,12 +1,13 @@
diff --git a/bun.lock b/bun.lock
index 32678df..b1f0cc9 100644
--- a/bun.lock
+++ b/bun.lock
@@ -3,6 +3,10 @@
"workspaces": {
"": {
"name": "sgse-app",
+ "dependencies": {
+ "@tanstack/svelte-form": "^1.23.8",
+ "lucide-svelte": "^0.546.0",
+ },
"devDependencies": {
"@biomejs/biome": "^2.2.0",
"turbo": "^2.5.4",
@@ -16,6 +20,7 @@
"@mmailaender/convex-better-auth-svelte": "^0.2.0",
"@sgse-app/backend": "workspace:*",
"@tanstack/svelte-form": "^1.19.2",
+ "better-auth": "^1.3.29",
"convex": "catalog:",
"convex-svelte": "^0.0.11",
"zod": "^4.0.17",
@@ -67,6 +72,8 @@
"packages": {
"@better-auth/core": ["@better-auth/core@1.3.27", "", { "dependencies": { "better-call": "1.0.19", "zod": "^4.1.5" } }, "sha512-3Sfdax6MQyronY+znx7bOsfQHI6m1SThvJWb0RDscFEAhfqLy95k1sl+/PgGyg0cwc2cUXoEiAOSqYdFYrg3vA=="],
+ "@better-auth/telemetry": ["@better-auth/telemetry@1.3.29", "", { "dependencies": { "@better-auth/core": "1.3.29", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18" } }, "sha512-1BFh3YulYDrwWcUkfEWddcrcApACyI4wtrgq3NBd9y+tilBRjWTCWEPuRqJrfM3a5F1ZSqsvOYfFG1XZbkxlVw=="],
+
"@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="],
"@better-fetch/fetch": ["@better-fetch/fetch@1.1.18", "", {}, "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA=="],
@@ -285,11 +292,13 @@
"@tanstack/devtools-event-client": ["@tanstack/devtools-event-client@0.3.3", "", {}, "sha512-RfV+OPV/M3CGryYqTue684u10jUt55PEqeBOnOtCe6tAmHI9Iqyc8nHeDhWPEV9715gShuauFVaMc9RiUVNdwg=="],
- "@tanstack/form-core": ["@tanstack/form-core@1.24.3", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.3.2", "@tanstack/store": "^0.7.7" } }, "sha512-e+HzSD49NWr4aIqJWtPPzmi+/phBJAP3nSPN8dvxwmJWqAxuB/cH138EcmCFf3+oA7j3BXvwvTY0I+8UweGPjQ=="],
+ "@tanstack/form-core": ["@tanstack/form-core@1.24.4", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.3.3", "@tanstack/pacer": "^0.15.3", "@tanstack/store": "^0.7.7" } }, "sha512-+eIR7DiDamit1zvTVgaHxuIRA02YFgJaXMUGxsLRJoBpUjGl/g/nhUocQoNkRyfXqOlh8OCMTanjwDprWSRq6w=="],
+
+ "@tanstack/pacer": ["@tanstack/pacer@0.15.4", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.3.2", "@tanstack/store": "^0.7.5" } }, "sha512-vGY+CWsFZeac3dELgB6UZ4c7OacwsLb8hvL2gLS6hTgy8Fl0Bm/aLokHaeDIP+q9F9HUZTnp360z9uv78eg8pg=="],
"@tanstack/store": ["@tanstack/store@0.7.7", "", {}, "sha512-xa6pTan1bcaqYDS9BDpSiS63qa6EoDkPN9RsRaxHuDdVDNntzq3xNwR5YKTU/V3SkSyC9T4YVOPh2zRQN0nhIQ=="],
- "@tanstack/svelte-form": ["@tanstack/svelte-form@1.23.7", "", { "dependencies": { "@tanstack/form-core": "1.24.3", "@tanstack/svelte-store": "^0.7.7" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-OrUH1nR+icLm3fTgyHj34fHHZS9F2o+Z/7a/EJE3PhH4YV3XOOmc/okes28UVeWypuBv7Iu/vCc9cEAD/6ltpA=="],
+ "@tanstack/svelte-form": ["@tanstack/svelte-form@1.23.8", "", { "dependencies": { "@tanstack/form-core": "1.24.4", "@tanstack/svelte-store": "^0.7.7" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-ZH17T/gOQ9sBpI/38zBCBiuceLsa9c9rOgwB7CRt/FBFunIkaG2gY02IiUBpjZfm1fiKBcTryaJGfR3XAtIH/g=="],
"@tanstack/svelte-store": ["@tanstack/svelte-store@0.7.7", "", { "dependencies": { "@tanstack/store": "0.7.7" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-JeDyY7SxBi6EKzkf2wWoghdaC2bvmwNL9X/dgkx7LKEvJVle+te7tlELI3cqRNGbjXt9sx+97jx9M5dCCHcuog=="],
@@ -389,6 +398,8 @@
"locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="],
+ "lucide-svelte": ["lucide-svelte@0.546.0", "", { "peerDependencies": { "svelte": "^3 || ^4 || ^5.0.0-next.42" } }, "sha512-vCvBUlFapD59ivX1b/i7wdUadSgC/3gQGvrGEZjSecOlThT+UR+X5UxdVEakHuhniTrSX0nJ2WrY5r25SVDtyQ=="],
+
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
@@ -487,6 +498,8 @@
"zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="],
+ "@better-auth/telemetry/@better-auth/core": ["@better-auth/core@1.3.29", "", { "dependencies": { "zod": "^4.1.5" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18", "better-call": "1.0.19", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-Ka2mg4qZACFaLY7DOGFXv1Ma8CkF17k0ClUd2U/ZJbbSoEPI5gnVguEmakJB6HFYswszeZh2295IFORtW9wf7A=="],
+
"@convex-dev/better-auth/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.6.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg=="],
@@ -505,6 +518,8 @@
"vite/esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="],
+ "web/better-auth": ["better-auth@1.3.29", "", { "dependencies": { "@better-auth/core": "1.3.29", "@better-auth/telemetry": "1.3.29", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "@simplewebauthn/browser": "^13.1.2", "@simplewebauthn/server": "^13.1.2", "better-call": "1.0.19", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.5" } }, "sha512-1va1XZLTQme3DX33PgHqwwVyOJya5H0+ozT6BhOjTnwecC50I75F0OqqTwINq4XZ0+GuD3bl3I55RiFP49jStw=="],
+
"vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="],
"vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="],
@@ -554,5 +569,7 @@
"vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="],
"vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="],
+
+ "web/better-auth/@better-auth/core": ["@better-auth/core@1.3.29", "", { "dependencies": { "zod": "^4.1.5" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.18", "better-call": "1.0.19", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-Ka2mg4qZACFaLY7DOGFXv1Ma8CkF17k0ClUd2U/ZJbbSoEPI5gnVguEmakJB6HFYswszeZh2295IFORtW9wf7A=="],
}
}
diff --git a/package.json b/package.json
index f8e917b..50128c2 100644
--- a/package.json
+++ b/package.json
@@ -27,5 +27,9 @@
"turbo": "^2.5.4",
"@biomejs/biome": "^2.2.0"
},
- "packageManager": "bun@1.3.0"
+ "packageManager": "bun@1.3.0",
+ "dependencies": {
+ "@tanstack/svelte-form": "^1.23.8",
+ "lucide-svelte": "^0.546.0"
+ }
}
diff --git a/packages/backend/convex/_generated/api.d.ts b/packages/backend/convex/_generated/api.d.ts
index 6e2c911..46eb3a8 100644
--- a/packages/backend/convex/_generated/api.d.ts
+++ b/packages/backend/convex/_generated/api.d.ts
@@ -13,8 +13,10 @@ import type * as betterAuth__generated_api from "../betterAuth/_generated/api.js
import type * as betterAuth__generated_server from "../betterAuth/_generated/server.js";
import type * as betterAuth_adapter from "../betterAuth/adapter.js";
import type * as betterAuth_auth from "../betterAuth/auth.js";
+import type * as funcionarios from "../funcionarios.js";
import type * as healthCheck from "../healthCheck.js";
import type * as http from "../http.js";
+import type * as simbolos from "../simbolos.js";
import type * as todos from "../todos.js";
import type {
@@ -37,8 +39,10 @@ declare const fullApi: ApiFromModules<{
"betterAuth/_generated/server": typeof betterAuth__generated_server;
"betterAuth/adapter": typeof betterAuth_adapter;
"betterAuth/auth": typeof betterAuth_auth;
+ funcionarios: typeof funcionarios;
healthCheck: typeof healthCheck;
http: typeof http;
+ simbolos: typeof simbolos;
todos: typeof todos;
}>;
declare const fullApiWithMounts: typeof fullApi;
diff --git a/packages/backend/convex/funcionarios.ts b/packages/backend/convex/funcionarios.ts
index e69de29..753e307 100644
--- a/packages/backend/convex/funcionarios.ts
+++ b/packages/backend/convex/funcionarios.ts
@@ -0,0 +1,24 @@
+import { v } from "convex/values";
+import { query, mutation } from "./_generated/server";
+
+export const getAll = query({
+ handler: async (ctx) => {
+ return await ctx.db.query("funcionarios").collect();
+ },
+});
+
+export const create = mutation({
+ args: {
+ nome: v.string(),
+ matricula: v.string(),
+ simboloId: v.id("simbolos"),
+ },
+ handler: async (ctx, args) => {
+ const novoFuncionarioId = await ctx.db.insert("funcionarios", {
+ nome: args.nome,
+ matricula: args.matricula,
+ simboloId: args.simboloId,
+ });
+ return await ctx.db.get(novoFuncionarioId);
+ },
+});
diff --git a/packages/backend/convex/schema.ts b/packages/backend/convex/schema.ts
index 7ed6938..7bd5455 100644
--- a/packages/backend/convex/schema.ts
+++ b/packages/backend/convex/schema.ts
@@ -1,7 +1,13 @@
import { defineSchema, defineTable } from "convex/server";
-import { v } from "convex/values";
+import { Infer, v } from "convex/values";
import { tables } from "./betterAuth/schema";
+export const simboloTipo = v.union(
+ v.literal("cargo_comissionado"),
+ v.literal("funcao_gratificada")
+);
+export type SimboloTipo = Infer;
+
export default defineSchema({
...tables,
todos: defineTable({
@@ -20,13 +26,21 @@ export default defineSchema({
telefone: v.optional(v.string()),
email: v.optional(v.string()),
matricula: v.string(),
- simbolo: v.optional(v.string()),
vencimento: v.optional(v.string()),
admissao: v.optional(v.string()),
desligamento: v.optional(v.string()),
ferias: v.optional(v.string()),
- atestado: v.optional(v.string()),
+ simboloId: v.id("simbolos"),
})
.index("by_matricula", ["matricula"])
.index("by_nome", ["nome"]),
+
+ simbolos: defineTable({
+ nome: v.string(),
+ tipo: simboloTipo,
+ descricao: v.string(),
+ vencValor: v.string(),
+ repValor: v.string(),
+ valor: v.string(),
+ }),
});
diff --git a/packages/backend/convex/simbolos.ts b/packages/backend/convex/simbolos.ts
new file mode 100644
index 0000000..5686fea
--- /dev/null
+++ b/packages/backend/convex/simbolos.ts
@@ -0,0 +1,50 @@
+import { v } from "convex/values";
+import { query, mutation } from "./_generated/server";
+import { simboloTipo } from "./schema";
+
+export const getAll = query({
+ handler: async (ctx) => {
+ return await ctx.db.query("simbolos").collect();
+ },
+});
+
+export const create = mutation({
+ args: {
+ nome: v.string(),
+ tipo: simboloTipo,
+ refValor: v.string(),
+ vencValor: v.string(),
+ descricao: v.string(),
+ valor: v.optional(v.string()),
+ },
+ handler: async (ctx, args) => {
+ let refValor = args.refValor;
+ let vencValor = args.vencValor;
+ let valor = args.valor ?? "";
+
+ if (args.tipo === "cargo_comissionado") {
+ if (!refValor || !vencValor) {
+ throw new Error(
+ "Valor de referência e valor de vencimento são obrigatórios para cargo comissionado"
+ );
+ }
+ valor = (Number(refValor) + Number(vencValor)).toFixed(2);
+ } else {
+ if (!args.valor) {
+ throw new Error("Valor é obrigatório para função gratificada");
+ }
+ refValor = "";
+ vencValor = "";
+ valor = args.valor;
+ }
+ const novoSimboloId = await ctx.db.insert("simbolos", {
+ nome: args.nome,
+ descricao: args.descricao,
+ repValor: refValor,
+ vencValor: vencValor,
+ tipo: args.tipo,
+ valor,
+ });
+ return await ctx.db.get(novoSimboloId);
+ },
+});