feat: enhance RegistroPonto and WebcamCapture components for improved data handling and user experience

- Added a refresh mechanism in the RegistroPonto component to ensure queries are updated after point registration, improving data accuracy.
- Expanded the WebcamCapture component to prevent multiple simultaneous play calls, enhancing video playback reliability.
- Updated the registro-pontos page to default the date range to the last 30 days for better visibility and user convenience.
- Introduced debug logging for queries and data handling to assist in development and troubleshooting.
This commit is contained in:
2025-11-22 23:57:05 -03:00
parent 90e81e4667
commit 467e04b605
5 changed files with 269 additions and 58 deletions

View File

@@ -791,6 +791,7 @@ export const registrarPonto = mutation({
export const listarRegistrosDia = query({
args: {
data: v.optional(v.string()), // YYYY-MM-DD, se não fornecido usa hoje
_refresh: v.optional(v.number()), // Parâmetro usado pelo frontend para forçar refresh
},
handler: async (ctx, args) => {
const usuario = await getCurrentUserFunction(ctx);
@@ -801,12 +802,22 @@ export const listarRegistrosDia = query({
const funcionarioId = usuario.funcionarioId; // Garantir que não é undefined
const data = args.data || new Date().toISOString().split('T')[0]!;
console.log('[listarRegistrosDia] Buscando registros:', { funcionarioId, data });
const registros = await ctx.db
.query('registrosPonto')
.withIndex('by_funcionario_data', (q) => q.eq('funcionarioId', funcionarioId).eq('data', data))
.order('asc')
.collect();
console.log('[listarRegistrosDia] Registros encontrados:', registros.length, registros.map(r => ({
_id: r._id,
tipo: r.tipo,
data: r.data,
hora: r.hora,
minuto: r.minuto
})));
return registros;
},
});
@@ -862,7 +873,7 @@ export const listarRegistrosPeriodo = query({
handler: async (ctx, args) => {
const usuario = await getCurrentUserFunction(ctx);
if (!usuario) {
// Retornar array vazio quando não autenticado
console.warn('[listarRegistrosPeriodo] Usuário não autenticado');
return [];
}
@@ -872,15 +883,27 @@ export const listarRegistrosPeriodo = query({
// Validar formato das datas
if (!args.dataInicio || !args.dataFim) {
console.warn('[listarRegistrosPeriodo] Datas não fornecidas');
return [];
}
// Validar formato YYYY-MM-DD
const dataInicioRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!dataInicioRegex.test(args.dataInicio) || !dataInicioRegex.test(args.dataFim)) {
console.warn('[listarRegistrosPeriodo] Formato de data inválido', {
dataInicio: args.dataInicio,
dataFim: args.dataFim
});
return [];
}
console.log('[listarRegistrosPeriodo] Buscando registros', {
dataInicio: args.dataInicio,
dataFim: args.dataFim,
funcionarioId: args.funcionarioId,
usuarioId: usuario._id
});
let registrosFiltrados;
// Se funcionário foi especificado, usar índice por funcionário e data (mais eficiente)
@@ -901,21 +924,41 @@ export const listarRegistrosPeriodo = query({
});
} else {
// Se não há funcionário especificado, buscar todos e filtrar (menos eficiente, mas necessário)
// Usar comparação de strings diretamente para datas no formato YYYY-MM-DD
const registros = await ctx.db
.query('registrosPonto')
.withIndex('by_data', (q) =>
q.gte('data', args.dataInicio).lte('data', args.dataFim)
)
.collect();
// Garantir que as datas estão no formato correto e filtrar novamente para garantir
registrosFiltrados = registros.filter((r) => {
// Comparação de strings funciona para formato YYYY-MM-DD
return r.data >= args.dataInicio && r.data <= args.dataFim;
});
try {
// Tentar usar índice por data primeiro
const registros = await ctx.db
.query('registrosPonto')
.withIndex('by_data', (q) =>
q.gte('data', args.dataInicio).lte('data', args.dataFim)
)
.collect();
console.log('[listarRegistrosPeriodo] Registros do índice by_data:', registros.length);
// Garantir que as datas estão no formato correto e filtrar novamente para garantir
registrosFiltrados = registros.filter((r) => {
// Comparação de strings funciona para formato YYYY-MM-DD
return r.data >= args.dataInicio && r.data <= args.dataFim;
});
console.log('[listarRegistrosPeriodo] Registros após filtro:', registrosFiltrados.length);
} catch (error) {
console.error('[listarRegistrosPeriodo] Erro ao buscar registros:', error);
// Fallback: buscar todos e filtrar manualmente
const todosRegistros = await ctx.db
.query('registrosPonto')
.collect();
registrosFiltrados = todosRegistros.filter((r) => {
return r.data >= args.dataInicio && r.data <= args.dataFim;
});
console.log('[listarRegistrosPeriodo] Fallback - registros encontrados:', registrosFiltrados.length);
}
}
console.log('[listarRegistrosPeriodo] Registros encontrados antes de buscar funcionários:', registrosFiltrados.length);
// Buscar informações dos funcionários
const funcionariosIds = new Set(registrosFiltrados.map((r) => r.funcionarioId));
const funcionarios = await Promise.all(
@@ -940,6 +983,8 @@ export const listarRegistrosPeriodo = query({
}
}
console.log('[listarRegistrosPeriodo] Total de registros a retornar:', registrosFiltrados.length);
return registrosFiltrados.map((registro) => {
const funcionario = funcionarios.find((f) => f?._id === registro.funcionarioId);
const chave = `${registro.funcionarioId}-${registro.data}`;
@@ -1225,11 +1270,19 @@ export const obterHistoricoESaldoDia = query({
args: {
funcionarioId: v.id('funcionarios'),
data: v.string(), // YYYY-MM-DD
_refresh: v.optional(v.number()), // Parâmetro usado pelo frontend para forçar refresh
},
handler: async (ctx, args) => {
const usuario = await getCurrentUserFunction(ctx);
if (!usuario || !usuario.funcionarioId) {
throw new Error('Usuário não autenticado');
console.warn('[obterHistoricoESaldoDia] Usuário não autenticado ou sem funcionarioId');
// Retornar dados vazios em vez de lançar erro
return {
registros: [],
cargaHorariaDiaria: 0,
horasTrabalhadas: 0,
saldoMinutos: 0,
};
}
// Verificar se é o próprio funcionário ou tem permissão
@@ -1245,6 +1298,11 @@ export const obterHistoricoESaldoDia = query({
)
.order('asc')
.collect();
console.log('[obterHistoricoESaldoDia] Registros encontrados:', registros.length, {
funcionarioId: args.funcionarioId,
data: args.data
});
// Buscar configuração de ponto
const config = await ctx.db