[Parecer Juridico]

This commit is contained in:
luisfepsale
2025-10-28 09:56:35 -03:00
parent 9f75feb69a
commit 45ea53b364
8 changed files with 904 additions and 225 deletions
+330
View File
@@ -0,0 +1,330 @@
import { GlobalFunctions, TransferAreaProperties } from '@/GlobalFunctions';
import { apiService } from './api';
/**
* Interface para resposta do POST de parecer técnico
*/
export interface CreateOpinionResponse {
success: boolean;
id?: string;
file_url?: string;
file_url_melhoria?: string;
}
/**
* Interface para requisição de criação de parecer
*/
export interface CreateOpinionRequest {
titulo: string;
categoria: string;
instrucoes: string;
userEmail?: string;
estabelecimentoId?: number;
}
/**
* Interface para um parecer retornado pela API
*/
export interface OpinionRecord {
id: string;
estabelecimento_id: number;
user_email: string;
titulo: string;
categoria: string;
instrucoes: string;
file_url: string;
created_at: string;
file_url_melhoria: string;
}
/**
* Interface para parâmetros de paginação e busca
*/
export interface GetOpinionsParams {
page?: number;
per_page?: number;
search?: string;
userEmail?: string;
estabelecimentoId?: number;
}
/**
* Interface para resposta do GET de pareceres
*/
export interface GetOpinionsResponse {
data: OpinionRecord[];
total: number;
page: number;
per_page: number;
}
/**
* Serviço para gerenciamento de pareceres jurídicos
*/
class AgentService {
private readonly CREATE_OPINION_ENDPOINT = '/webhook/codex/gepam/parecer-tecnico';
private readonly GET_OPINIONS_ENDPOINT = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/get_parecer';
/**
* Cria um novo parecer técnico
*
* @param request - Dados do parecer
* @returns Promise com a resposta da API
*/
async createOpinion(request: CreateOpinionRequest): Promise<CreateOpinionResponse> {
const {
titulo,
categoria,
instrucoes,
userEmail,
estabelecimentoId
} = request;
// Usa valores do GlobalFunctions se não forem fornecidos
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
const estabId = estabelecimentoId || GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);
// Validações
if (!titulo || titulo.trim().length === 0) {
throw {
success: false,
message: 'Título do parecer é obrigatório',
};
}
if (!instrucoes || instrucoes.trim().length === 0) {
throw {
success: false,
message: 'Instruções são obrigatórias',
};
}
if (!email) {
throw {
success: false,
message: 'Email do usuário não fornecido',
};
}
if (!estabId) {
throw {
success: false,
message: 'ID do estabelecimento não fornecido',
};
}
// Log para debug
console.log('Criando parecer:', {
titulo,
categoria,
instrucoesLength: instrucoes.length,
userEmail: email,
estabelecimentoId: estabId,
});
try {
// Faz a requisição usando o serviço de API
const response = await apiService.post<CreateOpinionResponse>(
this.CREATE_OPINION_ENDPOINT,
{
user_email: email,
estabelecimento_id: estabId,
titulo: titulo.trim(),
categoria: categoria.trim(),
instrucoes: instrucoes.trim(),
}
);
console.log('Resposta da API (criar parecer):', response.data);
return response.data;
} catch (error: any) {
// Trata erros específicos
console.error('Erro ao criar parecer:', error);
throw {
success: false,
message: error.message || 'Erro ao criar parecer',
status: error.status,
};
}
}
/**
* Busca todos os pareceres do usuário com paginação e busca
*
* @param params - Parâmetros de paginação e busca
* @returns Promise com array de pareceres
*/
async getOpinions(params?: GetOpinionsParams): Promise<OpinionRecord[]> {
const {
page = 1,
per_page = 10,
search = '',
userEmail,
estabelecimentoId
} = params || {};
// Usa valores do GlobalFunctions se não forem fornecidos
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
const estabId = estabelecimentoId || GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);
if (!email) {
throw {
success: false,
message: 'Email do usuário não fornecido',
};
}
if (!estabId) {
throw {
success: false,
message: 'ID do estabelecimento não fornecido',
};
}
console.log('Buscando pareceres:', {
userEmail: email,
estabelecimentoId: estabId,
page,
per_page,
search,
});
try {
// Constrói a URL com parâmetros de query
const url = `${this.GET_OPINIONS_ENDPOINT}/${email}/${estabId}`;
const response = await apiService.get<OpinionRecord[]>(url, {
params: {
page,
per_page,
search,
},
});
console.log('Resposta da API (buscar pareceres):', response.data);
// A API retorna diretamente o array de pareceres
// Garante que sempre retorna um array
if (Array.isArray(response.data)) {
return response.data;
} else if (response.data && typeof response.data === 'object') {
// Se a resposta for um objeto, tenta encontrar o array dentro dele
console.warn('API retornou objeto em vez de array:', response.data);
if (Array.isArray((response.data as any).data)) {
return (response.data as any).data;
} else if (Array.isArray((response.data as any).opinions)) {
return (response.data as any).opinions;
}
}
// Se não conseguir extrair array, retorna vazio
console.warn('Não foi possível extrair array de pareceres da resposta');
return [];
} catch (error: any) {
console.error('Erro ao buscar pareceres:', error);
throw {
success: false,
message: error.message || 'Erro ao buscar pareceres',
status: error.status,
};
}
}
/**
* Faz download de um arquivo de parecer
*
* @param fileUrl - URL do arquivo a ser baixado
* @param fileName - Nome do arquivo para download
*/
async downloadOpinion(fileUrl: string, fileName: string): Promise<void> {
if (!fileUrl) {
throw {
success: false,
message: 'URL do arquivo não fornecida',
};
}
try {
// Cria um elemento <a> temporário para forçar o download
const link = document.createElement('a');
link.href = fileUrl;
link.download = fileName;
link.target = '_blank';
link.rel = 'noopener noreferrer';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
console.log('Download iniciado:', { fileUrl, fileName });
} catch (error: any) {
console.error('Erro ao fazer download:', error);
throw {
success: false,
message: error.message || 'Erro ao fazer download do arquivo',
};
}
}
/**
* Exclui um parecer técnico
*
* @param opinionId - ID do parecer a ser excluído
* @param userEmail - Email do usuário (opcional, usa GlobalFunctions se não fornecido)
* @returns Promise com a resposta da API
*/
async deleteOpinion(opinionId: string, userEmail?: string): Promise<{ success: boolean }> {
// Usa valores do GlobalFunctions se não forem fornecidos
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
if (!opinionId) {
throw {
success: false,
message: 'ID do parecer não fornecido',
};
}
if (!email) {
throw {
success: false,
message: 'Email do usuário não fornecido',
};
}
console.log('Excluindo parecer:', {
opinionId,
userEmail: email,
});
try {
// Constrói a URL com o user_email e id
const url = `/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/delete_parecer/${email}/${opinionId}`;
const response = await apiService.delete<{ success: boolean }[]>(url);
console.log('Resposta da API (excluir parecer):', response.data);
// A API retorna um array com { success: true }
if (Array.isArray(response.data) && response.data.length > 0) {
return response.data[0];
}
return { success: true };
} catch (error: any) {
console.error('Erro ao excluir parecer:', error);
throw {
success: false,
message: error.message || 'Erro ao excluir parecer',
status: error.status,
};
}
}
}
// Exporta instância única (Singleton)
export const agentService = new AgentService();
+76
View File
@@ -603,6 +603,82 @@ class ChatService {
}
}
/**
* Renomeia uma pasta existente
*
* @param folderId - ID da pasta a ser renomeada
* @param newName - Novo nome da pasta
* @param userEmail - Email do usuário (opcional)
* @returns Promise com o resultado da operação
*/
async renameFolder(folderId: string, newName: string, userEmail?: string): Promise<{ success: boolean; folder?: FolderRecord }> {
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
if (!email) {
throw {
success: false,
message: 'Email do usuário não fornecido',
};
}
if (!folderId || folderId.trim().length === 0) {
throw {
success: false,
message: 'ID da pasta não pode estar vazio',
};
}
if (!newName || newName.trim().length === 0) {
throw {
success: false,
message: 'Nome da pasta não pode estar vazio',
};
}
console.log('Renomeando pasta:', {
folderId,
newName,
userEmail: email,
});
try {
const response = await apiService.put<Array<{ success: boolean; user_email?: string; name?: string; id?: string }>>(
this.POST_FOLDER_ENDPOINT,
{
id: folderId,
user_email: email,
name: newName.trim(),
}
);
console.log('Resposta completa do PUT (renomear pasta):', response);
console.log('response.data:', response.data);
// A API retorna um array com um objeto: [{"success":true, "user_email": "...", "name": "...", "id": "..."}]
let result: { success: boolean; user_email?: string; name?: string; id?: string };
if (Array.isArray(response.data)) {
result = response.data[0];
console.log('API retornou array, usando primeiro elemento:', result);
} else {
result = response.data as any;
console.log('API retornou objeto direto:', result);
}
return {
success: result.success ?? true,
};
} catch (error: any) {
console.error('Erro ao renomear pasta:', error);
throw {
success: false,
message: error.message || 'Erro ao renomear pasta',
status: error.status,
};
}
}
/**
* Busca todos os chats e pastas do usuário
*
+31 -5
View File
@@ -11,9 +11,10 @@ export type ImageSize = '1024x1024' | '1024x1792' | '1792x1024';
*/
export interface ImageGenerationResponse {
success: boolean;
image_url: string; // URL da imagem gerada
image_generation_id: string;
message: string; // Descrição original
image_url?: string; // URL da imagem gerada (opcional quando há erro)
image_generation_id?: string; // ID da geração (opcional quando há erro)
message: string; // Descrição original ou mensagem de erro
code?: string; // Código de erro (ex: "server_error", "invalid_request")
}
/**
@@ -137,14 +138,39 @@ class ImageGenerationService {
}
);
// Verifica se a resposta indica erro
if (!response.data.success) {
throw {
success: false,
message: response.data.message || 'Erro ao gerar imagem',
code: response.data.code,
};
}
return response.data;
} catch (error: any) {
// Trata erros específicos
// Trata erros específicos da API
console.error('Erro na geração de imagem:', error);
// Se o erro já tem a estrutura esperada (veio da validação acima), repassa
if (error.success === false && error.message) {
throw error;
}
// Se o erro veio da requisição HTTP, tenta extrair a resposta da API
if (error.response?.data) {
const apiError = error.response.data;
throw {
success: false,
message: apiError.message || 'Erro ao gerar imagem',
code: apiError.code,
};
}
// Erro genérico
throw {
success: false,
message: error.message || 'Erro ao gerar imagem',
message: error.message || 'Erro ao gerar imagem. Tente novamente.',
status: error.status,
};
}