diff --git a/apps/web/package.json b/apps/web/package.json index 61cc60c..8eb81c6 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -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", diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/ferias/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/ferias/+page.svelte index 9c8243c..cd6d2f2 100644 --- a/apps/web/src/routes/(dashboard)/recursos-humanos/ferias/+page.svelte +++ b/apps/web/src/routes/(dashboard)/recursos-humanos/ferias/+page.svelte @@ -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([]); + + // 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( + todasSolicitacoesQuery?.data ?? ultimasSolicitacoesValidas + ); + let filtroStatus = $state('todos'); let filtroNome = $state(''); let filtroMatricula = $state(''); @@ -46,7 +84,6 @@ let filtroPeriodoFim = $state(''); let dataInicioRelatorio = $state(''); let dataFimRelatorio = $state(''); - const solicitacoes = $derived(todasSolicitacoesQuery?.data ?? []); // Filtrar solicitações const solicitacoesFiltradas = $derived( @@ -304,68 +341,131 @@ let calendarioContainer: HTMLDivElement | null = null; let calendarioInstance: CalendarInstance | null = null; let CalendarClass: CalendarConstructor | null = null; + let calendarioInicializado = $state(false); - onMount(() => { - let destroyed = false; - - const inicializarCalendario = async () => { - const [coreModule, dayGridModule, interactionModule, localeModule] = await Promise.all([ - import('@fullcalendar/core'), - import('@fullcalendar/daygrid'), - import('@fullcalendar/interaction'), - import('@fullcalendar/core/locales/pt-br') - ]); - - if (destroyed || !calendarioContainer) { - return; - } - - CalendarClass = coreModule.Calendar; - const dayGridPlugin = dayGridModule.default; - const interactionPlugin = interactionModule.default; - const ptBrLocale = localeModule.default; - - calendarioInstance = new CalendarClass(calendarioContainer, { - plugins: [dayGridPlugin, interactionPlugin], - initialView: 'dayGridMonth', - height: 'auto', - locale: 'pt-br', - locales: [ptBrLocale], - navLinks: true, - weekNumbers: false, - headerToolbar: { - left: 'prev,next today', - center: 'title', - right: 'dayGridMonth,dayGridWeek' - }, - buttonText: { - today: 'Hoje', - month: 'Mês', - week: 'Semana' - }, - events: eventosFerias - }); - - calendarioInstance.render(); - }; - - void inicializarCalendario(); - - return () => { - destroyed = true; - calendarioInstance?.destroy(); - calendarioInstance = null; - }; - }); - + // Inicializar calendário quando o container estiver disponível $effect(() => { - if (!calendarioInstance) { + // Verificar se o container está disponível e o calendário ainda não foi inicializado + const container = calendarioContainer; + + if (!container || calendarioInicializado || calendarioInstance) { return; } - calendarioInstance.removeAllEvents(); - for (const evento of eventosFerias) { - calendarioInstance.addEvent(evento); + // Usar setTimeout para garantir que o elemento está completamente no DOM + let timeoutId: ReturnType | 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'), + import('@fullcalendar/interaction'), + import('@fullcalendar/core/locales/pt-br') + ]); + + // Verificar novamente após os imports + if (!calendarioContainer || calendarioInstance || calendarioInicializado) { + return; + } + + CalendarClass = coreModule.Calendar; + const dayGridPlugin = dayGridModule.default; + const interactionPlugin = interactionModule.default; + const ptBrLocale = localeModule.default; + + calendarioInstance = new CalendarClass(calendarioContainer, { + plugins: [dayGridPlugin, interactionPlugin], + initialView: 'dayGridMonth', + height: 'auto', + locale: 'pt-br', + locales: [ptBrLocale], + navLinks: true, + weekNumbers: false, + headerToolbar: { + left: 'prev,next today', + center: 'title', + right: 'dayGridMonth,dayGridWeek' + }, + buttonText: { + today: 'Hoje', + month: 'Mês', + week: 'Semana' + }, + events: eventosFerias + }); + + calendarioInstance.render(); + calendarioInicializado = true; + } catch (error) { + console.error('Erro ao inicializar calendário:', error); + } + }, 300); + + // Cleanup + return () => { + 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(() => { + // Não atualizar se o calendário não estiver inicializado + if (!calendarioInstance || !calendarioInicializado) { + return; + } + + try { + // Remover todos os eventos existentes + calendarioInstance.removeAllEvents(); + + // 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); + } } }); @@ -844,337 +944,46 @@ + + {#if hasError} +
+ + + +
+

