adiciona funcionarios pagina
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
"@mmailaender/convex-better-auth-svelte": "^0.2.0",
|
"@mmailaender/convex-better-auth-svelte": "^0.2.0",
|
||||||
"@sgse-app/backend": "workspace:*",
|
"@sgse-app/backend": "workspace:*",
|
||||||
"@tanstack/svelte-form": "^1.19.2",
|
"@tanstack/svelte-form": "^1.19.2",
|
||||||
|
"better-auth": "^1.3.29",
|
||||||
"convex": "catalog:",
|
"convex": "catalog:",
|
||||||
"convex-svelte": "^0.0.11",
|
"convex-svelte": "^0.0.11",
|
||||||
"zod": "^4.0.17"
|
"zod": "^4.0.17"
|
||||||
|
|||||||
@@ -1 +1,39 @@
|
|||||||
<h1 class="text-2xl font-bold">Recursos Humanos</h1>
|
<script>
|
||||||
|
import { resolve } from "$app/paths";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h2 class="text-3xl font-bold text-brand-dark">Recursos Humanos</h2>
|
||||||
|
|
||||||
|
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
|
<h3 class="text-lg font-bold text-brand-dark col-span-4">Funcionários</h3>
|
||||||
|
<a
|
||||||
|
href={resolve("/recursos-humanos/funcionarios/cadastro")}
|
||||||
|
class="p-4 rounded-xl border hover:shadow bgbase-100"
|
||||||
|
>Cadastrar Funcionários</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={resolve("/recursos-humanos/funcionarios/editar")}
|
||||||
|
class="p-4 rounded-xl border hover:shadow bgbase-100">Editar Cadastro</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={resolve("/recursos-humanos/funcionarios/excluir")}
|
||||||
|
class="p-4 rounded-xl border hover:shadow bgbase-100">Excluir Cadastro</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={resolve("/recursos-humanos/funcionarios/relatorios")}
|
||||||
|
class="p-4 rounded-xl border hover:shadow bgbase-100">Relatórios</a
|
||||||
|
>
|
||||||
|
|
||||||
|
<h3 class="text-lg font-bold text-brand-dark col-span-4">Simbolos</h3>
|
||||||
|
<a
|
||||||
|
href={resolve("/recursos-humanos/simbolos/cadastro")}
|
||||||
|
class="p-4 rounded-xl border hover:shadow bgbase-100"
|
||||||
|
>Cadastrar Simbolos</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={resolve("/recursos-humanos/simbolos")}
|
||||||
|
class="p-4 rounded-xl border hover:shadow bgbase-100">Listar Simbolos</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { useQuery } from "convex-svelte";
|
||||||
|
import { api } from "@sgse-app/backend/convex/_generated/api";
|
||||||
|
|
||||||
|
const simbolosQuery = useQuery(api.simbolos.getAll, {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<h2 class="text-3xl font-bold text-brand-dark">Simbolos</h2>
|
||||||
|
|
||||||
|
{#each simbolosQuery.data as simbolo}
|
||||||
|
<div class="p-4 rounded-xl border hover:shadow bgbase-100">
|
||||||
|
<h3 class="text-lg font-bold text-brand-dark">{simbolo.nome}</h3>
|
||||||
|
<p class="text-sm text-gray-500">{simbolo.vencValor}</p>
|
||||||
|
<p class="text-sm text-gray-500">{simbolo.repValor}</p>
|
||||||
|
<p class="text-sm text-gray-500">{simbolo.descricao}</p>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<p>Nenhum simbolo encontrado</p>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,381 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { useConvexClient } from "convex-svelte";
|
||||||
|
import { api } from "@sgse-app/backend/convex/_generated/api";
|
||||||
|
import { createForm } from "@tanstack/svelte-form";
|
||||||
|
import z from "zod";
|
||||||
|
import { Plus } from "lucide-svelte";
|
||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import type { SimboloTipo } from "@sgse-app/backend/convex/schema";
|
||||||
|
|
||||||
|
const client = useConvexClient();
|
||||||
|
|
||||||
|
let tipo = $state<SimboloTipo>("cargo_comissionado");
|
||||||
|
|
||||||
|
const defaultValues = {
|
||||||
|
nome: "",
|
||||||
|
refValor: "",
|
||||||
|
vencValor: "",
|
||||||
|
descricao: "",
|
||||||
|
tipo: "cargo_comissionado",
|
||||||
|
valor: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
nome: z.string().min(1),
|
||||||
|
refValor: z.string().optional(),
|
||||||
|
vencValor: z.string().optional(),
|
||||||
|
descricao: z.string().min(1),
|
||||||
|
tipo: z.enum(["cargo_comissionado", "funcao_gratificada"]),
|
||||||
|
valor: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
function formatCurrencyBR(raw: string): string {
|
||||||
|
const digits = (raw || "").replace(/\D/g, "");
|
||||||
|
if (!digits) return "";
|
||||||
|
const number = parseInt(digits, 10);
|
||||||
|
const cents = (number / 100).toFixed(2);
|
||||||
|
const [intPart, decPart] = cents.split(".");
|
||||||
|
const intWithThousands = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
||||||
|
return `${intWithThousands},${decPart}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmaskCurrencyToDotDecimal(masked: string): string {
|
||||||
|
if (!masked) return "";
|
||||||
|
const digits = masked.replace(/\D/g, "");
|
||||||
|
if (!digits) return "";
|
||||||
|
const value = (parseInt(digits, 10) / 100).toFixed(2);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDotDecimalToBR(value: string): string {
|
||||||
|
if (!value) return "";
|
||||||
|
const [intPart, decRaw] = value.split(".");
|
||||||
|
const intDigits = (intPart || "0").replace(/\D/g, "");
|
||||||
|
const intWithThousands = intDigits.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
||||||
|
const decPart = (decRaw ?? "00").padEnd(2, "0").slice(0, 2);
|
||||||
|
return `${intWithThousands},${decPart}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let notice = $state<{ kind: "success" | "error"; text: string } | null>(null);
|
||||||
|
function getTotalPreview(): string {
|
||||||
|
if (tipo !== "cargo_comissionado") return "";
|
||||||
|
const r = unmaskCurrencyToDotDecimal(form.getFieldValue("refValor"));
|
||||||
|
const v = unmaskCurrencyToDotDecimal(form.getFieldValue("vencValor"));
|
||||||
|
if (!r || !v) return "";
|
||||||
|
const sum = (Number(r) + Number(v)).toFixed(2);
|
||||||
|
return formatDotDecimalToBR(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
const form = createForm(() => ({
|
||||||
|
onSubmit: async ({ value, formApi }) => {
|
||||||
|
const isCargo = value.tipo === "cargo_comissionado";
|
||||||
|
const payload = {
|
||||||
|
nome: value.nome,
|
||||||
|
refValor: isCargo ? unmaskCurrencyToDotDecimal(value.refValor) : "",
|
||||||
|
vencValor: isCargo ? unmaskCurrencyToDotDecimal(value.vencValor) : "",
|
||||||
|
descricao: value.descricao,
|
||||||
|
tipo: value.tipo as SimboloTipo,
|
||||||
|
valor: !isCargo ? unmaskCurrencyToDotDecimal(value.valor) : undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await client.mutation(api.simbolos.create, payload);
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
formApi.reset();
|
||||||
|
notice = { kind: "success", text: "Símbolo cadastrado com sucesso." };
|
||||||
|
setTimeout(() => goto("/recursos-humanos/simbolos"), 600);
|
||||||
|
} else {
|
||||||
|
console.log("erro ao registrar cliente");
|
||||||
|
notice = { kind: "error", text: "Erro ao cadastrar símbolo." };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
defaultValues,
|
||||||
|
}));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form
|
||||||
|
class="max-w-3xl mx-auto p-4"
|
||||||
|
onsubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
form.handleSubmit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="card bg-base-100 shadow-xl">
|
||||||
|
<div class="card-body space-y-6">
|
||||||
|
{#if notice}
|
||||||
|
<div
|
||||||
|
class="alert"
|
||||||
|
class:alert-success={notice.kind === "success"}
|
||||||
|
class:alert-error={notice.kind === "error"}
|
||||||
|
>
|
||||||
|
<span>{notice.text}</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div>
|
||||||
|
<h2 class="card-title text-3xl">Cadastro de Símbolos</h2>
|
||||||
|
<p class="opacity-70">
|
||||||
|
Preencha os campos abaixo para cadastrar um novo símbolo.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form.Field name="nome" validators={{ onChange: schema.shape.nome }}>
|
||||||
|
{#snippet children({ name, state, handleChange })}
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="nome">
|
||||||
|
<span class="label-text font-medium"
|
||||||
|
>Símbolo <span class="text-error">*</span></span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
{name}
|
||||||
|
value={state.value}
|
||||||
|
placeholder="Ex.: DAS-1"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
autocomplete="off"
|
||||||
|
oninput={(e) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
const value = target.value;
|
||||||
|
handleChange(value);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
aria-required="true"
|
||||||
|
/>
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text-alt opacity-60"
|
||||||
|
>Informe o nome identificador do símbolo.</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</form.Field>
|
||||||
|
|
||||||
|
<form.Field
|
||||||
|
name="descricao"
|
||||||
|
validators={{ onChange: schema.shape.descricao }}
|
||||||
|
>
|
||||||
|
{#snippet children({ name, state, handleChange })}
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="descricao">
|
||||||
|
<span class="label-text font-medium"
|
||||||
|
>Descrição <span class="text-error">*</span></span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
{name}
|
||||||
|
value={state.value}
|
||||||
|
placeholder="Ex.: Cargo de Apoio 1"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
autocomplete="off"
|
||||||
|
oninput={(e) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
const value = target.value;
|
||||||
|
handleChange(value);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
aria-required="true"
|
||||||
|
/>
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text-alt opacity-60"
|
||||||
|
>Descreva brevemente o símbolo.</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</form.Field>
|
||||||
|
|
||||||
|
<form.Field
|
||||||
|
name="tipo"
|
||||||
|
validators={{
|
||||||
|
onChange: ({ value }) => (value ? undefined : "Obrigatório"),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#snippet children({ name, state, handleChange })}
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="tipo">
|
||||||
|
<span class="label-text font-medium"
|
||||||
|
>type <span class="text-error">*</span></span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
{name}
|
||||||
|
class="select select-bordered w-full"
|
||||||
|
value={tipo}
|
||||||
|
oninput={(e) => {
|
||||||
|
const target = e.target as HTMLSelectElement;
|
||||||
|
const value = target.value;
|
||||||
|
handleChange(value);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
aria-required="true"
|
||||||
|
>
|
||||||
|
<option value="cargo_comissionado">Cargo comissionado</option>
|
||||||
|
<option value="funcao_gratificada">Função gratificada</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</form.Field>
|
||||||
|
|
||||||
|
{#if tipo === "cargo_comissionado"}
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<form.Field
|
||||||
|
name="vencValor"
|
||||||
|
validators={{
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
form.getFieldValue("tipo") === "cargo_comissionado" && !value
|
||||||
|
? "Obrigatório"
|
||||||
|
: undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#snippet children({ name, state, handleChange })}
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="vencValor">
|
||||||
|
<span class="label-text font-medium"
|
||||||
|
>Valor de Vencimento <span class="text-error">*</span></span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
{name}
|
||||||
|
value={state.value}
|
||||||
|
placeholder="Ex.: 1200,00"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
inputmode="decimal"
|
||||||
|
autocomplete="off"
|
||||||
|
oninput={(e) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
const formatted = formatCurrencyBR(target.value);
|
||||||
|
target.value = formatted;
|
||||||
|
handleChange(formatted);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
aria-required="true"
|
||||||
|
/>
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text-alt opacity-60"
|
||||||
|
>Valor efetivo de vencimento.</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</form.Field>
|
||||||
|
|
||||||
|
<form.Field
|
||||||
|
name="refValor"
|
||||||
|
validators={{
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
form.getFieldValue("tipo") === "cargo_comissionado" && !value
|
||||||
|
? "Obrigatório"
|
||||||
|
: undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#snippet children({ name, state, handleChange })}
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="refValor">
|
||||||
|
<span class="label-text font-medium"
|
||||||
|
>Valor de Referência <span class="text-error">*</span></span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
{name}
|
||||||
|
value={state.value}
|
||||||
|
placeholder="Ex.: 1000,00"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
inputmode="decimal"
|
||||||
|
autocomplete="off"
|
||||||
|
oninput={(e) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
const formatted = formatCurrencyBR(target.value);
|
||||||
|
target.value = formatted;
|
||||||
|
handleChange(formatted);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
aria-required="true"
|
||||||
|
/>
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text-alt opacity-60"
|
||||||
|
>Valor base de referência.</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</form.Field>
|
||||||
|
</div>
|
||||||
|
{#if getTotalPreview()}
|
||||||
|
<div class="alert bg-base-200">
|
||||||
|
<span>Total previsto: R$ {getTotalPreview()}</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<form.Field
|
||||||
|
name="valor"
|
||||||
|
validators={{
|
||||||
|
onChange: ({ value }) =>
|
||||||
|
form.getFieldValue("tipo") === "funcao_gratificada" && !value
|
||||||
|
? "Obrigatório"
|
||||||
|
: undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#snippet children({ name, state, handleChange })}
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="valor">
|
||||||
|
<span class="label-text font-medium"
|
||||||
|
>Valor <span class="text-error">*</span></span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
{name}
|
||||||
|
value={state.value}
|
||||||
|
placeholder="Ex.: 1.500,00"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
inputmode="decimal"
|
||||||
|
autocomplete="off"
|
||||||
|
oninput={(e) => {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
const formatted = formatCurrencyBR(target.value);
|
||||||
|
target.value = formatted;
|
||||||
|
handleChange(formatted);
|
||||||
|
}}
|
||||||
|
required
|
||||||
|
aria-required="true"
|
||||||
|
/>
|
||||||
|
<div class="label">
|
||||||
|
<span class="label-text-alt opacity-60"
|
||||||
|
>Informe o valor da função gratificada.</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</form.Field>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<form.Subscribe
|
||||||
|
selector={(state) => ({
|
||||||
|
canSubmit: state.canSubmit,
|
||||||
|
isSubmitting: state.isSubmitting,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{#snippet children({ canSubmit, isSubmitting })}
|
||||||
|
<div class="card-actions justify-end pt-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-ghost"
|
||||||
|
disabled={isSubmitting}
|
||||||
|
onclick={() => goto("/recursos-humanos/simbolos")}
|
||||||
|
>
|
||||||
|
Cancelar
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary"
|
||||||
|
class:loading={isSubmitting}
|
||||||
|
disabled={isSubmitting || !canSubmit}
|
||||||
|
>
|
||||||
|
<Plus class="h-5 w-5" />
|
||||||
|
<span>Cadastrar Símbolo</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</form.Subscribe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import "../app.css";
|
import "../app.css";
|
||||||
import Header from "$lib/components/Header.svelte";
|
|
||||||
import Sidebar from "$lib/components/Sidebar.svelte";
|
import Sidebar from "$lib/components/Sidebar.svelte";
|
||||||
import { PUBLIC_CONVEX_URL } from "$env/static/public";
|
import { PUBLIC_CONVEX_URL } from "$env/static/public";
|
||||||
import { setupConvex } from "convex-svelte";
|
import { setupConvex } from "convex-svelte";
|
||||||
|
import { createSvelteAuthClient } from "@mmailaender/convex-better-auth-svelte/svelte";
|
||||||
|
import { authClient } from "$lib/auth";
|
||||||
|
|
||||||
const { children } = $props();
|
const { children } = $props();
|
||||||
setupConvex(PUBLIC_CONVEX_URL);
|
createSvelteAuthClient({ authClient });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
21
bun.lock
21
bun.lock
@@ -3,6 +3,10 @@
|
|||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sgse-app",
|
"name": "sgse-app",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/svelte-form": "^1.23.8",
|
||||||
|
"lucide-svelte": "^0.546.0",
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2.2.0",
|
"@biomejs/biome": "^2.2.0",
|
||||||
"turbo": "^2.5.4",
|
"turbo": "^2.5.4",
|
||||||
@@ -16,6 +20,7 @@
|
|||||||
"@mmailaender/convex-better-auth-svelte": "^0.2.0",
|
"@mmailaender/convex-better-auth-svelte": "^0.2.0",
|
||||||
"@sgse-app/backend": "workspace:*",
|
"@sgse-app/backend": "workspace:*",
|
||||||
"@tanstack/svelte-form": "^1.19.2",
|
"@tanstack/svelte-form": "^1.19.2",
|
||||||
|
"better-auth": "^1.3.29",
|
||||||
"convex": "catalog:",
|
"convex": "catalog:",
|
||||||
"convex-svelte": "^0.0.11",
|
"convex-svelte": "^0.0.11",
|
||||||
"zod": "^4.0.17",
|
"zod": "^4.0.17",
|
||||||
@@ -67,6 +72,8 @@
|
|||||||
"packages": {
|
"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/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-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=="],
|
"@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/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/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=="],
|
"@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=="],
|
"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=="],
|
"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=="],
|
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
||||||
@@ -487,6 +498,8 @@
|
|||||||
|
|
||||||
"zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="],
|
"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=="],
|
"@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=="],
|
"@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=="],
|
"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/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=="],
|
"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-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=="],
|
"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=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,5 +27,9 @@
|
|||||||
"turbo": "^2.5.4",
|
"turbo": "^2.5.4",
|
||||||
"@biomejs/biome": "^2.2.0"
|
"@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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
packages/backend/convex/_generated/api.d.ts
vendored
4
packages/backend/convex/_generated/api.d.ts
vendored
@@ -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__generated_server from "../betterAuth/_generated/server.js";
|
||||||
import type * as betterAuth_adapter from "../betterAuth/adapter.js";
|
import type * as betterAuth_adapter from "../betterAuth/adapter.js";
|
||||||
import type * as betterAuth_auth from "../betterAuth/auth.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 healthCheck from "../healthCheck.js";
|
||||||
import type * as http from "../http.js";
|
import type * as http from "../http.js";
|
||||||
|
import type * as simbolos from "../simbolos.js";
|
||||||
import type * as todos from "../todos.js";
|
import type * as todos from "../todos.js";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
@@ -37,8 +39,10 @@ declare const fullApi: ApiFromModules<{
|
|||||||
"betterAuth/_generated/server": typeof betterAuth__generated_server;
|
"betterAuth/_generated/server": typeof betterAuth__generated_server;
|
||||||
"betterAuth/adapter": typeof betterAuth_adapter;
|
"betterAuth/adapter": typeof betterAuth_adapter;
|
||||||
"betterAuth/auth": typeof betterAuth_auth;
|
"betterAuth/auth": typeof betterAuth_auth;
|
||||||
|
funcionarios: typeof funcionarios;
|
||||||
healthCheck: typeof healthCheck;
|
healthCheck: typeof healthCheck;
|
||||||
http: typeof http;
|
http: typeof http;
|
||||||
|
simbolos: typeof simbolos;
|
||||||
todos: typeof todos;
|
todos: typeof todos;
|
||||||
}>;
|
}>;
|
||||||
declare const fullApiWithMounts: typeof fullApi;
|
declare const fullApiWithMounts: typeof fullApi;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { defineSchema, defineTable } from "convex/server";
|
import { defineSchema, defineTable } from "convex/server";
|
||||||
import { v } from "convex/values";
|
import { Infer, v } from "convex/values";
|
||||||
import { tables } from "./betterAuth/schema";
|
import { tables } from "./betterAuth/schema";
|
||||||
|
|
||||||
|
export const simboloTipo = v.union(
|
||||||
|
v.literal("cargo_comissionado"),
|
||||||
|
v.literal("funcao_gratificada")
|
||||||
|
);
|
||||||
|
export type SimboloTipo = Infer<typeof simboloTipo>;
|
||||||
|
|
||||||
export default defineSchema({
|
export default defineSchema({
|
||||||
...tables,
|
...tables,
|
||||||
todos: defineTable({
|
todos: defineTable({
|
||||||
@@ -20,13 +26,21 @@ export default defineSchema({
|
|||||||
telefone: v.optional(v.string()),
|
telefone: v.optional(v.string()),
|
||||||
email: v.optional(v.string()),
|
email: v.optional(v.string()),
|
||||||
matricula: v.string(),
|
matricula: v.string(),
|
||||||
simbolo: v.optional(v.string()),
|
|
||||||
vencimento: v.optional(v.string()),
|
vencimento: v.optional(v.string()),
|
||||||
admissao: v.optional(v.string()),
|
admissao: v.optional(v.string()),
|
||||||
desligamento: v.optional(v.string()),
|
desligamento: v.optional(v.string()),
|
||||||
ferias: v.optional(v.string()),
|
ferias: v.optional(v.string()),
|
||||||
atestado: v.optional(v.string()),
|
simboloId: v.id("simbolos"),
|
||||||
})
|
})
|
||||||
.index("by_matricula", ["matricula"])
|
.index("by_matricula", ["matricula"])
|
||||||
.index("by_nome", ["nome"]),
|
.index("by_nome", ["nome"]),
|
||||||
|
|
||||||
|
simbolos: defineTable({
|
||||||
|
nome: v.string(),
|
||||||
|
tipo: simboloTipo,
|
||||||
|
descricao: v.string(),
|
||||||
|
vencValor: v.string(),
|
||||||
|
repValor: v.string(),
|
||||||
|
valor: v.string(),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
50
packages/backend/convex/simbolos.ts
Normal file
50
packages/backend/convex/simbolos.ts
Normal file
@@ -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);
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user