Use resolve() for all internal hrefs and goto paths to ensure correct

routing
This commit is contained in:
2025-11-12 23:18:41 -03:00
parent a2451baafc
commit bd574aedc0
32 changed files with 168 additions and 136 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 {
@@ -30,7 +31,7 @@
});
if (!data) {
goto('/recursos-humanos/funcionarios');
goto(resolve('/recursos-humanos/funcionarios'));
return;
}
@@ -44,7 +45,7 @@
});
} catch (err) {
console.error('Erro ao carregar:', err);
goto('/recursos-humanos/funcionarios');
goto(resolve('/recursos-humanos/funcionarios'));
} finally {
loading = false;
}
@@ -129,16 +130,16 @@
<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 +177,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"

View File

@@ -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,10 @@
<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 +1711,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"

View File

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

View File

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

View File

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

View File

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

View File

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