Erro ao carregar dados

+
{errorMessage}
+
+
+ {/if} +
-
-
- - - -
-
Total
-
{stats.total}
-
Solicitações
-
- -
-
- - - -
-
Aguardando
-
{stats.aguardando}
-
Pendentes
-
- -
-
- - - -
-
Aprovadas
-
{stats.aprovadas}
-
Deferidas
-
- -
-
- - - -
-
Reprovadas
-
{stats.reprovadas}
-
Indeferidas
-
-
- - -
-
-
-

Filtros

- -
- -
- -
-
-
- Status - {#if filtroStatus !== 'todos'} - - {/if} -
- -

- Defina o status das solicitações que deseja visualizar. -

-
+ {#if isLoading && !hasError} + {#each Array.from({ length: 4 }, (_, i) => i) as index (index)} +
+
+
+
+
- - -
-
-
- Nome do funcionário - -
- -

- Pesquise por nome completo ou parcial para localizar rapidamente um colaborador. -

-
-
- - -
-
-
- Matrícula - -
- -

- Utilize a matrícula funcional para filtrar solicitações específicas. -

-
-
- - -
-
-
- E-mail institucional - -
- -

- Busque usando o correio institucional cadastrado na ficha do colaborador. -

-
-
- - -
-
-
- Mês de referência - -
- -

- Filtra as solicitações que possuem períodos ativos dentro do mês informado. -

-
-
- - -
-
-
- Período personalizado - -
-
-
- Data inicial - -
-
- Data final - -
-
-

- Combine as datas para localizar períodos específicos de férias aprovadas ou em - andamento. -

-
-
-
-
-
- - -
-
-
-
+ {/each} + {:else} +
+
-
-

- Impressão da Programação de Férias -

-

- Escolha o período desejado e gere um relatório pronto para impressão com todos os - colaboradores em férias, incluindo detalhes completos de cada período. -

-
+
Total
+
{stats.total}
+
Solicitações
-
-
- - -
-
- - -
-
- -
-
-

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

-
-
- -
-
-

- Solicitações ({solicitacoesFiltradas.length}) -

- - {#if solicitacoesFiltradas.length === 0} -
+
+
+ d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" + /> - Nenhuma solicitação encontrada com os filtros aplicados.
- {:else} -
- - - - - - - - - - - - - - {#each solicitacoesFiltradas as solicitacao (solicitacao._id)} - - - - - - - - - - {/each} - -
FuncionárioTimeAnoPeríodosTotal DiasStatusSolicitado em
-
-
-
- {solicitacao.funcionario?.nome.substring(0, 2).toUpperCase()} -
-
-
-
{solicitacao.funcionario?.nome}
-
- {solicitacao.funcionario?.matricula || 'S/N'} -
-
-
-
- {#if solicitacao.time} -
- {solicitacao.time.nome} -
- {:else} - Sem time - {/if} -
{solicitacao.anoReferencia}{solicitacao.periodos.length} período(s){totalDiasSolicitacao(solicitacao)} dia(s) -
- {getStatusTexto(solicitacao.status)} -
-
{formatarData(solicitacao._creationTime)}
-
- {/if} -
-
- -
- -
-
-
-
- - - -
-
-

- Dias de Férias Programados por Mês -

-

- Somatório de dias planejados considerando a data de início de cada período -

-
-
-
+
Aguardando
+
{stats.aguardando}
+
Pendentes
+
+ +
+
- {#if periodosPorMesAtivos.length === 0} - Sem dados registrados até o momento. - {:else} - {@const maxDias = Math.max( - 1, - getMax(periodosPorMesAtivos, (p) => p.totalDias) - )} - {#each [0, 1, 2, 3, 4, 5] as passo (passo)} - {@const valor = Math.round((maxDias / 5) * passo)} - {@const y = chartHeight - padding.bottom - scaleY(valor, maxDias)} - - - {valor} dia(s) - - {/each} - - - p.totalDias, maxDias)} - fill="url(#gradient-ferias-mes)" - opacity="0.75" - /> - { - const x = getX(index, periodosPorMesAtivos.length); - const y = chartHeight - padding.bottom - scaleY(item.totalDias, maxDias); - return `${x},${y}`; - (''); - }) - .join(' ')} - fill="none" - stroke="rgb(59, 130, 246)" - stroke-width="3" - stroke-linecap="round" - /> - {#each periodosPorMesAtivos as item, index (item.label)} - {@const x = getX(index, periodosPorMesAtivos.length)} - {@const y = chartHeight - padding.bottom - scaleY(item.totalDias, maxDias)} - - - {item.totalDias} dia(s) - - - {item.quantidadePeriodos} período(s) - - {/each} - {#each periodosPorMesAtivos as item, index (item.label)} - {@const x = getX(index, periodosPorMesAtivos.length)} - -
- {item.label} -
-
- {/each} - - - - - - - {/if} +
- {#if periodosPorMes.length > 1} -
+
+
Aprovadas
+
{stats.aprovadas}
+
Deferidas
+
+ +
+
+ + + +
+
Reprovadas
+
{stats.reprovadas}
+
Indeferidas
+
+ {/if} +
+ + + {#if isLoading && !hasError} +
+
+
+
+ {#each Array.from({ length: 6 }, (_, i) => i) as index (index)} +
+
+
+ {/each} +
+
+
+ {:else} +
+
+
+

Filtros

+ +
+ +
+ +
+
- Janela exibida - - {periodosPorMes[rangeInicioIndice]?.label ?? '-'} - → - {periodosPorMes[rangeFimIndice]?.label ?? '-'} - -
-
-
- Status + {#if filtroStatus !== 'todos'} +
-
- - -
+ Limpar + + {/if}
-

- Ajuste com o mouse os intervalos exibidos no gráfico. + +

+ Defina o status das solicitações que deseja visualizar.

- {/if} +
+ + +
+
+
+ Nome do funcionário + +
+ +

+ Pesquise por nome completo ou parcial para localizar rapidamente um colaborador. +

+
+
+ + +
+
+
+ Matrícula + +
+ +

+ Utilize a matrícula funcional para filtrar solicitações específicas. +

+
+
+ + +
+
+
+ E-mail institucional + +
+ +

+ Busque usando o correio institucional cadastrado na ficha do colaborador. +

+
+
+ + +
+
+
+ Mês de referência + +
+ +

+ Filtra as solicitações que possuem períodos ativos dentro do mês informado. +

+
+
+ + +
+
+
+ Período personalizado + +
+
+
+ Data inicial + +
+
+ Data final + +
+
+

+ Combine as datas para localizar períodos específicos de férias aprovadas ou em + andamento. +

+
+
+ {/if} - -
+ + {#if !isLoading || !hasError} +
-
+
-
+

- Dias Totais Aprovados por Ano de Referência + Impressão da Programação de Férias

- Volume agregado de dias e número de solicitações por ano + Escolha o período desejado e gere um relatório pronto para impressão com todos os + colaboradores em férias, incluindo detalhes completos de cada período.

-
- - {#if solicitacoesPorAno.length === 0} - Ainda não há solicitações registradas para exibição. - {:else} - {@const maxDiasAno = Math.max( - 1, - getMax(solicitacoesPorAno, (item) => item.diasTotais) - )} - {#each [0, 1, 2, 3, 4, 5] as passo (passo)} - {@const valor = Math.round((maxDiasAno / 5) * passo)} - {@const y = chartHeight - padding.bottom - scaleY(valor, maxDiasAno)} - - - {valor} dia(s) - - {/each} - - - item.diasTotais, maxDiasAno)} - fill="url(#gradient-ferias-ano)" - opacity="0.75" - /> - { - const x = getX(index, solicitacoesPorAno.length); - const y = chartHeight - padding.bottom - scaleY(item.diasTotais, maxDiasAno); - return `${x},${y}`; - }) - .join(' ')} +
+
+ + +
+
+ + +
+
+ +
+
+

+ 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. +

+
+
+ {/if} + + + {#if isLoading && !hasError} +
+
+
+
+ {#each Array.from({ length: 5 }, (_, i) => i) as index (index)} +
+ {/each}
+ {:else} +
+
+

+ Solicitações ({solicitacoesFiltradas.length}) +

- -
-
-
-
+ {#if solicitacoesFiltradas.length === 0} +
+ d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" + > + Nenhuma solicitação encontrada com os filtros aplicados.
-
-

Calendário Geral de Férias

-

- Visualize os períodos aprovados diretamente no calendário interativo -

+ {:else} +
+ + + + + + + + + + + + + + {#each solicitacoesFiltradas as solicitacao (solicitacao._id)} + + + + + + + + + + {/each} + +
FuncionárioTimeAnoPeríodosTotal DiasStatusSolicitado em
+
+
+
+ {solicitacao.funcionario?.nome.substring(0, 2).toUpperCase()} +
+
+
+
{solicitacao.funcionario?.nome}
+
+ {solicitacao.funcionario?.matricula || 'S/N'} +
+
+
+
+ {#if solicitacao.time} +
+ {solicitacao.time.nome} +
+ {:else} + Sem time + {/if} +
{solicitacao.anoReferencia}{solicitacao.periodos.length} período(s){totalDiasSolicitacao(solicitacao)} dia(s) +
+ {getStatusTexto(solicitacao.status)} +
+
{formatarData(solicitacao._creationTime)}
+
+ {/if} +
+
+ {/if} + + + {#if isLoading && !hasError} +
+ {#each Array.from({ length: 3 }, (_, i) => i) as index (index)} +
+
+
+
-
-
+ {/each} +
+ {:else} +
+ +
+
+
+
+ + + +
+
+

+ Dias de Férias Programados por Mês +

+

+ Somatório de dias planejados considerando a data de início de cada período +

+
+
+
+ + {#if periodosPorMesAtivos.length === 0} + Sem dados registrados até o momento. + {:else} + {@const maxDias = Math.max( + 1, + getMax(periodosPorMesAtivos, (p) => p.totalDias) + )} + {#each [0, 1, 2, 3, 4, 5] as passo (passo)} + {@const valor = Math.round((maxDias / 5) * passo)} + {@const y = chartHeight - padding.bottom - scaleY(valor, maxDias)} + + + {valor} dia(s) + + {/each} + + + p.totalDias, maxDias)} + fill="url(#gradient-ferias-mes)" + opacity="0.75" + /> + { + const x = getX(index, periodosPorMesAtivos.length); + const y = chartHeight - padding.bottom - scaleY(item.totalDias, maxDias); + return `${x},${y}`; + }) + .join(' ')} + fill="none" + stroke="rgb(59, 130, 246)" + stroke-width="3" + stroke-linecap="round" + /> + {#each periodosPorMesAtivos as item, index (item.label)} + {@const x = getX(index, periodosPorMesAtivos.length)} + {@const y = chartHeight - padding.bottom - scaleY(item.totalDias, maxDias)} + + + {item.totalDias} dia(s) + + + {item.quantidadePeriodos} período(s) + + {/each} + {#each periodosPorMesAtivos as item, index (item.label)} + {@const x = getX(index, periodosPorMesAtivos.length)} + +
+ {item.label} +
+
+ {/each} + + + + + + + {/if} +
+ {#if periodosPorMes.length > 1} +
+
+ Janela exibida + + {periodosPorMes[rangeInicioIndice]?.label ?? '-'} + → + {periodosPorMes[rangeFimIndice]?.label ?? '-'} + +
+
+
+ + +
+
+ + +
+
+

+ Ajuste com o mouse os intervalos exibidos no gráfico. +

+
+ {/if} +
+
+
+ + +
+
+
+
+ + + +
+
+

+ Dias Totais Aprovados por Ano de Referência +

+

+ Volume agregado de dias e número de solicitações por ano +

+
+
+
+ + {#if solicitacoesPorAno.length === 0} + Ainda não há solicitações registradas para exibição. + {:else} + {@const maxDiasAno = Math.max( + 1, + getMax(solicitacoesPorAno, (item) => item.diasTotais) + )} + {#each [0, 1, 2, 3, 4, 5] as passo (passo)} + {@const valor = Math.round((maxDiasAno / 5) * passo)} + {@const y = chartHeight - padding.bottom - scaleY(valor, maxDiasAno)} + + + {valor} dia(s) + + {/each} + + + item.diasTotais, maxDiasAno)} + fill="url(#gradient-ferias-ano)" + opacity="0.75" + /> + { + const x = getX(index, solicitacoesPorAno.length); + const y = chartHeight - padding.bottom - scaleY(item.diasTotais, maxDiasAno); + return `${x},${y}`; + }) + .join(' ')} + fill="none" + stroke="rgb(16, 185, 129)" + stroke-width="3" + stroke-linecap="round" + /> + {#each solicitacoesPorAno as item, index (item.ano)} + {@const x = getX(index, solicitacoesPorAno.length)} + {@const y = chartHeight - padding.bottom - scaleY(item.diasTotais, maxDiasAno)} + + + {item.diasTotais} dia(s) + + + {item.solicitacoes} solicitação(ões) + + {/each} + {#each solicitacoesPorAno as item, index (item.ano)} + {@const x = getX(index, solicitacoesPorAno.length)} + +
+ {item.ano} +
+
+ {/each} + + + + + + + {/if} +
+
+
+
+ + +
+
+
+
+ + + +
+
+

Calendário Geral de Férias

+

+ Visualize os períodos aprovados diretamente no calendário interativo +

+
+
+
+
+
-
+ {/if}
SGSE - Sistema de Gerenciamento da Secretaria de Esportes.
+ + diff --git a/bun.lock b/bun.lock index b026cf6..da367c8 100644 --- a/bun.lock +++ b/bun.lock @@ -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=="], diff --git a/package.json b/package.json index c2c84bd..1bfb50c 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/backend/convex/_generated/api.d.ts b/packages/backend/convex/_generated/api.d.ts index a7f3da2..87b4b87 100644 --- a/packages/backend/convex/_generated/api.d.ts +++ b/packages/backend/convex/_generated/api.d.ts @@ -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 >; + +/** + * 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 >; diff --git a/packages/backend/convex/_generated/server.d.ts b/packages/backend/convex/_generated/server.d.ts index b5c6828..bec05e6 100644 --- a/packages/backend/convex/_generated/server.d.ts +++ b/packages/backend/convex/_generated/server.d.ts @@ -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 - | GenericMutationCtx - | GenericQueryCtx; - /** * Define a query in this Convex app's public API. * @@ -92,11 +85,12 @@ export declare const internalAction: ActionBuilder; /** * 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; diff --git a/packages/backend/convex/_generated/server.js b/packages/backend/convex/_generated/server.js index 4a21df4..bf3d25a 100644 --- a/packages/backend/convex/_generated/server.js +++ b/packages/backend/convex/_generated/server.js @@ -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;