diff --git a/apps/web/src/routes/(dashboard)/recursos-humanos/controle-ponto/homologacao/+page.svelte b/apps/web/src/routes/(dashboard)/recursos-humanos/controle-ponto/homologacao/+page.svelte index 913bbc9..061f56f 100644 --- a/apps/web/src/routes/(dashboard)/recursos-humanos/controle-ponto/homologacao/+page.svelte +++ b/apps/web/src/routes/(dashboard)/recursos-humanos/controle-ponto/homologacao/+page.svelte @@ -13,7 +13,7 @@ let funcionarioSelecionado = $state | ''>(''); let registroSelecionado = $state | ''>(''); let modoEdicao = $state(false); - let modoAjuste = $state(false); + let abaAtiva = $state<'editar' | 'ajustar'>('editar'); // Formulário de edição let horaNova = $state(8); @@ -23,11 +23,72 @@ let motivoDescricao = $state(''); let observacoes = $state(''); + // Campo de hora unificado (formato HH:mm) + let novaHoraFormatada = $state('08:00'); + + // Converter hora/minuto para formato HH:mm + function horaMinutoParaTime(hora: number, minuto: number): string { + return `${hora.toString().padStart(2, '0')}:${minuto.toString().padStart(2, '0')}`; + } + + // Converter formato HH:mm para hora/minuto + function timeParaHoraMinuto(time: string): { hora: number; minuto: number } { + const [h, m] = time.split(':').map(Number); + return { hora: h || 0, minuto: m || 0 }; + } + + // Calcular período entre duas datas/horas em dias, horas e minutos + function calcularPeriodo( + dataInicio: string, + horaInicio: string, + dataFim: string, + horaFim: string + ): { dias: number; horas: number; minutos: number } { + if (!dataInicio || !horaInicio || !dataFim || !horaFim) { + return { dias: 0, horas: 0, minutos: 0 }; + } + + const inicio = new Date(`${dataInicio}T${horaInicio}:00`); + const fim = new Date(`${dataFim}T${horaFim}:00`); + + if (fim < inicio) { + return { dias: 0, horas: 0, minutos: 0 }; + } + + const diffMs = fim.getTime() - inicio.getTime(); + const diffMinutos = Math.floor(diffMs / (1000 * 60)); + + const dias = Math.floor(diffMinutos / (24 * 60)); + const minutosRestantes = diffMinutos % (24 * 60); + const horas = Math.floor(minutosRestantes / 60); + const minutos = minutosRestantes % 60; + + return { dias, horas, minutos }; + } + + // Obter registro selecionado + const registroEmEdicao = $derived.by(() => { + if (!registroSelecionado) return null; + return registros.find((r) => r._id === registroSelecionado) || null; + }); + + // Formatar data do registro + const dataRegistroFormatada = $derived.by(() => { + if (!registroEmEdicao) return ''; + const data = new Date(registroEmEdicao.data); + return data.toLocaleDateString('pt-BR', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + }); + }); + // Formulário de ajuste let tipoAjuste = $state<'compensar' | 'abonar' | 'descontar'>('compensar'); - let periodoDias = $state(0); - let periodoHoras = $state(0); - let periodoMinutos = $state(0); + let dataInicioAjuste = $state(new Date().toISOString().split('T')[0]!); + let horaInicioAjuste = $state('08:00'); + let dataFimAjuste = $state(new Date().toISOString().split('T')[0]!); + let horaFimAjuste = $state('18:00'); // Queries const subordinadosQuery = useQuery(api.times.listarSubordinadosDoGestorAtual, {}); @@ -75,6 +136,7 @@ registroSelecionado = registroId; horaNova = registro.hora; minutoNova = registro.minuto; + novaHoraFormatada = horaMinutoParaTime(registro.hora, registro.minuto); motivoId = ''; motivoTipo = ''; motivoDescricao = ''; @@ -83,24 +145,40 @@ modoAjuste = false; } - function abrirAjuste() { - modoAjuste = true; - modoEdicao = false; - registroSelecionado = ''; - tipoAjuste = 'compensar'; - periodoDias = 0; - periodoHoras = 0; - periodoMinutos = 0; + function abrirEdicaoComAjuste(registroId: Id<'registrosPonto'>) { + const registro = registros.find((r) => r._id === registroId); + if (!registro) return; + + registroSelecionado = registroId; + horaNova = registro.hora; + minutoNova = registro.minuto; + novaHoraFormatada = horaMinutoParaTime(registro.hora, registro.minuto); motivoId = ''; motivoTipo = ''; motivoDescricao = ''; observacoes = ''; + modoEdicao = true; + abaAtiva = 'editar'; + + // Resetar campos de ajuste + tipoAjuste = 'compensar'; + const hoje = new Date().toISOString().split('T')[0]!; + dataInicioAjuste = hoje; + dataFimAjuste = hoje; + horaInicioAjuste = '08:00'; + horaFimAjuste = '18:00'; } function cancelar() { modoEdicao = false; - modoAjuste = false; registroSelecionado = ''; + abaAtiva = 'editar'; + novaHoraFormatada = '08:00'; + const hoje = new Date().toISOString().split('T')[0]!; + dataInicioAjuste = hoje; + dataFimAjuste = hoje; + horaInicioAjuste = '08:00'; + horaFimAjuste = '18:00'; } async function salvarEdicao() { @@ -109,11 +187,14 @@ return; } + // Converter hora formatada para hora/minuto + const { hora, minuto } = timeParaHoraMinuto(novaHoraFormatada); + try { await client.mutation(api.pontos.editarRegistroPonto, { registroId: registroSelecionado, - horaNova, - minutoNova, + horaNova: hora, + minutoNova: minuto, motivoId: motivoId || undefined, motivoTipo: motivoTipo || undefined, motivoDescricao: motivoDescricao || undefined, @@ -134,8 +215,21 @@ return; } - if (periodoDias === 0 && periodoHoras === 0 && periodoMinutos === 0) { - toast.error('Informe pelo menos um período (dias, horas ou minutos)'); + if (!dataInicioAjuste || !horaInicioAjuste || !dataFimAjuste || !horaFimAjuste) { + toast.error('Preencha todas as datas e horários do período'); + return; + } + + // Calcular período entre início e fim + const { dias, horas, minutos } = calcularPeriodo( + dataInicioAjuste, + horaInicioAjuste, + dataFimAjuste, + horaFimAjuste + ); + + if (dias === 0 && horas === 0 && minutos === 0) { + toast.error('A data/hora final deve ser maior que a inicial'); return; } @@ -143,9 +237,9 @@ await client.mutation(api.pontos.ajustarBancoHoras, { funcionarioId: funcionarioSelecionado, tipoAjuste, - periodoDias, - periodoHoras, - periodoMinutos, + periodoDias: dias, + periodoHoras: horas, + periodoMinutos: minutos, motivoId: motivoId || undefined, motivoTipo: motivoTipo || undefined, motivoDescricao: motivoDescricao || undefined, @@ -182,7 +276,7 @@ + +
+
+

