feat: improve point registration processing feedback with step-by-step messages and update modal positioning across components.
This commit is contained in:
@@ -13,20 +13,20 @@
|
|||||||
|
|
||||||
let modalPosition = $state<{ top: number; left: number } | null>(null);
|
let modalPosition = $state<{ top: number; left: number } | null>(null);
|
||||||
|
|
||||||
// Função para calcular a posição baseada no relógio sincronizado
|
// Função para calcular a posição baseada no card de registro de ponto
|
||||||
function calcularPosicaoModal() {
|
function calcularPosicaoModal() {
|
||||||
// Procurar pelo elemento do relógio sincronizado
|
// Procurar pelo elemento do card de registro de ponto
|
||||||
const relogioRef = document.getElementById('relogio-sincronizado-ref');
|
const cardRef = document.getElementById('card-registro-ponto-ref');
|
||||||
|
|
||||||
if (relogioRef) {
|
if (cardRef) {
|
||||||
const rect = relogioRef.getBoundingClientRect();
|
const rect = cardRef.getBoundingClientRect();
|
||||||
const viewportWidth = window.innerWidth;
|
const viewportWidth = window.innerWidth;
|
||||||
const viewportHeight = window.innerHeight;
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
// Posicionar o modal na mesma posição do relógio sincronizado
|
// Posicionar o modal na mesma posição do card de registro
|
||||||
// Centralizado horizontalmente no card do relógio
|
// Centralizado horizontalmente no card
|
||||||
const left = rect.left + (rect.width / 2);
|
const left = rect.left + (rect.width / 2);
|
||||||
// Posicionar abaixo do card do relógio com um pequeno espaçamento
|
// Posicionar abaixo do card com um pequeno espaçamento
|
||||||
const top = rect.bottom + 20;
|
const top = rect.bottom + 20;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -21,20 +21,20 @@
|
|||||||
let gerando = $state(false);
|
let gerando = $state(false);
|
||||||
let modalPosition = $state<{ top: number; left: number } | null>(null);
|
let modalPosition = $state<{ top: number; left: number } | null>(null);
|
||||||
|
|
||||||
// Função para calcular a posição baseada no relógio sincronizado
|
// Função para calcular a posição baseada no card de registro de ponto
|
||||||
function calcularPosicaoModal() {
|
function calcularPosicaoModal() {
|
||||||
// Procurar pelo elemento do relógio sincronizado
|
// Procurar pelo elemento do card de registro de ponto
|
||||||
const relogioRef = document.getElementById('relogio-sincronizado-ref');
|
const cardRef = document.getElementById('card-registro-ponto-ref');
|
||||||
|
|
||||||
if (relogioRef) {
|
if (cardRef) {
|
||||||
const rect = relogioRef.getBoundingClientRect();
|
const rect = cardRef.getBoundingClientRect();
|
||||||
const viewportWidth = window.innerWidth;
|
const viewportWidth = window.innerWidth;
|
||||||
const viewportHeight = window.innerHeight;
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
// Posicionar o modal na mesma posição do relógio sincronizado
|
// Posicionar o modal na mesma posição do card de registro
|
||||||
// Centralizado horizontalmente no card do relógio
|
// Centralizado horizontalmente no card
|
||||||
const left = rect.left + (rect.width / 2);
|
const left = rect.left + (rect.width / 2);
|
||||||
// Posicionar abaixo do card do relógio com um pequeno espaçamento
|
// Posicionar abaixo do card com um pequeno espaçamento
|
||||||
const top = rect.bottom + 20;
|
const top = rect.bottom + 20;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
let mostrandoModalConfirmacao = $state(false);
|
let mostrandoModalConfirmacao = $state(false);
|
||||||
let dataHoraAtual = $state<{ data: string; hora: string } | null>(null);
|
let dataHoraAtual = $state<{ data: string; hora: string } | null>(null);
|
||||||
let aguardandoProcessamento = $state(false);
|
let aguardandoProcessamento = $state(false);
|
||||||
|
let etapaProcessamento = $state<'coletando' | 'sincronizando' | 'upload' | 'registrando' | null>(null);
|
||||||
|
|
||||||
const registrosHoje = $derived(registrosHojeQuery?.data || []);
|
const registrosHoje = $derived(registrosHojeQuery?.data || []);
|
||||||
const config = $derived(configQuery?.data);
|
const config = $derived(configQuery?.data);
|
||||||
@@ -204,15 +205,19 @@
|
|||||||
registrando = true;
|
registrando = true;
|
||||||
sucesso = null;
|
sucesso = null;
|
||||||
coletandoInfo = true;
|
coletandoInfo = true;
|
||||||
|
aguardandoProcessamento = true;
|
||||||
|
etapaProcessamento = 'coletando';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Coletar informações do dispositivo
|
// Coletar informações do dispositivo
|
||||||
|
etapaProcessamento = 'coletando';
|
||||||
const informacoesDispositivo = await obterInformacoesDispositivo();
|
const informacoesDispositivo = await obterInformacoesDispositivo();
|
||||||
// Nota: A permissão de sensor não é impeditiva - apenas câmera e localização são obrigatórias
|
// Nota: A permissão de sensor não é impeditiva - apenas câmera e localização são obrigatórias
|
||||||
|
|
||||||
coletandoInfo = false;
|
coletandoInfo = false;
|
||||||
|
|
||||||
// Obter tempo sincronizado e aplicar GMT offset (igual ao relógio)
|
// Obter tempo sincronizado e aplicar GMT offset (igual ao relógio)
|
||||||
|
etapaProcessamento = 'sincronizando';
|
||||||
const configRelogio = await client.query(api.configuracaoRelogio.obterConfiguracao, {});
|
const configRelogio = await client.query(api.configuracaoRelogio.obterConfiguracao, {});
|
||||||
// Usar gmtOffset da configuração, sem valor padrão, pois 0 é um valor válido
|
// Usar gmtOffset da configuração, sem valor padrão, pois 0 é um valor válido
|
||||||
const gmtOffset = configRelogio.gmtOffset ?? 0;
|
const gmtOffset = configRelogio.gmtOffset ?? 0;
|
||||||
@@ -262,6 +267,7 @@
|
|||||||
let imagemId: Id<'_storage'> | undefined = undefined;
|
let imagemId: Id<'_storage'> | undefined = undefined;
|
||||||
if (imagemCapturada) {
|
if (imagemCapturada) {
|
||||||
try {
|
try {
|
||||||
|
etapaProcessamento = 'upload';
|
||||||
imagemId = await uploadImagem(imagemCapturada);
|
imagemId = await uploadImagem(imagemCapturada);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao fazer upload da imagem:', error);
|
console.error('Erro ao fazer upload da imagem:', error);
|
||||||
@@ -272,6 +278,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registrar ponto
|
// Registrar ponto
|
||||||
|
etapaProcessamento = 'registrando';
|
||||||
const resultado = await client.mutation(api.pontos.registrarPonto, {
|
const resultado = await client.mutation(api.pontos.registrarPonto, {
|
||||||
imagemId,
|
imagemId,
|
||||||
informacoesDispositivo,
|
informacoesDispositivo,
|
||||||
@@ -314,6 +321,7 @@
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao registrar ponto:', error);
|
console.error('Erro ao registrar ponto:', error);
|
||||||
aguardandoProcessamento = false;
|
aguardandoProcessamento = false;
|
||||||
|
etapaProcessamento = null;
|
||||||
let mensagemErro = 'Erro desconhecido ao registrar ponto';
|
let mensagemErro = 'Erro desconhecido ao registrar ponto';
|
||||||
let detalhesErro = 'Tente novamente em alguns instantes.';
|
let detalhesErro = 'Tente novamente em alguns instantes.';
|
||||||
|
|
||||||
@@ -392,6 +400,7 @@
|
|||||||
registrando = false;
|
registrando = false;
|
||||||
coletandoInfo = false;
|
coletandoInfo = false;
|
||||||
aguardandoProcessamento = false;
|
aguardandoProcessamento = false;
|
||||||
|
etapaProcessamento = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,7 +527,11 @@
|
|||||||
function confirmarRegistro() {
|
function confirmarRegistro() {
|
||||||
mostrandoModalConfirmacao = false;
|
mostrandoModalConfirmacao = false;
|
||||||
aguardandoProcessamento = true;
|
aguardandoProcessamento = true;
|
||||||
|
etapaProcessamento = 'coletando';
|
||||||
|
// Usar setTimeout para garantir que o modal de processamento apareça antes de iniciar o registro
|
||||||
|
setTimeout(() => {
|
||||||
registrarPonto();
|
registrarPonto();
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelarRegistro() {
|
function cancelarRegistro() {
|
||||||
@@ -855,20 +868,20 @@
|
|||||||
// Posicionamento dos modais
|
// Posicionamento dos modais
|
||||||
let modalPosition = $state<{ top: number; left: number } | null>(null);
|
let modalPosition = $state<{ top: number; left: number } | null>(null);
|
||||||
|
|
||||||
// Função para calcular a posição baseada no relógio sincronizado
|
// Função para calcular a posição baseada no card de registro de ponto
|
||||||
function calcularPosicaoModal() {
|
function calcularPosicaoModal() {
|
||||||
// Procurar pelo elemento do relógio sincronizado
|
// Procurar pelo elemento do card de registro de ponto
|
||||||
const relogioRef = document.getElementById('relogio-sincronizado-ref');
|
const cardRef = document.getElementById('card-registro-ponto-ref');
|
||||||
|
|
||||||
if (relogioRef) {
|
if (cardRef) {
|
||||||
const rect = relogioRef.getBoundingClientRect();
|
const rect = cardRef.getBoundingClientRect();
|
||||||
const viewportWidth = window.innerWidth;
|
const viewportWidth = window.innerWidth;
|
||||||
const viewportHeight = window.innerHeight;
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
// Posicionar o modal na mesma posição do relógio sincronizado
|
// Posicionar o modal na mesma posição do card de registro
|
||||||
// Centralizado horizontalmente no card do relógio
|
// Centralizado horizontalmente no card
|
||||||
const left = rect.left + (rect.width / 2);
|
const left = rect.left + (rect.width / 2);
|
||||||
// Posicionar abaixo do card do relógio com um pequeno espaçamento
|
// Posicionar abaixo do card com um pequeno espaçamento
|
||||||
const top = rect.bottom + 20;
|
const top = rect.bottom + 20;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -1009,7 +1022,7 @@
|
|||||||
|
|
||||||
<!-- Card de Registro de Ponto Modernizado -->
|
<!-- Card de Registro de Ponto Modernizado -->
|
||||||
<div class="card bg-gradient-to-br from-base-100 via-base-100 to-primary/5 border border-base-300 shadow-2xl max-w-2xl mx-auto">
|
<div class="card bg-gradient-to-br from-base-100 via-base-100 to-primary/5 border border-base-300 shadow-2xl max-w-2xl mx-auto">
|
||||||
<div class="card-body p-6">
|
<div id="card-registro-ponto-ref" class="card-body p-6">
|
||||||
<!-- Cabeçalho -->
|
<!-- Cabeçalho -->
|
||||||
<div class="flex items-center justify-center gap-3 mb-6">
|
<div class="flex items-center justify-center gap-3 mb-6">
|
||||||
<div class="p-2.5 bg-primary/10 rounded-xl">
|
<div class="p-2.5 bg-primary/10 rounded-xl">
|
||||||
@@ -1498,8 +1511,32 @@
|
|||||||
>
|
>
|
||||||
<div class="flex flex-col items-center gap-4 text-center">
|
<div class="flex flex-col items-center gap-4 text-center">
|
||||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||||
<h3 id="modal-aguardando-title" class="text-xl font-bold text-base-content">Processando Registro</h3>
|
<h3 id="modal-aguardando-title" class="text-xl font-bold text-base-content">
|
||||||
<p class="text-base-content/70">Por favor, aguarde enquanto processamos seu registro de ponto...</p>
|
{#if etapaProcessamento === 'coletando'}
|
||||||
|
Coletando Informações
|
||||||
|
{:else if etapaProcessamento === 'sincronizando'}
|
||||||
|
Sincronizando Horário
|
||||||
|
{:else if etapaProcessamento === 'upload'}
|
||||||
|
Enviando Foto
|
||||||
|
{:else if etapaProcessamento === 'registrando'}
|
||||||
|
Registrando Ponto
|
||||||
|
{:else}
|
||||||
|
Processando Registro
|
||||||
|
{/if}
|
||||||
|
</h3>
|
||||||
|
<p class="text-base-content/70">
|
||||||
|
{#if etapaProcessamento === 'coletando'}
|
||||||
|
Coletando informações do dispositivo e localização...
|
||||||
|
{:else if etapaProcessamento === 'sincronizando'}
|
||||||
|
Sincronizando o horário com o servidor...
|
||||||
|
{:else if etapaProcessamento === 'upload'}
|
||||||
|
Enviando a foto capturada para o servidor...
|
||||||
|
{:else if etapaProcessamento === 'registrando'}
|
||||||
|
Finalizando o registro de ponto no sistema...
|
||||||
|
{:else}
|
||||||
|
Por favor, aguarde enquanto processamos seu registro de ponto...
|
||||||
|
{/if}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1540,7 +1577,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-circle btn-ghost hover:bg-base-300"
|
class="btn btn-sm btn-circle btn-ghost hover:bg-base-300"
|
||||||
onclick={cancelarRegistro}
|
onclick={cancelarRegistro}
|
||||||
disabled={registrando}
|
disabled={registrando || aguardandoProcessamento}
|
||||||
>
|
>
|
||||||
<XCircle class="h-5 w-5" />
|
<XCircle class="h-5 w-5" />
|
||||||
</button>
|
</button>
|
||||||
@@ -1658,7 +1695,7 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-outline"
|
class="btn btn-outline"
|
||||||
onclick={cancelarRegistro}
|
onclick={cancelarRegistro}
|
||||||
disabled={registrando}
|
disabled={registrando || aguardandoProcessamento}
|
||||||
>
|
>
|
||||||
<XCircle class="h-5 w-5" />
|
<XCircle class="h-5 w-5" />
|
||||||
Cancelar
|
Cancelar
|
||||||
@@ -1666,11 +1703,11 @@
|
|||||||
<button
|
<button
|
||||||
class="btn btn-primary gap-2"
|
class="btn btn-primary gap-2"
|
||||||
onclick={confirmarRegistro}
|
onclick={confirmarRegistro}
|
||||||
disabled={registrando}
|
disabled={registrando || aguardandoProcessamento}
|
||||||
>
|
>
|
||||||
{#if registrando}
|
{#if registrando || aguardandoProcessamento}
|
||||||
<span class="loading loading-spinner loading-sm"></span>
|
<span class="loading loading-spinner loading-sm"></span>
|
||||||
Registrando...
|
Processando...
|
||||||
{:else}
|
{:else}
|
||||||
<CheckCircle2 class="h-5 w-5" />
|
<CheckCircle2 class="h-5 w-5" />
|
||||||
Confirmar Registro
|
Confirmar Registro
|
||||||
|
|||||||
Reference in New Issue
Block a user