Correcao ferias #17

Merged
deyvisonwanderley merged 4 commits from correcao-ferias into master 2025-11-13 11:51:35 +00:00
7 changed files with 1219 additions and 888 deletions
Showing only changes of commit 0b7f1ad621 - Show all commits

View File

@@ -44,7 +44,7 @@
"@types/papaparse": "^5.3.14",
"better-auth": "catalog:",
"convex": "catalog:",
"convex-svelte": "^0.0.11",
"convex-svelte": "^0.0.12",
"date-fns": "^4.1.0",
"emoji-picker-element": "^1.27.0",
"is-network-error": "^1.3.0",

View File

@@ -7,8 +7,6 @@
import { api } from '@sgse-app/backend/convex/_generated/api';
import type { FunctionReturnType } from 'convex/server';
import type { Id } from '@sgse-app/backend/convex/_generated/dataModel';
import '@fullcalendar/core/index.css';
import '@fullcalendar/daygrid/index.css';
type CalendarConstructor = typeof import('@fullcalendar/core').Calendar;
type CalendarInstance = import('@fullcalendar/core').Calendar;
type EventInput = import('@fullcalendar/core').EventInput;
@@ -37,6 +35,46 @@
// Buscar TODAS as solicitações de férias (Dashboard RH)
const todasSolicitacoesQuery = useQuery(api.ferias.listarTodas, {});
// Estados de loading e error
const isLoading = $derived(todasSolicitacoesQuery?.isLoading ?? true);
// Verificar erro de forma segura
const queryResult = $derived(todasSolicitacoesQuery);
const hasError = $derived(
queryResult !== undefined &&
queryResult !== null &&
typeof queryResult === 'object' &&
'error' in queryResult &&
(queryResult as { error?: unknown }).error !== undefined
);
const errorMessage = $derived(() => {
if (!hasError) return 'Erro desconhecido ao carregar dados';
const queryWithError = queryResult as { error?: unknown } | undefined;
if (!queryWithError?.error) return 'Erro desconhecido ao carregar dados';
if (queryWithError.error instanceof Error) {
return queryWithError.error.message;
}
if (typeof queryWithError.error === 'string') {
return queryWithError.error;
}
return 'Erro desconhecido ao carregar dados';
});
// Manter último valor válido para evitar dados desaparecendo
let ultimasSolicitacoesValidas = $state<TodasSolicitacoes>([]);
// Atualizar apenas quando temos dados válidos
$effect(() => {
if (todasSolicitacoesQuery?.data && !hasError) {
ultimasSolicitacoesValidas = todasSolicitacoesQuery.data;
}
});
// Usar último valor válido ou array vazio
const solicitacoes = $derived<TodasSolicitacoes>(
todasSolicitacoesQuery?.data ?? ultimasSolicitacoesValidas
);
let filtroStatus = $state<string>('todos');
let filtroNome = $state<string>('');
let filtroMatricula = $state<string>('');
@@ -46,7 +84,6 @@
let filtroPeriodoFim = $state<string>('');
let dataInicioRelatorio = $state<string>('');
let dataFimRelatorio = $state<string>('');
const solicitacoes = $derived<TodasSolicitacoes>(todasSolicitacoesQuery?.data ?? []);
// Filtrar solicitações
const solicitacoesFiltradas = $derived(
@@ -304,11 +341,26 @@
let calendarioContainer: HTMLDivElement | null = null;
let calendarioInstance: CalendarInstance | null = null;
let CalendarClass: CalendarConstructor | null = null;
let calendarioInicializado = $state(false);
onMount(() => {
let destroyed = false;
// Inicializar calendário quando o container estiver disponível
$effect(() => {
// Verificar se o container está disponível e o calendário ainda não foi inicializado
const container = calendarioContainer;
const inicializarCalendario = async () => {
if (!container || calendarioInicializado || calendarioInstance) {
return;
}
// Usar setTimeout para garantir que o elemento está completamente no DOM
let timeoutId: ReturnType<typeof setTimeout> | null = null;
timeoutId = setTimeout(async () => {
if (!calendarioContainer || calendarioInstance || calendarioInicializado) {
return;
}
try {
const [coreModule, dayGridModule, interactionModule, localeModule] = await Promise.all([
import('@fullcalendar/core'),
import('@fullcalendar/daygrid'),
@@ -316,7 +368,8 @@
import('@fullcalendar/core/locales/pt-br')
]);
if (destroyed || !calendarioContainer) {
// Verificar novamente após os imports
if (!calendarioContainer || calendarioInstance || calendarioInicializado) {
return;
}
@@ -347,26 +400,73 @@
});
calendarioInstance.render();
};
void inicializarCalendario();
calendarioInicializado = true;
} catch (error) {
console.error('Erro ao inicializar calendário:', error);
}
}, 300);
// Cleanup
return () => {
destroyed = true;
calendarioInstance?.destroy();
if (timeoutId) {
clearTimeout(timeoutId);
}
if (calendarioInstance && !calendarioContainer) {
try {
calendarioInstance.destroy();
} catch (error) {
console.error('Erro ao destruir calendário:', error);
}
calendarioInstance = null;
calendarioInicializado = false;
}
};
});
// Cleanup ao desmontar o componente
onMount(() => {
return () => {
if (calendarioInstance) {
try {
calendarioInstance.destroy();
} catch (error) {
console.error('Erro ao destruir calendário:', error);
}
calendarioInstance = null;
calendarioInicializado = false;
}
};
});
// Sincronizar eventos do calendário quando mudarem
$effect(() => {
if (!calendarioInstance) {
// Não atualizar se o calendário não estiver inicializado
if (!calendarioInstance || !calendarioInicializado) {
return;
}
try {
// Remover todos os eventos existentes
calendarioInstance.removeAllEvents();
for (const evento of eventosFerias) {
// Adicionar novos eventos
const eventosClonados = eventosFerias.map((evento) => ({
...evento,
extendedProps: { ...evento.extendedProps }
}));
// Adicionar eventos em lote
for (const evento of eventosClonados) {
calendarioInstance.addEvent(evento);
}
} catch (error) {
// Log do erro, mas não interromper o fluxo
if (error instanceof Error) {
console.error('Erro ao atualizar eventos do calendário:', error.message);
} else {
console.error('Erro ao atualizar eventos do calendário:', error);
}
}
});
if (typeof window !== 'undefined') {
@@ -844,8 +944,41 @@
</button>
</div>
</div>
<!-- Mensagem de erro -->
{#if hasError}
<div class="alert alert-error mb-6 shadow-lg">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 shrink-0 stroke-current"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<div>
<h3 class="font-bold">Erro ao carregar dados</h3>
<div class="text-sm">{errorMessage}</div>
</div>
</div>
{/if}
<!-- Estatísticas -->
<div class="mb-6 grid grid-cols-1 gap-4 md:grid-cols-4">
{#if isLoading && !hasError}
{#each Array.from({ length: 4 }, (_, i) => i) as index (index)}
<div class="stat bg-base-100 rounded-box border-base-300 border shadow-lg">
<div class="skeleton mb-2 h-8 w-8 rounded-full"></div>
<div class="skeleton mb-2 h-4 w-20"></div>
<div class="skeleton mb-2 h-8 w-16"></div>
<div class="skeleton h-4 w-24"></div>
</div>
{/each}
{:else}
<div class="stat bg-base-100 rounded-box border-base-300 border shadow-lg">
<div class="stat-figure text-primary">
@@ -933,9 +1066,24 @@
<div class="stat-title">Reprovadas</div>
<div class="stat-value text-error">{stats.reprovadas}</div>
<div class="stat-desc">Indeferidas</div>
</div>
{/if}
</div>
<!-- Filtros -->
{#if isLoading && !hasError}
<div class="card border-base-300/60 bg-base-100 mb-6 border shadow-xl">
<div class="card-body space-y-6">
<div class="skeleton h-6 w-32"></div>
<div class="grid grid-cols-12 gap-5">
{#each Array.from({ length: 6 }, (_, i) => i) as index (index)}
<div class="col-span-12 md:col-span-6 xl:col-span-4">
<div class="skeleton h-32 rounded-2xl"></div>
</div>
{/each}
</div>
</div>
</div>
{:else}
<div class="card border-base-300/60 bg-base-100 mb-6 border shadow-xl">
<div class="card-body space-y-6">
@@ -1166,8 +1314,10 @@
</div>
</div>
</div>
</div>
{/if}
<!-- Impressão da Programação -->
{#if !isLoading || !hasError}
<div class="card border-accent/30 bg-base-100 mb-6 border shadow-xl">
<div class="card-body space-y-4 p-6">
@@ -1245,13 +1395,26 @@
</button>
</div>
</div>
<p class="text-base-content/60 text-xs">
O relatório será aberto em uma nova aba com formatação própria para impressão. Verifique se
<p class="text-base-content/60 text-xs">
O relatório será aberto em uma nova aba com formatação própria para impressão. Verifique
se o bloqueador de pop-ups está desabilitado para o domínio.
</p>
</div>
</div>
{/if}
<!-- Lista de Solicitações -->
{#if isLoading && !hasError}
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
<div class="skeleton mb-4 h-6 w-48"></div>
<div class="space-y-4">
{#each Array.from({ length: 5 }, (_, i) => i) as index (index)}
<div class="skeleton h-16 w-full"></div>
{/each}
</div>
</div>
</div>
{:else}
<div class="card bg-base-100 shadow-lg">
<div class="card-body">
@@ -1311,7 +1474,10 @@
</div>
</td>
<td>
{#if solicitacao.time}
{#if solicitacao.time}
<div
class="badge badge-outline"
style="border-color: {solicitacao.time.cor}"
>
{solicitacao.time.nome}
</div>
@@ -1337,7 +1503,21 @@
</div>
{/if}
</div>
</div>
{/if}
<!-- Visualizações e Relatórios -->
{#if isLoading && !hasError}
<div class="mb-6 space-y-6" bind:this={chartContainer}>
{#each Array.from({ length: 3 }, (_, i) => i) as index (index)}
<div class="card bg-base-100 border-primary/20 border shadow-lg">
<div class="card-body space-y-4 p-6">
<div class="skeleton mb-4 h-6 w-64"></div>
<div class="skeleton h-64 w-full"></div>
</div>
</div>
{/each}
</div>
{:else}
<div class="mb-6 space-y-6" bind:this={chartContainer}>
<!-- Gráfico 1 -->
@@ -1432,7 +1612,6 @@
.map((item, index) => {
const x = getX(index, periodosPorMesAtivos.length);
const y = chartHeight - padding.bottom - scaleY(item.totalDias, maxDias);
return `${x},${y}`;
return `${x},${y}`;
})
.join(' ')}
@@ -1716,15 +1895,159 @@
Visualize os períodos aprovados diretamente no calendário interativo
</p>
</div>
</div>
<div class="bg-base-200/40 w-full overflow-hidden rounded-xl p-4">
</div>
<div class="bg-base-200/40 relative w-full overflow-hidden rounded-xl p-4">
<div
class="calendario-ferias overflow-hidden rounded-xl shadow-2xl"
bind:this={calendarioContainer}
></div>
</div>
</div>
</div>
</div>
{/if}
</main>
<footer
class="border-base-300/60 bg-base-100 text-base-content/70 mt-8 border-t py-6 text-center text-sm"
>
SGSE - Sistema de Gerenciamento da Secretaria de Esportes.
</footer>
<style>
/* Calendário de Férias */
.calendario-ferias {
font-family:
'Inter',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
sans-serif;
}
/* Toolbar moderna com cores azuis/primary */
:global(.calendario-ferias .fc .fc-toolbar) {
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
padding: 1rem;
border-radius: 1rem 1rem 0 0;
color: white !important;
}
:global(.calendario-ferias .fc .fc-toolbar-title) {
color: white !important;
font-weight: 700;
font-size: 1.5rem;
}
:global(.calendario-ferias .fc .fc-button) {
background: rgba(255, 255, 255, 0.2) !important;
border: 1px solid rgba(255, 255, 255, 0.3) !important;
color: white !important;
font-weight: 600;
text-transform: capitalize;
transition: all 0.3s ease;
}
:global(.calendario-ferias .fc .fc-button:hover) {
background: rgba(255, 255, 255, 0.3) !important;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
:global(.calendario-ferias .fc .fc-button-active) {
background: rgba(255, 255, 255, 0.4) !important;
}
/* Cabeçalho dos dias */
:global(.calendario-ferias .fc .fc-col-header-cell) {
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
font-weight: 600;
text-transform: uppercase;
font-size: 0.75rem;
letter-spacing: 0.05em;
padding: 0.75rem 0.5rem;
color: #495057;
}
/* Células dos dias */
:global(.calendario-ferias .fc .fc-daygrid-day) {
transition: all 0.2s ease;
}
:global(.calendario-ferias .fc .fc-daygrid-day:hover) {
background: rgba(37, 99, 235, 0.05);
}
:global(.calendario-ferias .fc .fc-daygrid-day-number) {
padding: 0.5rem;
font-weight: 600;
color: #495057;
}
/* Fim de semana */
:global(.calendario-ferias .fc .fc-day-weekend) {
background: rgba(59, 130, 246, 0.05);
}
/* Hoje */
:global(.calendario-ferias .fc .fc-day-today) {
border: 2px solid #2563eb !important;
}
/* Eventos (férias) */
:global(.calendario-ferias .fc .fc-event) {
border-radius: 0.5rem;
padding: 0.25rem 0.5rem;
font-weight: 600;
font-size: 0.875rem;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transition: all 0.3s ease;
cursor: pointer;
}
:global(.calendario-ferias .fc .fc-event:hover) {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}
/* Seleção (arrastar) */
:global(.calendario-ferias .fc .fc-highlight) {
background: rgba(37, 99, 235, 0.3) !important;
border: 2px dashed #2563eb;
}
/* Datas desabilitadas (passado) */
:global(.calendario-ferias .fc .fc-day-past .fc-daygrid-day-number) {
opacity: 0.4;
}
/* Remover bordas padrão */
:global(.calendario-ferias .fc .fc-scrollgrid) {
border: none !important;
}
:global(.calendario-ferias .fc .fc-scrollgrid-section > td) {
border: none !important;
}
/* Grid moderno */
:global(.calendario-ferias .fc .fc-daygrid-day-frame) {
border: 1px solid #e9ecef;
min-height: 80px;
}
/* Responsivo */
@media (max-width: 768px) {
:global(.calendario-ferias .fc .fc-toolbar) {
flex-direction: column;
gap: 0.75rem;
}
:global(.calendario-ferias .fc .fc-toolbar-title) {
font-size: 1.25rem;
}
:global(.calendario-ferias .fc .fc-button) {
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
}
}

View File

@@ -1,6 +1,5 @@
{
"lockfileVersion": 1,
"configVersion": 0,
"workspaces": {
"": {
"name": "sgse-app",
@@ -42,7 +41,7 @@
"@types/papaparse": "^5.3.14",
"better-auth": "catalog:",
"convex": "catalog:",
"convex-svelte": "^0.0.11",
"convex-svelte": "^0.0.12",
"date-fns": "^4.1.0",
"emoji-picker-element": "^1.27.0",
"eslint": "catalog:",
@@ -120,7 +119,7 @@
"catalog": {
"@eslint/js": "^9.39.1",
"better-auth": "1.3.27",
"convex": "^1.28.0",
"convex": "^1.28.2",
"eslint": "^9.39.1",
"typescript": "^5.9.2",
},
@@ -717,11 +716,11 @@
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
"convex": ["convex@1.28.0", "", { "dependencies": { "esbuild": "0.25.4", "prettier": "^3.0.0" }, "peerDependencies": { "@auth0/auth0-react": "^2.0.1", "@clerk/clerk-react": "^4.12.8 || ^5.0.0", "react": "^18.0.0 || ^19.0.0-0 || ^19.0.0" }, "optionalPeers": ["@auth0/auth0-react", "@clerk/clerk-react", "react"], "bin": { "convex": "bin/main.js" } }, "sha512-40FgeJ/LxP9TxnkDDztU/A5gcGTdq1klcTT5mM0Ak+kSlQiDktMpjNX1TfkWLxXaE3lI4qvawKH95v2RiYgFxA=="],
"convex": ["convex@1.29.0", "", { "dependencies": { "esbuild": "0.25.4", "prettier": "^3.0.0" }, "peerDependencies": { "@auth0/auth0-react": "^2.0.1", "@clerk/clerk-react": "^4.12.8 || ^5.0.0", "react": "^18.0.0 || ^19.0.0-0 || ^19.0.0" }, "optionalPeers": ["@auth0/auth0-react", "@clerk/clerk-react", "react"], "bin": { "convex": "bin/main.js" } }, "sha512-uoIPXRKIp2eLCkkR9WJ2vc9NtgQtx8Pml59WPUahwbrd5EuW2WLI/cf2E7XrUzOSifdQC3kJZepisk4wJNTJaA=="],
"convex-helpers": ["convex-helpers@0.1.104", "", { "peerDependencies": { "@standard-schema/spec": "^1.0.0", "convex": "^1.24.0", "hono": "^4.0.5", "react": "^17.0.2 || ^18.0.0 || ^19.0.0", "typescript": "^5.5", "zod": "^3.22.4 || ^4.0.15" }, "optionalPeers": ["@standard-schema/spec", "hono", "react", "typescript", "zod"], "bin": { "convex-helpers": "bin.cjs" } }, "sha512-7CYvx7T3K6n+McDTK4ZQaQNNGBzq5aWezpjzsKbOxPXx7oNcTP9wrpef3JxeXWFzkByJv5hRCjseh9B7eNJ7Ig=="],
"convex-svelte": ["convex-svelte@0.0.11", "", { "peerDependencies": { "convex": "^1.10.0", "svelte": "^5.0.0" } }, "sha512-N/29gg5Zqy72vKL4xHSLk3jGwXVKIWXPs6xzq6KxGL84y/D6hG85pG2CPOzn08EzMmByts5FTkJ5p3var6yDng=="],
"convex-svelte": ["convex-svelte@0.0.12", "", { "dependencies": { "esm-env": "^1.2.2", "runed": "^0.31.1" }, "peerDependencies": { "convex": "^1.10.0", "svelte": "^5.0.0" } }, "sha512-sUZoYp4ZsokyvKlbbg1dWYB7MkAjZn4nNG9DnADEt9L6KTKuhhnEIt6fdLj+3GnVBUGDTssm17+7ppzFc4y7Gg=="],
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
@@ -1347,6 +1346,8 @@
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
"@mmailaender/convex-better-auth-svelte/convex-svelte": ["convex-svelte@0.0.11", "", { "peerDependencies": { "convex": "^1.10.0", "svelte": "^5.0.0" } }, "sha512-N/29gg5Zqy72vKL4xHSLk3jGwXVKIWXPs6xzq6KxGL84y/D6hG85pG2CPOzn08EzMmByts5FTkJ5p3var6yDng=="],
"@sveltejs/kit/@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
"@sveltejs/kit/cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
@@ -1371,6 +1372,8 @@
"convex/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="],
"convex-svelte/runed": ["runed@0.31.1", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-v3czcTnO+EJjiPvD4dwIqfTdHLZ8oH0zJheKqAHh9QMViY7Qb29UlAMRpX7ZtHh7AFqV60KmfxaJ9QMy+L1igQ=="],
"eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],

View File

@@ -8,7 +8,7 @@
"packages/*"
],
"catalog": {
"convex": "^1.28.0",
"convex": "^1.28.2",
"typescript": "^5.9.2",
"better-auth": "1.3.27",
"eslint": "^9.39.1",

View File

@@ -15,8 +15,8 @@ import type * as actions_smtp from "../actions/smtp.js";
import type * as actions_utils_nodeCrypto from "../actions/utils/nodeCrypto.js";
import type * as atestadosLicencas from "../atestadosLicencas.js";
import type * as ausencias from "../ausencias.js";
import type * as auth_utils from "../auth/utils.js";
import type * as auth from "../auth.js";
import type * as auth_utils from "../auth/utils.js";
import type * as chat from "../chat.js";
import type * as configuracaoEmail from "../configuracaoEmail.js";
import type * as crons from "../crons.js";
@@ -54,14 +54,6 @@ import type {
FunctionReference,
} from "convex/server";
/**
* A utility for referencing Convex functions in your app's API.
*
* Usage:
* ```js
* const myFunctionReference = api.myModule.myFunction;
* ```
*/
declare const fullApi: ApiFromModules<{
"actions/email": typeof actions_email;
"actions/linkPreview": typeof actions_linkPreview;
@@ -70,8 +62,8 @@ declare const fullApi: ApiFromModules<{
"actions/utils/nodeCrypto": typeof actions_utils_nodeCrypto;
atestadosLicencas: typeof atestadosLicencas;
ausencias: typeof ausencias;
"auth/utils": typeof auth_utils;
auth: typeof auth;
"auth/utils": typeof auth_utils;
chat: typeof chat;
configuracaoEmail: typeof configuracaoEmail;
crons: typeof crons;
@@ -103,14 +95,30 @@ declare const fullApi: ApiFromModules<{
"utils/getClientIP": typeof utils_getClientIP;
verificarMatriculas: typeof verificarMatriculas;
}>;
declare const fullApiWithMounts: typeof fullApi;
/**
* A utility for referencing Convex functions in your app's public API.
*
* Usage:
* ```js
* const myFunctionReference = api.myModule.myFunction;
* ```
*/
export declare const api: FilterApi<
typeof fullApiWithMounts,
typeof fullApi,
FunctionReference<any, "public">
>;
/**
* A utility for referencing Convex functions in your app's internal API.
*
* Usage:
* ```js
* const myFunctionReference = internal.myModule.myFunction;
* ```
*/
export declare const internal: FilterApi<
typeof fullApiWithMounts,
typeof fullApi,
FunctionReference<any, "internal">
>;

View File

@@ -10,7 +10,6 @@
import {
ActionBuilder,
AnyComponents,
HttpActionBuilder,
MutationBuilder,
QueryBuilder,
@@ -19,15 +18,9 @@ import {
GenericQueryCtx,
GenericDatabaseReader,
GenericDatabaseWriter,
FunctionReference,
} from "convex/server";
import type { DataModel } from "./dataModel.js";
type GenericCtx =
| GenericActionCtx<DataModel>
| GenericMutationCtx<DataModel>
| GenericQueryCtx<DataModel>;
/**
* Define a query in this Convex app's public API.
*
@@ -92,11 +85,12 @@ export declare const internalAction: ActionBuilder<DataModel, "internal">;
/**
* Define an HTTP action.
*
* This function will be used to respond to HTTP requests received by a Convex
* deployment if the requests matches the path and method where this action
* is routed. Be sure to route your action in `convex/http.js`.
* The wrapped function will be used to respond to HTTP requests received
* by a Convex deployment if the requests matches the path and method where
* this action is routed. Be sure to route your httpAction in `convex/http.js`.
*
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
* @param func - The function. It receives an {@link ActionCtx} as its first argument
* and a Fetch API `Request` object as its second.
* @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
*/
export declare const httpAction: HttpActionBuilder;

View File

@@ -16,7 +16,6 @@ import {
internalActionGeneric,
internalMutationGeneric,
internalQueryGeneric,
componentsGeneric,
} from "convex/server";
/**
@@ -81,10 +80,14 @@ export const action = actionGeneric;
export const internalAction = internalActionGeneric;
/**
* Define a Convex HTTP action.
* Define an HTTP action.
*
* @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object
* as its second.
* @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.
* The wrapped function will be used to respond to HTTP requests received
* by a Convex deployment if the requests matches the path and method where
* this action is routed. Be sure to route your httpAction in `convex/http.js`.
*
* @param func - The function. It receives an {@link ActionCtx} as its first argument
* and a Fetch API `Request` object as its second.
* @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
*/
export const httpAction = httpActionGeneric;