refactor: improve data handling and UI feedback in LGPD-related components; enhance error handling and consent term display
This commit is contained in:
@@ -451,10 +451,10 @@
|
|||||||
href={resolve('/abrir-chamado')}
|
href={resolve('/abrir-chamado')}
|
||||||
class="link link-hover hover:text-primary transition-colors">Suporte</a
|
class="link link-hover hover:text-primary transition-colors">Suporte</a
|
||||||
>
|
>
|
||||||
<span class="text-base-content/30">•</span>
|
<span class="text-base-content/30">•</span>
|
||||||
<a href={resolve('/privacidade')} class="link link-hover hover:text-primary transition-colors"
|
<a href={resolve('/privacidade')} class="link link-hover hover:text-primary transition-colors"
|
||||||
>Privacidade</a
|
>Privacidade</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 flex items-center gap-3">
|
<div class="mt-2 flex items-center gap-3">
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
|
|||||||
@@ -30,7 +30,17 @@ let observacoes = $state('');
|
|||||||
let carregando = $state(false);
|
let carregando = $state(false);
|
||||||
|
|
||||||
const client = useConvexClient();
|
const client = useConvexClient();
|
||||||
const minhasSolicitacoes = useQuery(api.lgpd.listarMinhasSolicitacoes, {});
|
const minhasSolicitacoesQuery = useQuery(api.lgpd.listarMinhasSolicitacoes, {});
|
||||||
|
|
||||||
|
// Garantir que sempre seja um array ou undefined
|
||||||
|
const minhasSolicitacoes = $derived(
|
||||||
|
minhasSolicitacoesQuery === undefined || minhasSolicitacoesQuery === null
|
||||||
|
? undefined
|
||||||
|
: Array.isArray(minhasSolicitacoesQuery)
|
||||||
|
? minhasSolicitacoesQuery
|
||||||
|
: []
|
||||||
|
);
|
||||||
|
|
||||||
const exportarDados = useQuery(api.lgpd.exportarDadosUsuario, {});
|
const exportarDados = useQuery(api.lgpd.exportarDadosUsuario, {});
|
||||||
|
|
||||||
const tiposSolicitacao: Array<{ valor: TipoSolicitacao; label: string; descricao: string }> = [
|
const tiposSolicitacao: Array<{ valor: TipoSolicitacao; label: string; descricao: string }> = [
|
||||||
@@ -241,16 +251,26 @@ let carregando = $state(false);
|
|||||||
<!-- Minhas Solicitações -->
|
<!-- Minhas Solicitações -->
|
||||||
<div class="card bg-base-100 shadow-xl">
|
<div class="card bg-base-100 shadow-xl">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="card-title text-2xl mb-4">Minhas Solicitações</h2>
|
<div class="flex items-center justify-between mb-4">
|
||||||
|
<h2 class="card-title text-2xl">Minhas Solicitações</h2>
|
||||||
|
{#if minhasSolicitacoes && Array.isArray(minhasSolicitacoes)}
|
||||||
|
<div class="badge badge-outline">
|
||||||
|
{minhasSolicitacoes.length} solicitação{minhasSolicitacoes.length !== 1 ? 'ões' : ''}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if minhasSolicitacoes === undefined}
|
{#if minhasSolicitacoes === undefined || minhasSolicitacoes === null}
|
||||||
<div class="flex justify-center items-center py-10">
|
<div class="flex justify-center items-center py-10">
|
||||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||||
</div>
|
</div>
|
||||||
{:else if minhasSolicitacoes.length === 0}
|
{:else if !Array.isArray(minhasSolicitacoes) || minhasSolicitacoes.length === 0}
|
||||||
<div class="text-center py-10">
|
<div class="text-center py-10">
|
||||||
<FileText class="h-16 w-16 text-base-content/30 mx-auto mb-4" />
|
<FileText class="h-16 w-16 text-base-content/30 mx-auto mb-4" />
|
||||||
<p class="text-base-content/60">Nenhuma solicitação encontrada</p>
|
<p class="text-base-content/60">Nenhuma solicitação encontrada</p>
|
||||||
|
<p class="text-xs text-base-content/40 mt-2">
|
||||||
|
Suas solicitações aparecerão aqui após serem criadas
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
|
|||||||
@@ -32,10 +32,14 @@
|
|||||||
let termoBusca = $state('');
|
let termoBusca = $state('');
|
||||||
|
|
||||||
const client = useConvexClient();
|
const client = useConvexClient();
|
||||||
const solicitacoes = useQuery(api.lgpd.listarSolicitacoes, {
|
|
||||||
|
// Query reativa que atualiza quando os filtros mudam
|
||||||
|
const solicitacoesQuery = $derived({
|
||||||
status: statusFiltro || undefined,
|
status: statusFiltro || undefined,
|
||||||
tipo: tipoFiltro || undefined
|
tipo: tipoFiltro || undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const solicitacoes = useQuery(api.lgpd.listarSolicitacoes, solicitacoesQuery);
|
||||||
|
|
||||||
let solicitacaoSelecionada = $state<string | null>(null);
|
let solicitacaoSelecionada = $state<string | null>(null);
|
||||||
let resposta = $state('');
|
let resposta = $state('');
|
||||||
@@ -85,15 +89,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function filtrarSolicitacoes() {
|
function filtrarSolicitacoes() {
|
||||||
if (!solicitacoes) return [];
|
// Verificar se solicitacoes existe e é um array
|
||||||
if (!termoBusca) return solicitacoes;
|
if (!solicitacoes || !Array.isArray(solicitacoes)) return [];
|
||||||
|
|
||||||
|
// Se não há termo de busca, retorna todas as solicitações
|
||||||
|
if (!termoBusca || termoBusca.trim() === '') return solicitacoes;
|
||||||
|
|
||||||
const busca = termoBusca.toLowerCase();
|
// Filtrar por termo de busca
|
||||||
|
const busca = termoBusca.toLowerCase().trim();
|
||||||
return solicitacoes.filter(
|
return solicitacoes.filter(
|
||||||
(s) =>
|
(s) =>
|
||||||
s.usuarioNome.toLowerCase().includes(busca) ||
|
(s.usuarioNome?.toLowerCase().includes(busca) ?? false) ||
|
||||||
s.usuarioEmail.toLowerCase().includes(busca) ||
|
(s.usuarioEmail?.toLowerCase().includes(busca) ?? false) ||
|
||||||
(s.usuarioMatricula?.toLowerCase().includes(busca) ?? false)
|
(s.usuarioMatricula?.toLowerCase().includes(busca) ?? false) ||
|
||||||
|
(getTipoLabel(s.tipo).toLowerCase().includes(busca)) ||
|
||||||
|
(getStatusBadge(s.status).label.toLowerCase().includes(busca))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,16 +203,52 @@
|
|||||||
<!-- Lista de Solicitações -->
|
<!-- Lista de Solicitações -->
|
||||||
<div class="card bg-base-100 shadow-xl">
|
<div class="card bg-base-100 shadow-xl">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="card-title text-2xl mb-4">Solicitações</h2>
|
<div class="flex items-center justify-between mb-4">
|
||||||
|
<h2 class="card-title text-2xl">Solicitações</h2>
|
||||||
|
{#if solicitacoes && Array.isArray(solicitacoes)}
|
||||||
|
<div class="badge badge-outline">
|
||||||
|
Total: {solicitacoes.length} | Exibindo: {solicitacoesFiltradas.length}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if solicitacoes === undefined}
|
{#if solicitacoes === undefined || solicitacoes === null}
|
||||||
<div class="flex justify-center items-center py-20">
|
<div class="flex justify-center items-center py-20">
|
||||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||||
</div>
|
</div>
|
||||||
{:else if solicitacoesFiltradas.length === 0}
|
{:else if !Array.isArray(solicitacoes) || solicitacoes.length === 0}
|
||||||
<div class="text-center py-10">
|
<div class="text-center py-10">
|
||||||
<FileText class="h-16 w-16 text-base-content/30 mx-auto mb-4" />
|
<FileText class="h-16 w-16 text-base-content/30 mx-auto mb-4" />
|
||||||
<p class="text-base-content/60">Nenhuma solicitação encontrada</p>
|
<p class="text-base-content/60">
|
||||||
|
{#if statusFiltro || tipoFiltro}
|
||||||
|
Nenhuma solicitação encontrada com os filtros aplicados
|
||||||
|
{:else}
|
||||||
|
Nenhuma solicitação encontrada
|
||||||
|
{/if}
|
||||||
|
</p>
|
||||||
|
{#if statusFiltro || tipoFiltro}
|
||||||
|
<button
|
||||||
|
onclick={() => {
|
||||||
|
statusFiltro = null;
|
||||||
|
tipoFiltro = null;
|
||||||
|
termoBusca = '';
|
||||||
|
}}
|
||||||
|
class="btn btn-sm btn-outline mt-4"
|
||||||
|
>
|
||||||
|
Limpar Filtros
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{:else if solicitacoesFiltradas.length === 0 && termoBusca}
|
||||||
|
<div class="text-center py-10">
|
||||||
|
<Search class="h-16 w-16 text-base-content/30 mx-auto mb-4" />
|
||||||
|
<p class="text-base-content/60">Nenhuma solicitação encontrada com o termo "{termoBusca}"</p>
|
||||||
|
<button
|
||||||
|
onclick={() => (termoBusca = '')}
|
||||||
|
class="btn btn-sm btn-outline mt-4"
|
||||||
|
>
|
||||||
|
Limpar Busca
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
@@ -230,6 +276,23 @@
|
|||||||
<div>
|
<div>
|
||||||
<span class="font-semibold">E-mail:</span> {solicitacao.usuarioEmail}
|
<span class="font-semibold">E-mail:</span> {solicitacao.usuarioEmail}
|
||||||
</div>
|
</div>
|
||||||
|
{#if solicitacao.consentimentoTermo}
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="font-semibold">Termo de Consentimento:</span>
|
||||||
|
<span class="badge badge-success badge-sm">Aceito</span>
|
||||||
|
<span class="text-xs text-base-content/60">
|
||||||
|
(v.{solicitacao.consentimentoTermo.versao} em{' '}
|
||||||
|
{format(new Date(solicitacao.consentimentoTermo.aceitoEm), 'dd/MM/yyyy', {
|
||||||
|
locale: ptBR
|
||||||
|
})})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="font-semibold">Termo de Consentimento:</span>
|
||||||
|
<span class="badge badge-warning badge-sm">Não aceito</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<div>
|
<div>
|
||||||
<span class="font-semibold">Criada em:</span>{' '}
|
<span class="font-semibold">Criada em:</span>{' '}
|
||||||
{format(new Date(solicitacao.criadoEm), "dd/MM/yyyy 'às' HH:mm", {
|
{format(new Date(solicitacao.criadoEm), "dd/MM/yyyy 'às' HH:mm", {
|
||||||
|
|||||||
2
packages/backend/convex/_generated/api.d.ts
vendored
2
packages/backend/convex/_generated/api.d.ts
vendored
@@ -69,6 +69,7 @@ import type * as tables_enderecos from "../tables/enderecos.js";
|
|||||||
import type * as tables_ferias from "../tables/ferias.js";
|
import type * as tables_ferias from "../tables/ferias.js";
|
||||||
import type * as tables_flows from "../tables/flows.js";
|
import type * as tables_flows from "../tables/flows.js";
|
||||||
import type * as tables_funcionarios from "../tables/funcionarios.js";
|
import type * as tables_funcionarios from "../tables/funcionarios.js";
|
||||||
|
import type * as tables_lgpdTables from "../tables/lgpdTables.js";
|
||||||
import type * as tables_licencas from "../tables/licencas.js";
|
import type * as tables_licencas from "../tables/licencas.js";
|
||||||
import type * as tables_pedidos from "../tables/pedidos.js";
|
import type * as tables_pedidos from "../tables/pedidos.js";
|
||||||
import type * as tables_ponto from "../tables/ponto.js";
|
import type * as tables_ponto from "../tables/ponto.js";
|
||||||
@@ -155,6 +156,7 @@ declare const fullApi: ApiFromModules<{
|
|||||||
"tables/ferias": typeof tables_ferias;
|
"tables/ferias": typeof tables_ferias;
|
||||||
"tables/flows": typeof tables_flows;
|
"tables/flows": typeof tables_flows;
|
||||||
"tables/funcionarios": typeof tables_funcionarios;
|
"tables/funcionarios": typeof tables_funcionarios;
|
||||||
|
"tables/lgpdTables": typeof tables_lgpdTables;
|
||||||
"tables/licencas": typeof tables_licencas;
|
"tables/licencas": typeof tables_licencas;
|
||||||
"tables/pedidos": typeof tables_pedidos;
|
"tables/pedidos": typeof tables_pedidos;
|
||||||
"tables/ponto": typeof tables_ponto;
|
"tables/ponto": typeof tables_ponto;
|
||||||
|
|||||||
@@ -311,26 +311,37 @@ export const listarMinhasSolicitacoes = query({
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let solicitacoes = await ctx.db
|
try {
|
||||||
.query('solicitacoesLGPD')
|
let solicitacoes = await ctx.db
|
||||||
.withIndex('by_usuario', (q) => q.eq('usuarioId', usuario._id))
|
.query('solicitacoesLGPD')
|
||||||
.order('desc')
|
.withIndex('by_usuario', (q) => q.eq('usuarioId', usuario._id))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if (args.status) {
|
// Filtrar por status se especificado
|
||||||
solicitacoes = solicitacoes.filter((s) => s.status === args.status);
|
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(),
|
criadoEm: v.number(),
|
||||||
prazoResposta: v.number(),
|
prazoResposta: v.number(),
|
||||||
respondidoEm: v.union(v.number(), v.null()),
|
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) => {
|
handler: async (ctx, args) => {
|
||||||
@@ -382,52 +402,137 @@ export const listarSolicitacoes = query({
|
|||||||
// Verificar se é TI (simplificado - pode melhorar com verificação de role)
|
// Verificar se é TI (simplificado - pode melhorar com verificação de role)
|
||||||
// Por enquanto, qualquer usuário autenticado pode ver (será melhorado)
|
// 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) {
|
if (args.status) {
|
||||||
solicitacoes = solicitacoes.filter((s) => s.status === args.status);
|
solicitacoes = solicitacoes.filter((s) => s.status === args.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filtrar por tipo
|
||||||
if (args.tipo) {
|
if (args.tipo) {
|
||||||
solicitacoes = solicitacoes.filter((s) => s.tipo === 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) {
|
if (args.limite) {
|
||||||
solicitacoes = solicitacoes.slice(0, 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
|
// Enriquecer com dados do usuário
|
||||||
const resultado = await Promise.all(
|
// Usar Promise.allSettled para garantir que todas as solicitações sejam processadas,
|
||||||
solicitacoes.map(async (s) => {
|
// mesmo se houver erro ao buscar dados de algum usuário
|
||||||
const usuarioSolicitante = await ctx.db.get(s.usuarioId);
|
const resultados = await Promise.allSettled(
|
||||||
let matricula: string | null = null;
|
solicitacoes.map(async (s): Promise<SolicitacaoEnriquecida> => {
|
||||||
|
try {
|
||||||
|
const usuarioSolicitante = await ctx.db.get(s.usuarioId);
|
||||||
|
let matricula: string | null = null;
|
||||||
|
|
||||||
if (usuarioSolicitante?.funcionarioId) {
|
if (usuarioSolicitante?.funcionarioId) {
|
||||||
const funcionario = await ctx.db.get(usuarioSolicitante.funcionarioId);
|
const funcionario = await ctx.db.get(usuarioSolicitante.funcionarioId);
|
||||||
matricula = funcionario?.matricula ?? null;
|
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;
|
return resultado;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user