Registro de Pontos

Gerencie e visualize os registros de ponto dos funcionários com informações detalhadas e relatórios

{#if estatisticas}

Total de Registros

{estatisticas.totalRegistros}

Funcionários

{estatisticas.totalFuncionarios}

{estatisticas.totalRegistros > 0 ? ((estatisticas.dentroDoPrazo / estatisticas.totalRegistros) * 100).toFixed(1) : 0}% dentro do prazo Ativo
{/if}
{#if estatisticas}

Total de Registros

{estatisticas.totalRegistros}

Dentro do Prazo

{estatisticas.dentroDoPrazo}

{estatisticas.totalRegistros > 0 ? ((estatisticas.dentroDoPrazo / estatisticas.totalRegistros) * 100).toFixed(1) : 0}% do total

Fora do Prazo

{estatisticas.foraDoPrazo}

{estatisticas.totalRegistros > 0 ? ((estatisticas.foraDoPrazo / estatisticas.totalRegistros) * 100).toFixed(1) : 0}% do total

Funcionários

{estatisticas.totalFuncionarios}

{estatisticas.funcionariosDentroPrazo} dentro, {estatisticas.funcionariosForaPrazo} fora

{/if}

Visão Geral das Estatísticas

{#if estatisticasQuery === undefined || estatisticasQuery?.isLoading}
Carregando estatísticas...
{:else if estatisticasQuery?.error}

Erro ao carregar estatísticas

{estatisticasQuery.error?.message || String(estatisticasQuery.error) || 'Erro desconhecido'}
{:else if !estatisticas || !chartData}

Nenhuma estatística disponível

{:else} {/if}

Filtros de Busca

{#if statusFiltro !== 'todos' || localizacaoFiltro !== 'todos'}

{registrosFiltrados.length} registro(s) encontrado(s) com os filtros aplicados {#if registros.length !== registrosFiltrados.length} (de {registros.length} total) {/if}

{/if}

Registros de Ponto

{#if funcionarioIdFiltro || dataInicio || dataFim}
{#if funcionarioIdFiltro && funcionarioSelecionadoNome}
{funcionarioSelecionadoNome}
{/if} {#if dataInicio}
De: {formatarDataDDMMAAAA(dataInicio)}
{/if} {#if dataFim}
Até: {formatarDataDDMMAAAA(dataFim)}
{/if}
{/if}
{#if registrosQuery === undefined || registrosQuery?.isLoading}
Carregando registros... Aguarde um momento
{:else if registrosQuery?.error}

Erro ao carregar registros

{registrosQuery.error?.message || String(registrosQuery.error) || 'Erro desconhecido'}
{:else if !registrosQuery?.data}
Aguardando dados da consulta...
{:else if registros.length === 0}

Nenhum registro encontrado

Período: {formatarDataDDMMAAAA(dataInicio)} até {formatarDataDDMMAAAA(dataFim)}

{#if funcionarioIdFiltro && funcionarioSelecionadoNome}

Funcionário: {funcionarioSelecionadoNome}

{/if}

Tente ajustar os filtros para encontrar registros.

{:else if registrosAgrupados.length === 0}

Registros encontrados, mas não foi possível agrupá-los

Total de registros: {registros.length}
{:else}
{#each registrosAgrupados as grupo}

{grupo.funcionario?.nome || 'Funcionário não encontrado'}

{#if grupo.funcionario?.matricula}

Matrícula: {grupo.funcionario.matricula}

{/if}
{#if grupo.funcionario?.descricaoCargo}

{grupo.funcionario.descricaoCargo}

{/if}
{#key grupo.funcionarioId} {@const bancoHorasQuery = useQuery(api.pontos.obterBancoHorasFuncionario, { funcionarioId: grupo.funcionarioId })} {@const bancoHoras = bancoHorasQuery?.data} {@const saldoAcumulado = bancoHoras?.saldoAcumuladoMinutos ?? 0} {@const saldoPositivo = saldoAcumulado >= 0} {#if bancoHoras}
{#if saldoPositivo} {:else} {/if}

Banco de Horas

{formatarSaldoHoras(saldoAcumulado)}

{/if} {/key}
{#each Object.values(grupo.registrosPorData) as grupoData, dataIndex} {@const totalRegistros = grupoData.registros.length} {@const dataFormatada = formatarDataDDMMAAAA(grupoData.data)} {@const saldosParciais = calcularSaldosParciais(grupoData.registros)} {@const isUltimoDia = dataIndex === Object.values(grupo.registrosPorData).length - 1} {#each grupoData.registros as registro, index} {@const saldoParcial = saldosParciais.get(index)} {#if index === 0} {/if} {/each} {/each}
Data Tipo Horário Saldo Parcial Saldo Diário Localização Status Ações
{dataFormatada} {config ? getTipoRegistroLabel(registro.tipo, { nomeEntrada: config.nomeEntrada, nomeSaidaAlmoco: config.nomeSaidaAlmoco, nomeRetornoAlmoco: config.nomeRetornoAlmoco, nomeSaida: config.nomeSaida }) : getTipoRegistroLabel(registro.tipo)} {formatarHoraPonto(registro.hora, registro.minuto)} {#if saldoParcial} Par {saldoParcial.parNumero}: +{saldoParcial.horas}h {saldoParcial.minutos}min {:else} - {/if} {#if grupoData.saldoDiarioComparativo} {:else if grupoData.saldoDiario} {:else} - {/if} {registro.dentroDoPrazo ? '✓ Dentro do Prazo' : '✗ Fora do Prazo'}
{/each}
{/if}
{#if mostrarModalImpressao && funcionarioParaImprimir} { mostrarModalImpressao = false; funcionarioParaImprimir = ''; }} onGenerate={gerarPDFComSelecao} /> {/if} {#if mostrarModalDetalhes && registroDetalhesId} {@const registroDetalhesQuery = useQuery( api.pontos.obterRegistro, registroDetalhesId ? { registroId: registroDetalhesId } : 'skip' )} {@const registroDetalhes = registroDetalhesQuery?.data} e.target === e.currentTarget && fecharModalDetalhes()} > {/if}