refactor: improve data handling and UI feedback in LGPD-related components; enhance error handling and consent term display
This commit is contained in:
@@ -311,26 +311,37 @@ export const listarMinhasSolicitacoes = query({
|
||||
return [];
|
||||
}
|
||||
|
||||
let solicitacoes = await ctx.db
|
||||
.query('solicitacoesLGPD')
|
||||
.withIndex('by_usuario', (q) => q.eq('usuarioId', usuario._id))
|
||||
.order('desc')
|
||||
.collect();
|
||||
try {
|
||||
let solicitacoes = await ctx.db
|
||||
.query('solicitacoesLGPD')
|
||||
.withIndex('by_usuario', (q) => q.eq('usuarioId', usuario._id))
|
||||
.collect();
|
||||
|
||||
if (args.status) {
|
||||
solicitacoes = solicitacoes.filter((s) => s.status === args.status);
|
||||
// Filtrar por status se especificado
|
||||
if (args.status) {
|
||||
solicitacoes = solicitacoes.filter((s) => s.status === args.status);
|
||||
}
|
||||
|
||||
// Ordenar por data de criação (mais recentes primeiro)
|
||||
solicitacoes.sort((a, b) => b.criadoEm - a.criadoEm);
|
||||
|
||||
const resultado = solicitacoes.map((s) => ({
|
||||
_id: s._id,
|
||||
tipo: s.tipo,
|
||||
status: s.status,
|
||||
criadoEm: s.criadoEm,
|
||||
prazoResposta: s.prazoResposta,
|
||||
respondidoEm: s.respondidoEm ?? null,
|
||||
resposta: s.resposta ?? null,
|
||||
arquivoResposta: s.arquivoResposta ? s.arquivoResposta.toString() : null
|
||||
}));
|
||||
|
||||
console.log(`[listarMinhasSolicitacoes] Usuário: ${usuario._id}, Solicitações encontradas: ${resultado.length}`);
|
||||
return resultado;
|
||||
} catch (error) {
|
||||
console.error('[listarMinhasSolicitacoes] Erro ao listar minhas solicitações:', error);
|
||||
return [];
|
||||
}
|
||||
|
||||
return solicitacoes.map((s) => ({
|
||||
_id: s._id,
|
||||
tipo: s.tipo,
|
||||
status: s.status,
|
||||
criadoEm: s.criadoEm,
|
||||
prazoResposta: s.prazoResposta,
|
||||
respondidoEm: s.respondidoEm ?? null,
|
||||
resposta: s.resposta ?? null,
|
||||
arquivoResposta: s.arquivoResposta ? s.arquivoResposta.toString() : null
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -370,7 +381,16 @@ export const listarSolicitacoes = query({
|
||||
criadoEm: v.number(),
|
||||
prazoResposta: v.number(),
|
||||
respondidoEm: v.union(v.number(), v.null()),
|
||||
respondidoPorNome: v.union(v.string(), v.null())
|
||||
respondidoPorNome: v.union(v.string(), v.null()),
|
||||
consentimentoTermo: v.union(
|
||||
v.object({
|
||||
aceito: v.boolean(),
|
||||
versao: v.string(),
|
||||
aceitoEm: v.number(),
|
||||
revogadoEm: v.union(v.number(), v.null())
|
||||
}),
|
||||
v.null()
|
||||
)
|
||||
})
|
||||
),
|
||||
handler: async (ctx, args) => {
|
||||
@@ -382,52 +402,137 @@ export const listarSolicitacoes = query({
|
||||
// Verificar se é TI (simplificado - pode melhorar com verificação de role)
|
||||
// Por enquanto, qualquer usuário autenticado pode ver (será melhorado)
|
||||
|
||||
let solicitacoes = await ctx.db.query('solicitacoesLGPD').order('desc').collect();
|
||||
// Buscar TODAS as solicitações sem filtros iniciais
|
||||
let solicitacoes = await ctx.db.query('solicitacoesLGPD').collect();
|
||||
|
||||
// Filtrar por status
|
||||
if (args.status) {
|
||||
solicitacoes = solicitacoes.filter((s) => s.status === args.status);
|
||||
}
|
||||
|
||||
// Filtrar por tipo
|
||||
if (args.tipo) {
|
||||
solicitacoes = solicitacoes.filter((s) => s.tipo === args.tipo);
|
||||
}
|
||||
|
||||
// Ordenar por data de criação (mais recentes primeiro)
|
||||
solicitacoes.sort((a, b) => b.criadoEm - a.criadoEm);
|
||||
|
||||
// Aplicar limite se especificado
|
||||
if (args.limite) {
|
||||
solicitacoes = solicitacoes.slice(0, args.limite);
|
||||
}
|
||||
|
||||
// Tipo do resultado enriquecido
|
||||
type SolicitacaoEnriquecida = {
|
||||
_id: Id<'solicitacoesLGPD'>;
|
||||
tipo: string;
|
||||
status: string;
|
||||
usuarioNome: string;
|
||||
usuarioEmail: string;
|
||||
usuarioMatricula: string | null;
|
||||
criadoEm: number;
|
||||
prazoResposta: number;
|
||||
respondidoEm: number | null;
|
||||
respondidoPorNome: string | null;
|
||||
consentimentoTermo: {
|
||||
aceito: boolean;
|
||||
versao: string;
|
||||
aceitoEm: number;
|
||||
revogadoEm: number | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
// Enriquecer com dados do usuário
|
||||
const resultado = await Promise.all(
|
||||
solicitacoes.map(async (s) => {
|
||||
const usuarioSolicitante = await ctx.db.get(s.usuarioId);
|
||||
let matricula: string | null = null;
|
||||
// Usar Promise.allSettled para garantir que todas as solicitações sejam processadas,
|
||||
// mesmo se houver erro ao buscar dados de algum usuário
|
||||
const resultados = await Promise.allSettled(
|
||||
solicitacoes.map(async (s): Promise<SolicitacaoEnriquecida> => {
|
||||
try {
|
||||
const usuarioSolicitante = await ctx.db.get(s.usuarioId);
|
||||
let matricula: string | null = null;
|
||||
|
||||
if (usuarioSolicitante?.funcionarioId) {
|
||||
const funcionario = await ctx.db.get(usuarioSolicitante.funcionarioId);
|
||||
matricula = funcionario?.matricula ?? null;
|
||||
if (usuarioSolicitante?.funcionarioId) {
|
||||
const funcionario = await ctx.db.get(usuarioSolicitante.funcionarioId);
|
||||
matricula = funcionario?.matricula ?? null;
|
||||
}
|
||||
|
||||
let respondidoPorNome: string | null = null;
|
||||
if (s.respondidoPor) {
|
||||
const respondente = await ctx.db.get(s.respondidoPor);
|
||||
respondidoPorNome = respondente?.nome ?? null;
|
||||
}
|
||||
|
||||
// Buscar consentimento do termo de uso
|
||||
let consentimentoTermo: {
|
||||
aceito: boolean;
|
||||
versao: string;
|
||||
aceitoEm: number;
|
||||
revogadoEm: number | null;
|
||||
} | null = null;
|
||||
|
||||
if (usuarioSolicitante) {
|
||||
try {
|
||||
const consentimento = await ctx.db
|
||||
.query('consentimentos')
|
||||
.withIndex('by_usuario_tipo', (q) =>
|
||||
q.eq('usuarioId', usuarioSolicitante._id).eq('tipo', 'termo_uso')
|
||||
)
|
||||
.order('desc')
|
||||
.first();
|
||||
|
||||
if (consentimento && consentimento.aceito && !consentimento.revogadoEm) {
|
||||
consentimentoTermo = {
|
||||
aceito: consentimento.aceito,
|
||||
versao: consentimento.versao,
|
||||
aceitoEm: consentimento.aceitoEm,
|
||||
revogadoEm: consentimento.revogadoEm ?? null
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
// Se houver erro ao buscar consentimento, continua sem ele
|
||||
console.error('Erro ao buscar consentimento:', error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
_id: s._id,
|
||||
tipo: s.tipo,
|
||||
status: s.status,
|
||||
usuarioNome: usuarioSolicitante?.nome ?? 'Usuário Desconhecido',
|
||||
usuarioEmail: usuarioSolicitante?.email ?? '',
|
||||
usuarioMatricula: matricula,
|
||||
criadoEm: s.criadoEm,
|
||||
prazoResposta: s.prazoResposta,
|
||||
respondidoEm: s.respondidoEm ?? null,
|
||||
respondidoPorNome,
|
||||
consentimentoTermo
|
||||
};
|
||||
} catch (error) {
|
||||
// Se houver erro ao processar uma solicitação, retorna com dados mínimos
|
||||
console.error('Erro ao processar solicitação:', s._id, error);
|
||||
return {
|
||||
_id: s._id,
|
||||
tipo: s.tipo,
|
||||
status: s.status,
|
||||
usuarioNome: 'Erro ao carregar',
|
||||
usuarioEmail: '',
|
||||
usuarioMatricula: null,
|
||||
criadoEm: s.criadoEm,
|
||||
prazoResposta: s.prazoResposta,
|
||||
respondidoEm: s.respondidoEm ?? null,
|
||||
respondidoPorNome: null,
|
||||
consentimentoTermo: null
|
||||
};
|
||||
}
|
||||
|
||||
let respondidoPorNome: string | null = null;
|
||||
if (s.respondidoPor) {
|
||||
const respondente = await ctx.db.get(s.respondidoPor);
|
||||
respondidoPorNome = respondente?.nome ?? null;
|
||||
}
|
||||
|
||||
return {
|
||||
_id: s._id,
|
||||
tipo: s.tipo,
|
||||
status: s.status,
|
||||
usuarioNome: usuarioSolicitante?.nome ?? 'Usuário Desconhecido',
|
||||
usuarioEmail: usuarioSolicitante?.email ?? '',
|
||||
usuarioMatricula: matricula,
|
||||
criadoEm: s.criadoEm,
|
||||
prazoResposta: s.prazoResposta,
|
||||
respondidoEm: s.respondidoEm ?? null,
|
||||
respondidoPorNome
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// Filtrar apenas resultados bem-sucedidos e converter para o tipo correto
|
||||
const resultado = resultados
|
||||
.filter((r): r is PromiseFulfilledResult<SolicitacaoEnriquecida> => r.status === 'fulfilled')
|
||||
.map((r) => r.value);
|
||||
|
||||
return resultado;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user