207 lines
6.0 KiB
TypeScript
207 lines
6.0 KiB
TypeScript
import { GlobalFunctions, TransferAreaProperties } from '@/GlobalFunctions';
|
|
import { apiService } from './api';
|
|
|
|
export interface CreateOpinionResponse {
|
|
success: boolean;
|
|
id?: string;
|
|
file_url?: string;
|
|
file_url_melhoria?: string;
|
|
}
|
|
|
|
export interface CreateOpinionRequest {
|
|
titulo: string;
|
|
categoria: string;
|
|
instrucoes: string;
|
|
userEmail?: string;
|
|
estabelecimentoId?: number;
|
|
}
|
|
|
|
export type OpinionStatus = 'processando' | 'concluido' | 'erro';
|
|
|
|
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;
|
|
status?: OpinionStatus;
|
|
isLocalPending?: boolean;
|
|
}
|
|
|
|
export interface GetOpinionsParams {
|
|
page?: number;
|
|
per_page?: number;
|
|
search?: string;
|
|
userEmail?: string;
|
|
estabelecimentoId?: number;
|
|
}
|
|
|
|
export interface GetOpinionsResponse {
|
|
data: OpinionRecord[];
|
|
total: number;
|
|
page: number;
|
|
per_page: number;
|
|
}
|
|
|
|
type ApiErrorShape = { message?: string; status?: number };
|
|
|
|
class AgentService {
|
|
private readonly CREATE_ENDPOINT = '/webhook/codex/gepam/parecer-tecnico';
|
|
private readonly OPINIONS_BASE = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex';
|
|
|
|
private resolveUserContext(userEmail?: string, estabelecimentoId?: number) {
|
|
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
|
|
const estabId = estabelecimentoId || GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);
|
|
return { email, estabId };
|
|
}
|
|
|
|
private assertUserContext(email: unknown, estabId: unknown) {
|
|
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' };
|
|
}
|
|
}
|
|
|
|
private toApiError(error: unknown): never {
|
|
const e = error as ApiErrorShape;
|
|
throw {
|
|
success: false,
|
|
message: e?.message || 'Erro desconhecido',
|
|
status: e?.status,
|
|
};
|
|
}
|
|
|
|
async createOpinion(request: CreateOpinionRequest): Promise<CreateOpinionResponse> {
|
|
const { titulo, categoria, instrucoes, userEmail, estabelecimentoId } = request;
|
|
|
|
if (!titulo?.trim()) {
|
|
throw { success: false, message: 'Título do parecer é obrigatório' };
|
|
}
|
|
|
|
if (!instrucoes?.trim()) {
|
|
throw { success: false, message: 'Instruções são obrigatórias' };
|
|
}
|
|
|
|
const { email, estabId } = this.resolveUserContext(userEmail, estabelecimentoId);
|
|
this.assertUserContext(email, estabId);
|
|
|
|
try {
|
|
const response = await apiService.post<CreateOpinionResponse>(
|
|
this.CREATE_ENDPOINT,
|
|
{
|
|
user_email: email,
|
|
estabelecimento_id: estabId,
|
|
titulo: titulo.trim(),
|
|
categoria: categoria.trim(),
|
|
instrucoes: instrucoes.trim(),
|
|
},
|
|
{ timeout: 600_000 }
|
|
);
|
|
|
|
return response.data;
|
|
} catch (error: unknown) {
|
|
console.error('Erro ao criar parecer:', error);
|
|
this.toApiError(error);
|
|
}
|
|
}
|
|
|
|
async getOpinions(params?: GetOpinionsParams): Promise<OpinionRecord[]> {
|
|
const { page = 1, per_page = 10, search = '', userEmail, estabelecimentoId } = params || {};
|
|
|
|
const { email, estabId } = this.resolveUserContext(userEmail, estabelecimentoId);
|
|
this.assertUserContext(email, estabId);
|
|
|
|
try {
|
|
const url = `${this.OPINIONS_BASE}/get_parecer/${email}/${estabId}`;
|
|
|
|
const response = await apiService.get<OpinionRecord[] | GetOpinionsResponse>(url, {
|
|
params: { page, per_page, search },
|
|
});
|
|
|
|
const raw = response.data;
|
|
|
|
if (Array.isArray(raw)) return raw;
|
|
|
|
if (raw && typeof raw === 'object') {
|
|
if (Array.isArray((raw as GetOpinionsResponse).data)) return (raw as GetOpinionsResponse).data;
|
|
if (Array.isArray((raw as { opinions?: OpinionRecord[] }).opinions)) {
|
|
return (raw as unknown as { opinions: OpinionRecord[] }).opinions;
|
|
}
|
|
}
|
|
|
|
return [];
|
|
} catch (error: unknown) {
|
|
console.error('Erro ao buscar pareceres:', error);
|
|
this.toApiError(error);
|
|
}
|
|
}
|
|
|
|
async downloadOpinion(fileUrl: string, fileName: string): Promise<void> {
|
|
if (!fileUrl) {
|
|
throw { success: false, message: 'URL do arquivo não fornecida' };
|
|
}
|
|
|
|
const triggerDownload = (href: string) => {
|
|
const link = document.createElement('a');
|
|
link.href = href;
|
|
link.download = fileName;
|
|
link.target = '_blank';
|
|
link.rel = 'noopener noreferrer';
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
};
|
|
|
|
try {
|
|
const response = await fetch(fileUrl, { method: 'GET', mode: 'cors', cache: 'no-cache' });
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Erro HTTP: ${response.status}`);
|
|
}
|
|
|
|
const blob = await response.blob();
|
|
const blobUrl = URL.createObjectURL(blob);
|
|
triggerDownload(blobUrl);
|
|
URL.revokeObjectURL(blobUrl);
|
|
} catch {
|
|
const url = new URL(fileUrl);
|
|
url.searchParams.set('response-content-disposition', `attachment; filename="${encodeURIComponent(fileName)}"`);
|
|
triggerDownload(url.toString());
|
|
}
|
|
}
|
|
|
|
async deleteOpinion(opinionId: string, userEmail?: string): Promise<{ success: boolean }> {
|
|
if (!opinionId) {
|
|
throw { success: false, message: 'ID do parecer não fornecido' };
|
|
}
|
|
|
|
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
|
|
|
|
if (!email) {
|
|
throw { success: false, message: 'Email do usuário não fornecido' };
|
|
}
|
|
|
|
try {
|
|
const url = `${this.OPINIONS_BASE}/delete_parecer/${email}/${opinionId}`;
|
|
const response = await apiService.delete<{ success: boolean }[]>(url);
|
|
|
|
if (Array.isArray(response.data) && response.data.length > 0) {
|
|
return response.data[0];
|
|
}
|
|
|
|
return { success: true };
|
|
} catch (error: unknown) {
|
|
console.error('Erro ao excluir parecer:', error);
|
|
this.toApiError(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
export const agentService = new AgentService();
|