diff --git a/apps/web/src/lib/components/chat/ChatWidget.svelte b/apps/web/src/lib/components/chat/ChatWidget.svelte
index 970b0ba..8a3edcd 100644
--- a/apps/web/src/lib/components/chat/ChatWidget.svelte
+++ b/apps/web/src/lib/components/chat/ChatWidget.svelte
@@ -1315,10 +1315,9 @@
tabindex="0"
aria-label="Redimensionar janela pela borda superior"
class="absolute top-0 right-0 left-0 z-50 h-2 cursor-ns-resize transition-colors"
- style="--hover-bg: {obterPrimariaRgba(0.2)}"
+ style="--hover-bg: {obterPrimariaRgba(0.2)}; border-radius: 24px 24px 0 0;"
onmousedown={(e) => handleResizeStart(e, 'n')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'n')}
- style="border-radius: 24px 24px 0 0;"
>
handleResizeStart(e, 's')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 's')}
- style="border-radius: 0 0 24px 24px;"
>
handleResizeStart(e, 'w')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'w')}
- style="border-radius: 24px 0 0 24px;"
>
handleResizeStart(e, 'e')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'e')}
- style="border-radius: 0 24px 24px 0;"
>
handleResizeStart(e, 'nw')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'nw')}
- style="border-radius: 24px 0 0 0;"
>
handleResizeStart(e, 'ne')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'ne')}
- style="border-radius: 0 24px 0 0;"
>
handleResizeStart(e, 'sw')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'sw')}
- style="border-radius: 0 0 0 24px;"
>
handleResizeStart(e, 'se')}
onkeydown={(e) => e.key === 'Enter' && handleResizeStart(e, 'se')}
- style="border-radius: 0 0 24px 0;"
>
diff --git a/apps/web/src/lib/components/ponto/RegistroPonto.svelte b/apps/web/src/lib/components/ponto/RegistroPonto.svelte
index 3a76e19..f714c8e 100644
--- a/apps/web/src/lib/components/ponto/RegistroPonto.svelte
+++ b/apps/web/src/lib/components/ponto/RegistroPonto.svelte
@@ -35,6 +35,9 @@
const client = useConvexClient();
+ // Estado de sincronização do relógio
+ let sincronizacaoConcluida = $state(false);
+
// Chave de refresh para forçar atualização das queries após registro
let refreshKey = $state(0);
@@ -60,17 +63,12 @@
funcionarioId && dataHoje ? { funcionarioId, data: dataHoje } : 'skip'
);
- const registrosHojeQuery = $derived.by(() =>
- useQuery(api.pontos.listarRegistrosDia, registrosHojeParams)
- );
+ // Queries de ponto - usando useQuery com parâmetros derivados reativos
+ const registrosHojeQuery = useQuery(api.pontos.listarRegistrosDia, registrosHojeParams);
- const historicoSaldoQuery = $derived.by(() =>
- useQuery(api.pontos.obterHistoricoESaldoDia, historicoSaldoParams)
- );
+ const historicoSaldoQuery = useQuery(api.pontos.obterHistoricoESaldoDia, historicoSaldoParams);
- const dispensaQuery = $derived.by(() =>
- useQuery(api.pontos.verificarDispensaAtiva, dispensaParams)
- );
+ const dispensaQuery = useQuery(api.pontos.verificarDispensaAtiva, dispensaParams);
// Query para obter status atual do funcionário (férias/licença)
const funcionarioStatusQuery = useQuery(
@@ -355,6 +353,9 @@
justificativa = ''; // Limpar justificativa após registro
mostrandoModalConfirmacao = false;
+ // Aguardar um pouco para garantir que o backend processou o registro
+ await new Promise((resolve) => setTimeout(resolve, 800));
+
// Forçar atualização das queries para mostrar o novo registro
refreshKey++;
@@ -362,11 +363,13 @@
console.log('[RegistroPonto] Registro bem-sucedido, refreshKey incrementado:', refreshKey);
}
- // Aguardar um pouco para garantir que o backend processou o registro
- await new Promise((resolve) => setTimeout(resolve, 500));
-
- // Forçar mais uma atualização após o delay para garantir sincronização
- refreshKey++;
+ // Aguardar mais um pouco e forçar outra atualização para garantir sincronização completa
+ setTimeout(() => {
+ refreshKey++;
+ if (import.meta.env.DEV) {
+ console.log('[RegistroPonto] Segunda atualização, refreshKey incrementado:', refreshKey);
+ }
+ }, 1500);
// Mostrar comprovante após 1 segundo
setTimeout(() => {
@@ -500,25 +503,27 @@
timestampBase = Date.now();
}
- // Aplicar GMT offset ao timestamp
- // Quando GMT é 0, usar timestamp UTC puro e deixar toLocaleTimeString() fazer a conversão automática
- // Quando GMT ≠ 0, aplicar offset configurado ao timestamp
+ // Aplicar GMT offset ao timestamp (o horário já vem corrigido do servidor)
+ // Apenas aplicar o offset configurado, sem ajustes adicionais de timezone
let timestamp: number;
if (gmtOffset !== 0) {
// Aplicar offset configurado
timestamp = timestampBase + gmtOffset * 60 * 60 * 1000;
} else {
- // Quando GMT = 0, manter timestamp UTC puro
- // O toLocaleTimeString() converterá automaticamente para o timezone local do navegador
+ // Quando GMT = 0, usar timestamp base diretamente (já vem corrigido)
timestamp = timestampBase;
}
+ // Usar métodos UTC diretamente para evitar conversão automática do navegador
+ // O timestamp já está ajustado, então formatamos como UTC para manter o valor correto
const dataObj = new Date(timestamp);
- const data = dataObj.toLocaleDateString('pt-BR');
- const hora = dataObj.toLocaleTimeString('pt-BR', {
- hour: '2-digit',
- minute: '2-digit',
- second: '2-digit'
- });
+ const dia = String(dataObj.getUTCDate()).padStart(2, '0');
+ const mes = String(dataObj.getUTCMonth() + 1).padStart(2, '0');
+ const ano = dataObj.getUTCFullYear();
+ const data = `${dia}/${mes}/${ano}`;
+ const horaStr = String(dataObj.getUTCHours()).padStart(2, '0');
+ const minutoStr = String(dataObj.getUTCMinutes()).padStart(2, '0');
+ const segundoStr = String(dataObj.getUTCSeconds()).padStart(2, '0');
+ const hora = `${horaStr}:${minutoStr}:${segundoStr}`;
dataHoraAtual = { data, hora };
} catch (error) {
console.warn('Erro ao obter tempo do servidor, usando tempo local:', error);
@@ -866,7 +871,8 @@
!estaDispensado &&
!emFerias &&
!emLicenca &&
- temFuncionarioAssociado
+ temFuncionarioAssociado &&
+ sincronizacaoConcluida // Só permitir registro após sincronização concluída
);
});
@@ -1131,24 +1137,40 @@
id="relogio-sincronizado-ref"
class="card from-primary/10 to-primary/5 border-primary/20 w-full max-w-sm rounded-2xl border-2 bg-linear-to-br p-5 shadow-lg"
>
-
+
+
+ {#if !sincronizacaoConcluida}
+
+
+
+
Aguarde a sincronização
+
+ O sistema está sincronizando o horário com o servidor. O botão de registro será habilitado
+ após a conclusão da sincronização.
+
+
+
+ {/if}
+