+ + Homologar Registro de Ponto +

+ {#if dataRegistroFormatada} +

+ Registro do dia {dataRegistroFormatada} +

+ {/if}
+
-
- - + +
+ + +
+ + + {#if abaAtiva === 'editar'} +
+ +
+ + +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+ + +
+ {/if} -
- - + + + + +
+ + +
+ + + +
+

+
+ Início do Período +

+
+
+ + +
+ +
+ + +
+
+
+ + +
+ +
+ + +
+

+
+ Fim do Período +

+
+
+ + +
+ +
+ + +
+
+
+ + + {#if dataInicioAjuste && horaInicioAjuste && dataFimAjuste && horaFimAjuste} + {@const periodoCalculado = calcularPeriodo(dataInicioAjuste, horaInicioAjuste, dataFimAjuste, horaFimAjuste)} + {#if periodoCalculado.dias > 0 || periodoCalculado.horas > 0 || periodoCalculado.minutos > 0} +
+
Período Calculado:
+
+ {periodoCalculado.dias > 0 ? `${periodoCalculado.dias} dia${periodoCalculado.dias > 1 ? 's' : ''} ` : ''} + {periodoCalculado.horas > 0 ? `${periodoCalculado.horas} hora${periodoCalculado.horas > 1 ? 's' : ''} ` : ''} + {periodoCalculado.minutos > 0 ? `${periodoCalculado.minutos} minuto${periodoCalculado.minutos > 1 ? 's' : ''}` : ''} + {#if periodoCalculado.dias === 0 && periodoCalculado.horas === 0 && periodoCalculado.minutos === 0} + Período inválido + {/if} +
+
+ {/if} {/if} - +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+ + +
- -
- - -
- -
- - -
- - -
- - -
- - - {/if} - - - {#if modoAjuste} -
-
-

Ajustar Banco de Horas

- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
- -
- - -
+ {/if}
{/if} - {#if funcionarioSelecionado && !modoEdicao && !modoAjuste} + {#if funcionarioSelecionado && !modoEdicao}

Registros do Funcionário

@@ -419,7 +617,7 @@