Merge pull request #18 from killer-cf/fix-page-with-lint-errors
Fix page with lint errors
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { useQuery, useConvexClient } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { toast } from 'svelte-sonner';
|
||||
@@ -499,7 +500,7 @@
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a>
|
||||
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline">Recursos Humanos</a>
|
||||
</li>
|
||||
<li>Atestados & Licenças</li>
|
||||
</ul>
|
||||
@@ -530,7 +531,7 @@
|
||||
<p class="text-base-content/70">Registro de atestados médicos e licenças</p>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn gap-2" onclick={() => goto('/recursos-humanos')}>
|
||||
<button class="btn gap-2" onclick={() => goto(resolve('/recursos-humanos'))}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { useQuery, useConvexClient } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import AprovarAusencias from '$lib/components/AprovarAusencias.svelte';
|
||||
@@ -72,7 +73,7 @@
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a>
|
||||
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline">Recursos Humanos</a>
|
||||
</li>
|
||||
<li>Gestão de Ausências</li>
|
||||
</ul>
|
||||
@@ -103,7 +104,7 @@
|
||||
<p class="text-base-content/70">Visão geral de todas as solicitações de ausências</p>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn gap-2" onclick={() => goto('/recursos-humanos')}>
|
||||
<button class="btn gap-2" onclick={() => goto(resolve('/recursos-humanos'))}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useConvexClient } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import type { SimboloTipo } from '@sgse-app/backend/convex/schema';
|
||||
import PrintModal from '$lib/components/PrintModal.svelte';
|
||||
|
||||
@@ -37,7 +38,7 @@
|
||||
}
|
||||
|
||||
function editSelected() {
|
||||
if (selectedId) goto(`/recursos-humanos/funcionarios/${selectedId}/editar`);
|
||||
if (selectedId) goto(resolve(`/recursos-humanos/funcionarios/${selectedId}/editar`));
|
||||
}
|
||||
|
||||
async function openPrintModal(funcionarioId: string) {
|
||||
@@ -53,7 +54,7 @@
|
||||
}
|
||||
|
||||
function navCadastro() {
|
||||
goto('/recursos-humanos/funcionarios/cadastro');
|
||||
goto(resolve('/recursos-humanos/funcionarios/cadastro'));
|
||||
}
|
||||
|
||||
load();
|
||||
@@ -68,7 +69,7 @@
|
||||
<!-- Breadcrumb -->
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li><a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a></li>
|
||||
<li><a href={resolve('/recursos-humanos')} class="text-primary hover:underline">Recursos Humanos</a></li>
|
||||
<li>Funcionários</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { api } from "@sgse-app/backend/convex/_generated/api";
|
||||
import { page } from "$app/stores";
|
||||
import { goto } from "$app/navigation";
|
||||
import { resolve } from "$app/paths";
|
||||
import { maskCPF, maskCEP, maskPhone } from "$lib/utils/masks";
|
||||
import { documentos, getDocumentoDefinicao } from "$lib/utils/documentos";
|
||||
import {
|
||||
@@ -34,7 +35,7 @@
|
||||
});
|
||||
|
||||
if (!data) {
|
||||
goto("/recursos-humanos/funcionarios");
|
||||
goto(resolve("/recursos-humanos/funcionarios"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,7 +56,7 @@
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Erro ao carregar funcionário:", err);
|
||||
goto("/recursos-humanos/funcionarios");
|
||||
goto(resolve("/recursos-humanos/funcionarios"));
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
@@ -93,13 +94,13 @@
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/recursos-humanos" class="text-primary hover:underline"
|
||||
<a href={resolve("/recursos-humanos")} class="text-primary hover:underline"
|
||||
>Recursos Humanos</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="/recursos-humanos/funcionarios"
|
||||
href={resolve("/recursos-humanos/funcionarios")}
|
||||
class="text-primary hover:underline">Funcionários</a
|
||||
>
|
||||
</li>
|
||||
@@ -141,7 +142,7 @@
|
||||
<button
|
||||
class="btn btn-primary gap-2"
|
||||
onclick={() =>
|
||||
goto(`/recursos-humanos/funcionarios/${funcionarioId}/editar`)}
|
||||
goto(resolve(`/recursos-humanos/funcionarios/${funcionarioId}/editar`))}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -163,7 +164,7 @@
|
||||
class="btn btn-secondary gap-2"
|
||||
onclick={() =>
|
||||
goto(
|
||||
`/recursos-humanos/funcionarios/${funcionarioId}/documentos`,
|
||||
resolve(`/recursos-humanos/funcionarios/${funcionarioId}/documentos`),
|
||||
)}
|
||||
>
|
||||
<svg
|
||||
@@ -304,7 +305,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
href="/recursos-humanos/ferias"
|
||||
href={resolve("/recursos-humanos/ferias")}
|
||||
class="btn btn-primary btn-sm gap-2"
|
||||
>
|
||||
<svg
|
||||
@@ -857,7 +858,7 @@
|
||||
class="btn btn-primary btn-sm gap-2"
|
||||
onclick={() =>
|
||||
goto(
|
||||
`/recursos-humanos/funcionarios/${funcionarioId}/documentos`,
|
||||
resolve(`/recursos-humanos/funcionarios/${funcionarioId}/documentos`),
|
||||
)}
|
||||
>
|
||||
<svg
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import FileUpload from '$lib/components/FileUpload.svelte';
|
||||
import ModelosDeclaracoes from '$lib/components/ModelosDeclaracoes.svelte';
|
||||
import {
|
||||
@@ -10,15 +11,16 @@
|
||||
categoriasDocumentos,
|
||||
getDocumentosByCategoria
|
||||
} from '$lib/utils/documentos';
|
||||
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
|
||||
const client = useConvexClient();
|
||||
|
||||
let funcionarioId = $derived($page.params.funcionarioId as string);
|
||||
let funcionarioId = $derived($page.params.funcionarioId as Id<'funcionarios'>);
|
||||
|
||||
let funcionario = $state<any>(null);
|
||||
let funcionario = $state<Doc<'funcionarios'> | null>(null);
|
||||
let documentosStorage = $state<Record<string, string | undefined>>({});
|
||||
let loading = $state(true);
|
||||
let filtro = $state<string>('todos'); // todos, enviados, pendentes
|
||||
let filtro = $state<'todos' | 'enviados' | 'pendentes'>('todos'); // todos, enviados, pendentes
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
@@ -26,11 +28,11 @@
|
||||
|
||||
// Carregar dados do funcionário
|
||||
const data = await client.query(api.funcionarios.getById, {
|
||||
id: funcionarioId as any
|
||||
id: funcionarioId
|
||||
});
|
||||
|
||||
if (!data) {
|
||||
goto('/recursos-humanos/funcionarios');
|
||||
goto(resolve('/recursos-humanos/funcionarios'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,13 +40,15 @@
|
||||
|
||||
// Mapear storage IDs dos documentos
|
||||
documentos.forEach((doc) => {
|
||||
if ((data as any)[doc.campo]) {
|
||||
documentosStorage[doc.campo] = (data as any)[doc.campo];
|
||||
const campo = doc.campo as keyof Doc<'funcionarios'>;
|
||||
const valor = data[campo];
|
||||
if (typeof valor === 'string') {
|
||||
documentosStorage[doc.campo] = valor;
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Erro ao carregar:', err);
|
||||
goto('/recursos-humanos/funcionarios');
|
||||
goto(resolve('/recursos-humanos/funcionarios'));
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
@@ -62,13 +66,23 @@
|
||||
body: file
|
||||
});
|
||||
|
||||
const { storageId } = await result.json();
|
||||
const uploadResponse = await result.json();
|
||||
if (
|
||||
!uploadResponse ||
|
||||
typeof uploadResponse !== 'object' ||
|
||||
!('storageId' in uploadResponse) ||
|
||||
typeof uploadResponse.storageId !== 'string'
|
||||
) {
|
||||
throw new Error('Resposta inválida ao fazer upload');
|
||||
}
|
||||
|
||||
const storageId = uploadResponse.storageId;
|
||||
|
||||
// Atualizar documento no funcionário
|
||||
await client.mutation(api.documentos.updateDocumento, {
|
||||
funcionarioId: funcionarioId as any,
|
||||
funcionarioId,
|
||||
campo,
|
||||
storageId: storageId as any
|
||||
storageId: storageId as Id<'_storage'>
|
||||
});
|
||||
|
||||
// Atualizar localmente
|
||||
@@ -76,8 +90,11 @@
|
||||
|
||||
// Recarregar
|
||||
await load();
|
||||
} catch (err: any) {
|
||||
throw new Error(err?.message || 'Erro ao fazer upload');
|
||||
} catch (err) {
|
||||
if (err instanceof Error && err.message) {
|
||||
throw err;
|
||||
}
|
||||
throw new Error('Erro ao fazer upload');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +102,7 @@
|
||||
try {
|
||||
// Atualizar documento no funcionário (set to null)
|
||||
await client.mutation(api.documentos.updateDocumento, {
|
||||
funcionarioId: funcionarioId as any,
|
||||
funcionarioId,
|
||||
campo,
|
||||
storageId: null
|
||||
});
|
||||
@@ -95,8 +112,10 @@
|
||||
|
||||
// Recarregar
|
||||
await load();
|
||||
} catch (err: any) {
|
||||
alert('Erro ao remover documento: ' + (err?.message || ''));
|
||||
} catch (err) {
|
||||
const mensagem =
|
||||
err instanceof Error && err.message ? err.message : 'Erro ao remover documento';
|
||||
alert('Erro ao remover documento: ' + mensagem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,16 +148,18 @@
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a>
|
||||
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline"
|
||||
>Recursos Humanos</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/recursos-humanos/funcionarios" class="text-primary hover:underline"
|
||||
<a href={resolve('/recursos-humanos/funcionarios')} class="text-primary hover:underline"
|
||||
>Funcionários</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href={`/recursos-humanos/funcionarios/${funcionarioId}`}
|
||||
href={resolve(`/recursos-humanos/funcionarios/${funcionarioId}`)}
|
||||
class="text-primary hover:underline">{funcionario.nome}</a
|
||||
>
|
||||
</li>
|
||||
@@ -176,7 +197,7 @@
|
||||
|
||||
<button
|
||||
class="btn gap-2"
|
||||
onclick={() => goto(`/recursos-humanos/funcionarios/${funcionarioId}`)}
|
||||
onclick={() => goto(resolve(`/recursos-humanos/funcionarios/${funcionarioId}`))}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -304,7 +325,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Documentos por Categoria -->
|
||||
{#each categoriasDocumentos as categoria}
|
||||
{#each categoriasDocumentos as categoria (categoria)}
|
||||
{@const docsCategoria = getDocumentosByCategoria(categoria).filter((doc) => {
|
||||
const temDocumento = !!documentosStorage[doc.campo];
|
||||
if (filtro === 'enviados') return temDocumento;
|
||||
@@ -321,7 +342,7 @@
|
||||
</h2>
|
||||
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{#each docsCategoria as doc}
|
||||
{#each docsCategoria as doc (doc.campo)}
|
||||
<FileUpload
|
||||
label={doc.nome}
|
||||
helpUrl={doc.helpUrl}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useConvexClient } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import type { SimboloTipo } from '@sgse-app/backend/convex/schema';
|
||||
import FileUpload from '$lib/components/FileUpload.svelte';
|
||||
@@ -446,7 +447,7 @@
|
||||
}
|
||||
|
||||
notice = { kind: 'success', text: 'Funcionário atualizado com sucesso!' };
|
||||
setTimeout(() => goto('/recursos-humanos/funcionarios'), 600);
|
||||
setTimeout(() => goto(resolve('/recursos-humanos/funcionarios')), 600);
|
||||
} catch (e: any) {
|
||||
notice = { kind: 'error', text: 'Erro ao atualizar funcionário.' };
|
||||
} finally {
|
||||
@@ -482,10 +483,12 @@
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a>
|
||||
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline"
|
||||
>Recursos Humanos</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/recursos-humanos/funcionarios" class="text-primary hover:underline"
|
||||
<a href={resolve('/recursos-humanos/funcionarios')} class="text-primary hover:underline"
|
||||
>Funcionários</a
|
||||
>
|
||||
</li>
|
||||
@@ -1710,7 +1713,7 @@
|
||||
type="button"
|
||||
class="btn btn-lg"
|
||||
disabled={loading}
|
||||
onclick={() => goto('/recursos-humanos/funcionarios')}
|
||||
onclick={() => goto(resolve('/recursos-humanos/funcionarios'))}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useConvexClient } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const client = useConvexClient();
|
||||
@@ -55,7 +56,7 @@
|
||||
}
|
||||
|
||||
function back() {
|
||||
goto('/recursos-humanos/funcionarios');
|
||||
goto(resolve('/recursos-humanos/funcionarios'));
|
||||
}
|
||||
|
||||
// Computed para lista filtrada
|
||||
@@ -80,7 +81,7 @@
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/" class="text-primary hover:text-primary-focus">
|
||||
<a href={resolve('/')} class="text-primary hover:text-primary-focus">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4"
|
||||
@@ -99,10 +100,10 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/recursos-humanos" class="text-primary hover:text-primary-focus">Recursos Humanos</a>
|
||||
<a href={resolve('/recursos-humanos')} class="text-primary hover:text-primary-focus">Recursos Humanos</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/recursos-humanos/funcionarios" class="text-primary hover:text-primary-focus"
|
||||
<a href={resolve('/recursos-humanos/funcionarios')} class="text-primary hover:text-primary-focus"
|
||||
>Funcionários</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useConvexClient } from "convex-svelte";
|
||||
import { api } from "@sgse-app/backend/convex/_generated/api";
|
||||
import { onMount } from "svelte";
|
||||
import { resolve } from "$app/paths";
|
||||
|
||||
const client = useConvexClient();
|
||||
|
||||
@@ -38,16 +39,16 @@
|
||||
containerWidth = Math.min(container.clientWidth - 32, 1200);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
updateSize();
|
||||
window.addEventListener('resize', updateSize);
|
||||
|
||||
|
||||
return () => window.removeEventListener('resize', updateSize);
|
||||
});
|
||||
|
||||
const chartHeight = 350;
|
||||
const padding = { top: 20, right: 20, bottom: 80, left: 70 };
|
||||
|
||||
|
||||
let chartWidth = $derived(containerWidth);
|
||||
|
||||
function getMax<T>(arr: Array<T>, sel: (t: T) => number): number {
|
||||
@@ -55,13 +56,13 @@
|
||||
for (const a of arr) m = Math.max(m, sel(a));
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
function scaleY(v: number, max: number): number {
|
||||
if (max <= 0) return 0;
|
||||
const innerH = chartHeight - padding.top - padding.bottom;
|
||||
return (v / max) * innerH;
|
||||
}
|
||||
|
||||
|
||||
function getX(i: number, n: number): number {
|
||||
const innerW = chartWidth - padding.left - padding.right;
|
||||
return padding.left + (innerW / (n - 1)) * i;
|
||||
@@ -71,13 +72,13 @@
|
||||
if (data.length === 0) return "";
|
||||
const n = data.length;
|
||||
let path = `M ${getX(0, n)} ${chartHeight - padding.bottom}`;
|
||||
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
const x = getX(i, n);
|
||||
const y = chartHeight - padding.bottom - scaleY(getValue(data[i]), max);
|
||||
path += ` L ${x} ${y}`;
|
||||
}
|
||||
|
||||
|
||||
path += ` L ${getX(n - 1, n)} ${chartHeight - padding.bottom}`;
|
||||
path += " Z";
|
||||
return path;
|
||||
@@ -88,9 +89,9 @@
|
||||
<!-- Breadcrumb -->
|
||||
<div class="text-sm breadcrumbs mb-4">
|
||||
<ul>
|
||||
<li><a href="/" class="hover:text-primary">Dashboard</a></li>
|
||||
<li><a href="/recursos-humanos" class="hover:text-primary">Recursos Humanos</a></li>
|
||||
<li><a href="/recursos-humanos/funcionarios" class="hover:text-primary">Funcionários</a></li>
|
||||
<li><a href={resolve('/')} class="hover:text-primary">Dashboard</a></li>
|
||||
<li><a href={resolve('/recursos-humanos')} class="hover:text-primary">Recursos Humanos</a></li>
|
||||
<li><a href={resolve('/recursos-humanos/funcionarios')} class="hover:text-primary">Funcionários</a></li>
|
||||
<li class="font-semibold text-primary">Relatórios</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -143,7 +144,7 @@
|
||||
<text x="16" y="32" class="opacity-60">Sem dados</text>
|
||||
{:else}
|
||||
{@const max = getMax(rows, (r) => r.valor)}
|
||||
|
||||
|
||||
<!-- Grid lines -->
|
||||
{#each [0,1,2,3,4,5] as t}
|
||||
{@const val = Math.round((max/5) * t)}
|
||||
@@ -151,18 +152,18 @@
|
||||
<line x1={padding.left} y1={y} x2={chartWidth - padding.right} y2={y} stroke="currentColor" stroke-opacity="0.1" stroke-dasharray="4,4" />
|
||||
<text x={padding.left - 8} y={y + 4} text-anchor="end" class="text-[10px] opacity-70">{`R$ ${val.toLocaleString('pt-BR')}`}</text>
|
||||
{/each}
|
||||
|
||||
|
||||
<!-- Eixos -->
|
||||
<line x1={padding.left} y1={chartHeight - padding.bottom} x2={chartWidth - padding.right} y2={chartHeight - padding.bottom} stroke="currentColor" stroke-opacity="0.3" stroke-width="2" />
|
||||
<line x1={padding.left} y1={padding.top} x2={padding.left} y2={chartHeight - padding.bottom} stroke="currentColor" stroke-opacity="0.3" stroke-width="2" />
|
||||
|
||||
|
||||
<!-- Area fill (camada) -->
|
||||
<path
|
||||
d={createAreaPath(rows, (r) => r.valor, max)}
|
||||
fill="url(#gradient-salary)"
|
||||
<path
|
||||
d={createAreaPath(rows, (r) => r.valor, max)}
|
||||
fill="url(#gradient-salary)"
|
||||
opacity="0.7"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points={rows.map((r, i) => {
|
||||
@@ -174,7 +175,7 @@
|
||||
stroke="rgb(59, 130, 246)"
|
||||
stroke-width="3"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Data points -->
|
||||
{#each rows as r, i}
|
||||
{@const x = getX(i, rows.length)}
|
||||
@@ -184,7 +185,7 @@
|
||||
{`R$ ${r.valor.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}`}
|
||||
</text>
|
||||
{/each}
|
||||
|
||||
|
||||
<!-- Eixo X labels -->
|
||||
{#each rows as r, i}
|
||||
{@const x = getX(i, rows.length)}
|
||||
@@ -196,7 +197,7 @@
|
||||
</div>
|
||||
</foreignObject>
|
||||
{/each}
|
||||
|
||||
|
||||
<!-- Gradient definition -->
|
||||
<defs>
|
||||
<linearGradient id="gradient-salary" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
@@ -230,7 +231,7 @@
|
||||
<text x="16" y="32" class="opacity-60">Sem dados</text>
|
||||
{:else}
|
||||
{@const maxC = getMax(rows, (r) => r.count)}
|
||||
|
||||
|
||||
<!-- Grid lines -->
|
||||
{#each [0,1,2,3,4,5] as t}
|
||||
{@const val = Math.round((maxC/5) * t)}
|
||||
@@ -238,18 +239,18 @@
|
||||
<line x1={padding.left} y1={y} x2={chartWidth - padding.right} y2={y} stroke="currentColor" stroke-opacity="0.1" stroke-dasharray="4,4" />
|
||||
<text x={padding.left - 6} y={y + 4} text-anchor="end" class="text-[10px] opacity-70">{val}</text>
|
||||
{/each}
|
||||
|
||||
|
||||
<!-- Eixos -->
|
||||
<line x1={padding.left} y1={chartHeight - padding.bottom} x2={chartWidth - padding.right} y2={chartHeight - padding.bottom} stroke="currentColor" stroke-opacity="0.3" stroke-width="2" />
|
||||
<line x1={padding.left} y1={padding.top} x2={padding.left} y2={chartHeight - padding.bottom} stroke="currentColor" stroke-opacity="0.3" stroke-width="2" />
|
||||
|
||||
|
||||
<!-- Area fill (camada) -->
|
||||
<path
|
||||
d={createAreaPath(rows, (r) => r.count, Math.max(1, maxC))}
|
||||
fill="url(#gradient-count)"
|
||||
<path
|
||||
d={createAreaPath(rows, (r) => r.count, Math.max(1, maxC))}
|
||||
fill="url(#gradient-count)"
|
||||
opacity="0.7"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Line -->
|
||||
<polyline
|
||||
points={rows.map((r, i) => {
|
||||
@@ -261,7 +262,7 @@
|
||||
stroke="rgb(236, 72, 153)"
|
||||
stroke-width="3"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Data points -->
|
||||
{#each rows as r, i}
|
||||
{@const x = getX(i, rows.length)}
|
||||
@@ -271,7 +272,7 @@
|
||||
{r.count}
|
||||
</text>
|
||||
{/each}
|
||||
|
||||
|
||||
<!-- Eixo X labels -->
|
||||
{#each rows as r, i}
|
||||
{@const x = getX(i, rows.length)}
|
||||
@@ -283,7 +284,7 @@
|
||||
</div>
|
||||
</foreignObject>
|
||||
{/each}
|
||||
|
||||
|
||||
<!-- Gradient definition -->
|
||||
<defs>
|
||||
<linearGradient id="gradient-count" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import { onMount } from 'svelte';
|
||||
import { resolve } from '$app/paths';
|
||||
|
||||
const client = useConvexClient();
|
||||
let isLoading = true;
|
||||
@@ -77,7 +78,7 @@
|
||||
<!-- Breadcrumb -->
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li><a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a></li>
|
||||
<li><a href={resolve('/recursos-humanos')} class="text-primary hover:underline">Recursos Humanos</a></li>
|
||||
<li>Símbolos</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -107,7 +108,7 @@
|
||||
<p class="text-base-content/70">Gerencie cargos comissionados e funções gratificadas</p>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/recursos-humanos/simbolos/cadastro" class="btn btn-primary btn-lg gap-2">
|
||||
<a href={resolve('/recursos-humanos/simbolos/cadastro')} class="btn btn-primary btn-lg gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
@@ -315,7 +316,7 @@
|
||||
class="dropdown-content menu bg-base-100 rounded-box border-base-300 z-10 w-52 border p-2 shadow-lg"
|
||||
>
|
||||
<li>
|
||||
<a href={'/recursos-humanos/simbolos/' + simbolo._id + '/editar'}>
|
||||
<a href={resolve(`/recursos-humanos/simbolos/${simbolo._id}/editar`)}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { useQuery, useConvexClient } from 'convex-svelte';
|
||||
import { resolve } from '$app/paths';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { createForm } from '@tanstack/svelte-form';
|
||||
import z from 'zod';
|
||||
@@ -80,7 +81,7 @@
|
||||
try {
|
||||
await client.mutation(api.simbolos.update, payload);
|
||||
notice = { kind: 'success', text: 'Símbolo atualizado com sucesso.' };
|
||||
setTimeout(() => goto('/recursos-humanos/simbolos'), 600);
|
||||
setTimeout(() => goto(resolve('/recursos-humanos/simbolos')), 600);
|
||||
} catch (error) {
|
||||
console.error('erro ao atualizar símbolo', error);
|
||||
notice = { kind: 'error', text: 'Erro ao atualizar símbolo.' };
|
||||
@@ -393,7 +394,7 @@
|
||||
type="button"
|
||||
class="btn"
|
||||
disabled={isSubmitting}
|
||||
onclick={() => goto('/recursos-humanos/simbolos')}
|
||||
onclick={() => goto(resolve('/recursos-humanos/simbolos'))}
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import z from 'zod';
|
||||
import { goto } from '$app/navigation';
|
||||
import type { SimboloTipo } from '@sgse-app/backend/convex/schema';
|
||||
import { resolve } from '$app/paths';
|
||||
|
||||
const client = useConvexClient();
|
||||
|
||||
@@ -83,7 +84,7 @@
|
||||
if (res) {
|
||||
formApi.reset();
|
||||
notice = { kind: 'success', text: 'Símbolo cadastrado com sucesso!' };
|
||||
setTimeout(() => goto('/recursos-humanos/simbolos'), 1500);
|
||||
setTimeout(() => goto(resolve('/recursos-humanos/simbolos')), 1500);
|
||||
}
|
||||
} catch (error: any) {
|
||||
notice = { kind: 'error', text: error.message || 'Erro ao cadastrar símbolo.' };
|
||||
@@ -97,9 +98,9 @@
|
||||
<!-- Breadcrumb -->
|
||||
<div class="breadcrumbs mb-4 text-sm">
|
||||
<ul>
|
||||
<li><a href="/recursos-humanos" class="text-primary hover:underline">Recursos Humanos</a></li>
|
||||
<li><a href={resolve('/recursos-humanos')} class="text-primary hover:underline">Recursos Humanos</a></li>
|
||||
<li>
|
||||
<a href="/recursos-humanos/simbolos" class="text-primary hover:underline">Símbolos</a>
|
||||
<a href={resolve('/recursos-humanos/simbolos')} class="text-primary hover:underline">Símbolos</a>
|
||||
</li>
|
||||
<li>Cadastrar</li>
|
||||
</ul>
|
||||
@@ -469,7 +470,7 @@
|
||||
type="button"
|
||||
class="btn btn-lg"
|
||||
disabled={isSubmitting}
|
||||
onclick={() => goto('/recursos-humanos/simbolos')}
|
||||
onclick={() => goto(resolve('/recursos-humanos/simbolos'))}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
Reference in New Issue
Block a user