diff --git a/apps/web/src/lib/components/ponto/RelogioSincronizado.svelte b/apps/web/src/lib/components/ponto/RelogioSincronizado.svelte index 181d24f..9f09cc5 100644 --- a/apps/web/src/lib/components/ponto/RelogioSincronizado.svelte +++ b/apps/web/src/lib/components/ponto/RelogioSincronizado.svelte @@ -9,12 +9,21 @@ let tempoAtual = $state(new Date()); let sincronizado = $state(false); + let sincronizando = $state(false); let usandoServidorExterno = $state(false); let offsetSegundos = $state(0); let erro = $state(null); let intervalId: ReturnType | null = null; + let intervaloSincronizacao: ReturnType | null = null; + let sincronizacaoEmAndamento = $state(false); // Flag para evitar múltiplas sincronizações simultâneas async function atualizarTempo() { + // Evitar múltiplas sincronizações simultâneas + if (sincronizacaoEmAndamento) { + return; + } + sincronizacaoEmAndamento = true; + sincronizando = true; try { const config = await client.query(api.configuracaoRelogio.obterConfiguracao, {}); // Usar gmtOffset da configuração, sem valor padrão, pois 0 é um valor válido @@ -25,7 +34,12 @@ if (config.usarServidorExterno) { try { - const resultado = await client.action(api.configuracaoRelogio.sincronizarTempo, {}); + // Adicionar timeout de 10 segundos para sincronização + const sincronizacaoPromise = client.action(api.configuracaoRelogio.sincronizarTempo, {}); + const timeoutPromise = new Promise((_, reject) => + setTimeout(() => reject(new Error('Timeout na sincronização (10s)')), 10000) + ); + const resultado = await Promise.race([sincronizacaoPromise, timeoutPromise]); if (resultado.sucesso && resultado.timestamp) { timestampBase = resultado.timestamp; sincronizado = true; @@ -43,7 +57,11 @@ usandoServidorExterno = false; erro = 'Usando relógio do PC (falha na sincronização)'; } else { - throw error; + // Mesmo sem fallback configurado, usar PC como última opção + timestampBase = obterTempoPC(); + sincronizado = false; + usandoServidorExterno = false; + erro = 'Usando relógio do PC (servidor indisponível)'; } } } else { @@ -71,6 +89,9 @@ tempoAtual = new Date(obterTempoPC()); sincronizado = false; erro = 'Erro ao obter tempo do servidor'; + } finally { + sincronizando = false; + sincronizacaoEmAndamento = false; } } @@ -81,17 +102,34 @@ } onMount(async () => { - await atualizarTempo(); - // Sincronizar a cada 30 segundos - setInterval(atualizarTempo, 30000); + // Inicializar com relógio do PC imediatamente para não bloquear a interface + tempoAtual = new Date(obterTempoPC()); + sincronizado = false; + erro = 'Usando relógio do PC'; // Atualizar display a cada segundo intervalId = setInterval(atualizarRelogio, 1000); + // Sincronizar em background (não bloquear) após um pequeno delay para garantir que a UI está renderizada + setTimeout(() => { + atualizarTempo().catch((error) => { + console.error('Erro ao sincronizar tempo em background:', error); + }); + }, 100); + // Sincronizar a cada 30 segundos + intervaloSincronizacao = setInterval(() => { + atualizarTempo().catch((error) => { + console.error('Erro ao sincronizar tempo periódico:', error); + }); + }, 30000); }); onDestroy(() => { if (intervalId) { clearInterval(intervalId); } + if (intervaloSincronizacao) { + clearInterval(intervaloSincronizacao); + } + sincronizacaoEmAndamento = false; }); const horaFormatada = $derived.by(() => { @@ -131,13 +169,18 @@
- {#if sincronizado} + {#if sincronizando} + + Sincronizando com servidor... + {:else if sincronizado} {#if usandoServidorExterno}