From 71f9c9ab860f7c5597427fb5fc82492a925aa9cf Mon Sep 17 00:00:00 2001 From: Vitex Tecnologia Date: Mon, 19 Jan 2026 14:19:18 -0300 Subject: [PATCH] =?UTF-8?q?mudanca=20requisicoes=20API=20do=20metodo=20PUT?= =?UTF-8?q?=20para=20POST=20e=20limpeza=20/=20organizacao=20dos=20c=C3=B3d?= =?UTF-8?q?igos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../intelligence-ia/pages/Financas.tsx | 9 +- .../intelligence-ia/pages/Integrations.tsx | 6 +- .../intelligence-ia/pages/MeuPerfil.tsx | 24 +- src/services/asana.ts | 109 +-------- src/services/index.ts | 4 +- .../{userProfile.ts => personalAgent.ts} | 227 ++++-------------- 6 files changed, 68 insertions(+), 311 deletions(-) rename src/services/{userProfile.ts => personalAgent.ts} (65%) diff --git a/src/modules/intelligence-ia/pages/Financas.tsx b/src/modules/intelligence-ia/pages/Financas.tsx index 8a521cd..c6556a7 100644 --- a/src/modules/intelligence-ia/pages/Financas.tsx +++ b/src/modules/intelligence-ia/pages/Financas.tsx @@ -48,7 +48,7 @@ import { PaginationPrevious, } from "@/components/ui/pagination"; import { Badge } from "@/components/ui/badge"; -import { userProfileService, FinancialIndicators, ExpenseItem, ExpensesResponse, ExpensesFilters, ExpenseCategory } from "@/services/userProfile"; +import { personalAgent, FinancialIndicators, ExpenseItem, ExpensesResponse, ExpensesFilters, ExpenseCategory } from "@/services/personalAgent"; import { GlobalFunctions, TransferAreaProperties } from "@/GlobalFunctions"; import { toast } from "@/hooks/use-toast"; @@ -175,7 +175,7 @@ export default function Financas() { } // Busca os indicadores financeiros da API - const response = await userProfileService.getFinancialIndicators(userEmail); + const response = await personalAgent.getFinancialIndicators(userEmail); if (response.success) { setIndicators(response); @@ -265,7 +265,7 @@ export default function Financas() { filters.data_final = format(endDate, "yyyy-MM-dd"); } - const response = await userProfileService.getExpenses(emailToUse, filters); + const response = await personalAgent.getExpenses(emailToUse, filters); if (response.success) { // Garante que a resposta tenha estrutura válida mesmo quando não há dados @@ -308,8 +308,7 @@ export default function Financas() { // Carrega categorias try { setLoadingCategories(true); - const categoriesData = await userProfileService.getCategories(); - console.log("Categorias carregadas:", categoriesData); + const categoriesData = await personalAgent.getCategories(); setCategories(categoriesData); } catch (error) { console.error("Erro ao carregar categorias:", error); diff --git a/src/modules/intelligence-ia/pages/Integrations.tsx b/src/modules/intelligence-ia/pages/Integrations.tsx index b1d8a68..5a1ea5d 100644 --- a/src/modules/intelligence-ia/pages/Integrations.tsx +++ b/src/modules/intelligence-ia/pages/Integrations.tsx @@ -4,7 +4,7 @@ import { GoogleCalendarCard } from "@/modules/intelligence-ia/components/integra import { GoogleSheetsCard } from "@/modules/intelligence-ia/components/integrations/GoogleSheetsCard"; import { AsanaCard } from "@/modules/intelligence-ia/components/integrations/AsanaCard"; import { asanaService } from "@/services/asana"; -import { userProfileService } from "@/services/userProfile"; +import { personalAgent } from "@/services/personalAgent"; import { GlobalFunctions, TransferAreaProperties } from "@/GlobalFunctions"; interface Workspace { @@ -199,16 +199,14 @@ export default function Integrations() { } if (!userEmail) { - console.log("Integrations: Não foi possível obter email do usuário"); setLoadingIntegration(false); return; } // Busca o perfil do usuário para obter o ID - const userProfile = await userProfileService.getUserProfile(userEmail); + const userProfile = await personalAgent.getUserProfile(userEmail); if (!userProfile.success || !userProfile.id) { - console.log("Integrations: Usuário não encontrado ou sem ID"); setLoadingIntegration(false); return; } diff --git a/src/modules/intelligence-ia/pages/MeuPerfil.tsx b/src/modules/intelligence-ia/pages/MeuPerfil.tsx index b4af161..3959745 100644 --- a/src/modules/intelligence-ia/pages/MeuPerfil.tsx +++ b/src/modules/intelligence-ia/pages/MeuPerfil.tsx @@ -14,7 +14,7 @@ import { } from "@/components/ui/dialog"; import { User, Mail, Phone, Save, Bell, Loader2, Plus } from "lucide-react"; import { toast } from "@/hooks/use-toast"; -import { userProfileService, UserProfile } from "@/services/userProfile"; +import { personalAgent, UserProfile } from "@/services/personalAgent"; import { GlobalFunctions, TransferAreaProperties } from "@/GlobalFunctions"; const formatPhoneNumber = (value: string) => { @@ -54,20 +54,15 @@ const MeuPerfil = () => { // Verifica se há token no sessionStorage primeiro const jsonUsuario = sessionStorage.getItem('usuarioLogado'); if (!jsonUsuario) { - console.log("MeuPerfil: Não há token no sessionStorage"); window.location.replace(import.meta.env.VITE_BASE_URL_HGTX_CORE || 'https://core.hgtx.com.br'); return; } - console.log("MeuPerfil: Token encontrado no sessionStorage"); - // Tenta obter o email do usuário logado let userEmail = GlobalFunctions.getUsuarioLogado().email; - console.log("MeuPerfil: Email obtido:", userEmail); // Se não tem email, tenta fazer refresh do token if (!userEmail) { - console.log("MeuPerfil: Email vazio, tentando fazer refresh do token"); try { await GlobalFunctions.getToken(); // Aguarda um pouco para o refresh ser processado (se necessário) @@ -75,7 +70,6 @@ const MeuPerfil = () => { // Verifica novamente após refresh userEmail = GlobalFunctions.getUsuarioLogado().email; - console.log("MeuPerfil: Email após refresh:", userEmail); } catch (error) { console.error("MeuPerfil: Erro ao obter token:", error); } @@ -85,24 +79,17 @@ const MeuPerfil = () => { // Se o token existe mas não tem email, pode ser problema na decodificação if (!userEmail) { const usuarioData = GlobalFunctions.getUsuarioLogado(); - console.log("MeuPerfil: Dados do usuário após tentativas:", usuarioData); // Se não tem email mas tem token no sessionStorage, tenta carregar mesmo assim // O loadUserProfile vai tratar o erro adequadamente se o email for necessário // Só redireciona se o token estiver completamente inválido (sem UID e sem EID) if (!usuarioData.email && usuarioData.UID === "0" && usuarioData.EID === "0") { - console.log("MeuPerfil: Token completamente inválido (sem UID/EID), redirecionando"); window.location.replace(import.meta.env.VITE_BASE_URL_HGTX_CORE || 'https://core.hgtx.com.br'); return; } - - // Se tem token mas não tem email, pode ser que o email esteja em outro campo - // ou o token precisa ser renovado. Tenta carregar o perfil mesmo assim. - console.log("MeuPerfil: Token existe mas email vazio, tentando carregar perfil mesmo assim"); } // Se passou na verificação (ou tem token válido), carrega o perfil - console.log("MeuPerfil: Carregando perfil do usuário"); loadUserProfile(); }; @@ -116,13 +103,11 @@ const MeuPerfil = () => { // Se não tem email, tenta obter do Transfer Area como fallback if (!userEmail) { - console.log("MeuPerfil: Email não encontrado no token, tentando Transfer Area"); const transferEmail = GlobalFunctions.getTransferProperty( TransferAreaProperties.UsuarioEmail ); if (transferEmail) { userEmail = transferEmail as string; - console.log("MeuPerfil: Email do Transfer Area:", userEmail); } } @@ -132,7 +117,6 @@ const MeuPerfil = () => { await GlobalFunctions.getToken(); await new Promise(resolve => setTimeout(resolve, 500)); userEmail = GlobalFunctions.getUsuarioLogado().email; - console.log("MeuPerfil: Email após refresh no loadUserProfile:", userEmail); } catch (error) { console.error("MeuPerfil: Erro ao fazer refresh no loadUserProfile:", error); } @@ -151,7 +135,7 @@ const MeuPerfil = () => { } setEmail(userEmail); - const response = await userProfileService.getUserProfile(userEmail); + const response = await personalAgent.getUserProfile(userEmail); if (response.success && response.id) { // Usuário existe @@ -203,7 +187,7 @@ const MeuPerfil = () => { try { setSaving(true); - const response = await userProfileService.updateUser(userId, { + const response = await personalAgent.updateUser(userId, { nome: nomeCompleto, whatsapp: whatsapp, followup: receberLembretes, @@ -255,7 +239,7 @@ const MeuPerfil = () => { try { setCreating(true); - const response = await userProfileService.createUser({ + const response = await personalAgent.createUser({ nome: createNome.trim(), email: email, whatsapp: createWhatsapp, diff --git a/src/services/asana.ts b/src/services/asana.ts index 9973158..7f729d4 100644 --- a/src/services/asana.ts +++ b/src/services/asana.ts @@ -1,58 +1,32 @@ -/** - * Serviço para integração com API do Asana - */ - -/** - * Interface para workspace do Asana (resposta da API) - */ export interface AsanaWorkspaceResponse { gid: string; resource_type: string; name: string; } -/** - * Interface para resposta da API de workspaces - */ export interface AsanaWorkspacesResponse { data: AsanaWorkspaceResponse[]; } -/** - * Interface para workspace formatado (usado no componente) - */ export interface AsanaWorkspace { id: string; name: string; } -/** - * Interface para usuário do Asana (resposta da API) - */ export interface AsanaUserResponse { gid: string; name: string; resource_type: string; } -/** - * Interface para resposta da API de usuários - */ export interface AsanaUsersResponse { data: AsanaUserResponse[]; } -/** - * Interface para usuário formatado (usado no componente) - */ export interface AsanaUser { id: string; name: string; } - -/** - * Interface para resposta da API de integração do Asana - */ export interface AsanaIntegrationResponse { success: boolean; integracao_id?: string; @@ -64,9 +38,6 @@ export interface AsanaIntegrationResponse { usuario_asana_nome?: string; } -/** - * Interface para request de criação/atualização de integração - */ export interface AsanaIntegrationRequest { user_id?: string; api_key: string; @@ -76,20 +47,9 @@ export interface AsanaIntegrationRequest { usuario_asana_nome: string; } -/** - * Serviço para integração com Asana - */ class AsanaService { - private readonly BASE_URL = 'https://app.asana.com/api/1.0'; - private readonly INTEGRATION_BASE_URL = 'https://prod-hgtx-intelligence-n8n.hgtx.com.br'; - private readonly INTEGRATION_WEBHOOK_ID = 'c898beff-84cb-44df-a69c-6eff27ccd7aa'; + private readonly ASANA_BASE_URL = 'https://app.asana.com/api/1.0'; - /** - * Lista os workspaces do Asana usando o token fornecido - * - * @param token - Token de acesso do Asana - * @returns Promise com a lista de workspaces formatados - */ async getWorkspaces(token: string): Promise { if (!token || token.trim().length === 0) { throw { @@ -107,12 +67,10 @@ class AsanaService { }; const response = await axios.get( - `${this.BASE_URL}/workspaces`, + `${this.ASANA_BASE_URL}/workspaces`, { headers } ); - // Converte a resposta da API para o formato esperado pelo componente - // A API retorna gid, mas o componente espera id return response.data.data.map((workspace) => ({ id: workspace.gid, name: workspace.name, @@ -120,7 +78,6 @@ class AsanaService { } catch (error: unknown) { console.error('Erro ao buscar workspaces do Asana:', error); - // Retorna o erro da API se existir if (error && typeof error === 'object' && 'response' in error) { const axiosError = error as { response?: { data?: any; status?: number } }; @@ -146,13 +103,6 @@ class AsanaService { } } - /** - * Lista os usuários de um workspace do Asana - * - * @param token - Token de acesso do Asana - * @param workspaceId - ID do workspace (gid) - * @returns Promise com a lista de usuários formatados - */ async getUsers(token: string, workspaceId: string): Promise { if (!token || token.trim().length === 0) { throw { @@ -177,7 +127,7 @@ class AsanaService { }; const response = await axios.get( - `${this.BASE_URL}/users?workspace=${workspaceId}`, + `${this.ASANA_BASE_URL}/users?workspace=${workspaceId}`, { headers } ); @@ -190,7 +140,6 @@ class AsanaService { } catch (error: unknown) { console.error('Erro ao buscar usuários do Asana:', error); - // Retorna o erro da API se existir if (error && typeof error === 'object' && 'response' in error) { const axiosError = error as { response?: { data?: any; status?: number } }; @@ -216,12 +165,6 @@ class AsanaService { } } - /** - * Obtém os detalhes da integração do Asana do usuário - * - * @param userId - ID do usuário - * @returns Promise com os detalhes da integração ou null se não houver - */ async getIntegration(userId: string): Promise { if (!userId || userId.trim().length === 0) { throw { @@ -234,7 +177,6 @@ class AsanaService { const axios = (await import('axios')).default; const { GlobalFunctions } = await import('@/GlobalFunctions'); - // Obtém o token JWT para autenticação const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; @@ -243,27 +185,19 @@ class AsanaService { 'accept': 'application/json', }; - // Adiciona API key (obrigatória) if (apiKey) { headers['apikey'] = apiKey; } - // Adiciona token JWT se disponível if (token) { headers['Authorization'] = `Bearer ${token}`; } - // Em desenvolvimento, usa proxy do Vite para evitar CORS - const baseUrl = import.meta.env.DEV - ? '/api/intelligence' - : this.INTEGRATION_BASE_URL; - const response = await axios.get( - `${baseUrl}/webhook/${this.INTEGRATION_WEBHOOK_ID}/codex/agente-pessoal/integracoes/asana/${userId}`, + `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/c898beff-84cb-44df-a69c-6eff27ccd7aa/codex/agente-pessoal/integracoes/asana/${userId}`, { headers } ); - // Se success é false, retorna null (não tem integração) if (!response.data.success) { return null; } @@ -280,17 +214,10 @@ class AsanaService { } } - // Para outros erros, retorna null silenciosamente (não quebra a aplicação) return null; } } - /** - * Cria uma nova integração do Asana - * - * @param request - Dados da integração a ser criada - * @returns Promise com a resposta da criação - */ async createIntegration(request: AsanaIntegrationRequest): Promise { if (!request.user_id || !request.api_key || !request.workspace_gid || !request.usuario_asana_gid) { throw { @@ -322,13 +249,8 @@ class AsanaService { headers['Authorization'] = `Bearer ${token}`; } - // Em desenvolvimento, usa proxy do Vite para evitar CORS - const baseUrl = import.meta.env.DEV - ? '/api/intelligence' - : this.INTEGRATION_BASE_URL; - const response = await axios.post( - `${baseUrl}/webhook/codex/agente-pessoal/integracoes/asana`, + `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/codex/agente-pessoal/integracoes/asana`, request, { headers } ); @@ -357,13 +279,6 @@ class AsanaService { } } - /** - * Atualiza uma integração existente do Asana - * - * @param integracaoId - ID da integração a ser atualizada - * @param request - Dados da integração a ser atualizada - * @returns Promise com a resposta da atualização - */ async updateIntegration(integracaoId: string, request: Omit): Promise { if (!integracaoId || !request.api_key || !request.workspace_gid || !request.usuario_asana_gid) { throw { @@ -376,7 +291,6 @@ class AsanaService { const axios = (await import('axios')).default; const { GlobalFunctions } = await import('@/GlobalFunctions'); - // Obtém o token JWT para autenticação const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; @@ -385,23 +299,18 @@ class AsanaService { 'accept': 'application/json', }; - // Adiciona API key (obrigatória) if (apiKey) { headers['apikey'] = apiKey; } - // Adiciona token JWT se disponível if (token) { headers['Authorization'] = `Bearer ${token}`; } - // Em desenvolvimento, usa proxy do Vite para evitar CORS - const baseUrl = import.meta.env.DEV - ? '/api/intelligence' - : this.INTEGRATION_BASE_URL; - - const response = await axios.put( - `${baseUrl}/webhook/${this.INTEGRATION_WEBHOOK_ID}/codex/agente-pessoal/integracoes/asana/${integracaoId}`, + const url = `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/c898beff-84cb-44df-a69c-6eff27ccd7aa/codex/agente-pessoal/integracoes/asana/${integracaoId}`; + + const response = await axios.post( + url, request, { headers } ); diff --git a/src/services/index.ts b/src/services/index.ts index f1f65a0..80f9cc0 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -6,7 +6,7 @@ export { apiService } from './api'; export { transcriptionService } from './transcription'; export { audioGenerationService, VOICE_OPTIONS } from './audioGeneration'; export { imageGenerationService, IMAGE_SIZE_OPTIONS } from './imageGeneration'; -export { userProfileService } from './userProfile'; +export { personalAgent } from './personalAgent'; export { asanaService } from './asana'; export type { TranscriptionResponse, TranscriptionRequest } from './transcription'; export type { AudioGenerationResponse, AudioGenerationRequest, VoiceType } from './audioGeneration'; @@ -20,7 +20,7 @@ export type { ExpensesResponse, ExpensesFilters, ExpenseCategory -} from './userProfile'; +} from './personalAgent'; export type { AsanaWorkspace, AsanaWorkspaceResponse, diff --git a/src/services/userProfile.ts b/src/services/personalAgent.ts similarity index 65% rename from src/services/userProfile.ts rename to src/services/personalAgent.ts index 6d4104e..82ef6a4 100644 --- a/src/services/userProfile.ts +++ b/src/services/personalAgent.ts @@ -1,9 +1,4 @@ -import { apiService } from './api'; import { GlobalFunctions } from '@/GlobalFunctions'; - -/** - * Interfaces para o serviço de perfil do usuário - */ export interface UserProfile { success: boolean; id?: string; @@ -27,9 +22,6 @@ export interface UpdateUserRequest { followup: boolean; } -/** - * Interface para indicadores financeiros - */ export interface FinancialIndicators { success: boolean; id: string; @@ -41,9 +33,6 @@ export interface FinancialIndicators { message?: string; } -/** - * Interface para despesa individual da API - */ export interface ExpenseItem { id: string; data_hora: string; @@ -56,9 +45,6 @@ export interface ExpenseItem { usuario_email: string; } -/** - * Interface para resposta da API de despesas - */ export interface ExpensesResponse { success: boolean; total_registros: number; @@ -68,9 +54,6 @@ export interface ExpensesResponse { data: ExpenseItem[]; } -/** - * Interface para filtros de busca de despesas - */ export interface ExpensesFilters { page?: number; per_page?: number; @@ -80,9 +63,6 @@ export interface ExpensesFilters { data_final?: string; } -/** - * Interface para categoria de despesas - */ export interface ExpenseCategory { id: number; nome: string; @@ -91,29 +71,8 @@ export interface ExpenseCategory { atualizado_em: string; } -/** - * Serviço para gerenciamento de perfil do usuário - */ -class UserProfileService { - // Em desenvolvimento, usa proxy do Vite para evitar CORS - // Em produção, usa URL direta (requer que servidor permita PUT no CORS) - private readonly BASE_URL = import.meta.env.DEV - ? '/api/intelligence' - : 'https://prod-hgtx-intelligence-n8n.hgtx.com.br'; - private readonly WEBHOOK_ID = '2299acaf-70ee-47e3-a6fc-56dcc678d651'; - private readonly GET_USER_ENDPOINT = `${this.BASE_URL}/webhook/${this.WEBHOOK_ID}/codex/agente-pessoal/user`; - private readonly CREATE_USER_ENDPOINT = `${this.BASE_URL}/webhook/codex/agente-pessoal/user`; - private readonly UPDATE_USER_ENDPOINT = `${this.BASE_URL}/webhook/${this.WEBHOOK_ID}/codex/agente-pessoal/user`; - private readonly GET_FINANCIAL_INDICATORS_ENDPOINT = `${this.BASE_URL}/webhook/${this.WEBHOOK_ID}/codex/agente-pessoal/financas/indicadores`; - private readonly GET_EXPENSES_ENDPOINT = `${this.BASE_URL}/webhook/${this.WEBHOOK_ID}/codex/agente-pessoal/financas`; - private readonly GET_CATEGORIES_ENDPOINT = `${this.BASE_URL}/webhook/codex/agente-pessoal/categorias`; +class PersonalAgent { - /** - * Obtém os detalhes do usuário pelo email - * - * @param userEmail - Email do usuário (opcional, usa do GlobalFunctions se não fornecido) - * @returns Promise com os dados do usuário ou erro se não existir - */ async getUserProfile(userEmail?: string): Promise { const email = userEmail || GlobalFunctions.getUsuarioLogado().email; @@ -125,36 +84,30 @@ class UserProfileService { } try { - // Usa axios diretamente pois a URL é absoluta e diferente do baseURL const axios = (await import('axios')).default; - - // Obtém o token JWT para autenticação + const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; - - // Prepara headers de autenticação + const headers: Record = { 'Content-Type': 'application/json', }; - - // Adiciona API key (obrigatória) + if (apiKey) { headers['apikey'] = apiKey; } - - // Adiciona token JWT se disponível + if (token) { headers['Authorization'] = `Bearer ${token}`; } - + const response = await axios.get( - `${this.GET_USER_ENDPOINT}/${email}`, + `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/2299acaf-70ee-47e3-a6fc-56dcc678d651/codex/agente-pessoal/user/${email}`, { headers } ); return response.data; } catch (error: any) { - // Se o usuário não existir, retorna o erro da API if (error.response?.data) { return error.response.data; } @@ -167,14 +120,8 @@ class UserProfileService { } } - /** - * Cria um novo usuário - * - * @param request - Dados do usuário a ser criado - * @returns Promise com os dados do usuário criado - */ async createUser(request: CreateUserRequest): Promise { - // Validações + if (!request.nome || request.nome.trim().length === 0) { throw { success: false, @@ -196,48 +143,30 @@ class UserProfileService { }; } - // Remove formatação do WhatsApp (apenas números) const whatsappNumbers = request.whatsapp.replace(/\D/g, ''); try { const axios = (await import('axios')).default; - - // Obtém o token JWT para autenticação + const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; - - // Prepara headers de autenticação - // A API pode precisar apenas da apikey, não do token JWT + const headers: Record = { 'Content-Type': 'application/json', }; - - // Adiciona API key (obrigatória) + if (apiKey) { headers['apikey'] = apiKey; } else { - console.warn('VITE_API_KEY não configurada'); + console.warn('API_KEY não configurada'); } - - // Adiciona token JWT se disponível (pode ser necessário) + if (token) { headers['Authorization'] = `Bearer ${token}`; } - - console.log('Criando usuário:', { - url: this.CREATE_USER_ENDPOINT, - hasApiKey: !!apiKey, - hasToken: !!token, - data: { - nome: request.nome.trim(), - email: request.email.trim(), - whatsapp: whatsappNumbers, - followup: request.followup, - }, - }); - + const response = await axios.post( - this.CREATE_USER_ENDPOINT, + 'https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/codex/agente-pessoal/user', { nome: request.nome.trim(), email: request.email.trim(), @@ -249,7 +178,6 @@ class UserProfileService { return response.data; } catch (error: any) { - // Retorna o erro da API se existir if (error.response?.data) { throw error.response.data; } @@ -262,15 +190,8 @@ class UserProfileService { } } - /** - * Atualiza os dados do usuário - * - * @param userId - ID do usuário - * @param request - Dados a serem atualizados - * @returns Promise com os dados atualizados do usuário - */ async updateUser(userId: string, request: UpdateUserRequest): Promise { - // Validações + if (!userId || userId.trim().length === 0) { throw { success: false, @@ -292,47 +213,28 @@ class UserProfileService { }; } - // Remove formatação do WhatsApp (apenas números) const whatsappNumbers = request.whatsapp.replace(/\D/g, ''); try { const axios = (await import('axios')).default; - - // Obtém o token JWT para autenticação + const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; - - // Prepara headers de autenticação + const headers: Record = { 'Content-Type': 'application/json', }; - - // Adiciona API key (obrigatória) + if (apiKey) { headers['apikey'] = apiKey; } - - // Adiciona token JWT se disponível + if (token) { headers['Authorization'] = `Bearer ${token}`; } - - console.log('Atualizando usuário:', { - url: `${this.UPDATE_USER_ENDPOINT}/${userId}`, - method: 'PUT', - hasApiKey: !!apiKey, - hasToken: !!token, - isDev: import.meta.env.DEV, - data: { - nome: request.nome.trim(), - whatsapp: whatsappNumbers, - followup: request.followup, - }, - }); - - // Usa PUT conforme documentação da API - const response = await axios.put( - `${this.UPDATE_USER_ENDPOINT}/${userId}`, + + const response = await axios.post( + `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/2299acaf-70ee-47e3-a6fc-56dcc678d651/codex/agente-pessoal/user/${userId}`, { nome: request.nome.trim(), whatsapp: whatsappNumbers, @@ -343,7 +245,6 @@ class UserProfileService { return response.data; } catch (error: any) { - // Retorna o erro da API se existir if (error.response?.data) { throw error.response.data; } @@ -356,12 +257,6 @@ class UserProfileService { } } - /** - * Obtém os indicadores financeiros do usuário - * - * @param userEmail - Email do usuário (opcional, usa do GlobalFunctions se não fornecido) - * @returns Promise com os indicadores financeiros - */ async getFinancialIndicators(userEmail?: string): Promise { const email = userEmail || GlobalFunctions.getUsuarioLogado().email; @@ -374,34 +269,29 @@ class UserProfileService { try { const axios = (await import('axios')).default; - - // Obtém o token JWT para autenticação + const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; - - // Prepara headers de autenticação + const headers: Record = { 'Content-Type': 'application/json', }; - - // Adiciona API key (obrigatória) + if (apiKey) { headers['apikey'] = apiKey; } - - // Adiciona token JWT se disponível + if (token) { headers['Authorization'] = `Bearer ${token}`; } const response = await axios.get( - `${this.GET_FINANCIAL_INDICATORS_ENDPOINT}/${email}`, + `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/2299acaf-70ee-47e3-a6fc-56dcc678d651/codex/agente-pessoal/financas/indicadores/${email}`, { headers } ); return response.data; } catch (error: unknown) { - // Retorna o erro da API se existir if (error && typeof error === 'object' && 'response' in error) { const axiosError = error as { response?: { data?: FinancialIndicators } }; if (axiosError.response?.data) { @@ -412,20 +302,13 @@ class UserProfileService { throw { success: false, message: error instanceof Error ? error.message : 'Erro ao buscar indicadores financeiros', - status: error && typeof error === 'object' && 'response' in error - ? (error as { response?: { status?: number } }).response?.status + status: error && typeof error === 'object' && 'response' in error + ? (error as { response?: { status?: number } }).response?.status : undefined, }; } } - /** - * Obtém a lista de despesas do usuário com paginação e filtros - * - * @param userEmail - Email do usuário (opcional, usa do GlobalFunctions se não fornecido) - * @param filters - Filtros de busca (página, itens por página, descrição, categoria, datas) - * @returns Promise com a lista de despesas paginada - */ async getExpenses(userEmail?: string, filters?: ExpensesFilters): Promise { const email = userEmail || GlobalFunctions.getUsuarioLogado().email; @@ -438,22 +321,18 @@ class UserProfileService { try { const axios = (await import('axios')).default; - - // Obtém o token JWT para autenticação + const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; - - // Prepara headers de autenticação + const headers: Record = { 'Content-Type': 'application/json', }; - - // Adiciona API key (obrigatória) + if (apiKey) { headers['apikey'] = apiKey; } - - // Adiciona token JWT se disponível + if (token) { headers['Authorization'] = `Bearer ${token}`; } @@ -468,14 +347,13 @@ class UserProfileService { if (filters?.data_final) params.append('data_final', filters.data_final); const queryString = params.toString(); - const url = `${this.GET_EXPENSES_ENDPOINT}/${email}${queryString ? `?${queryString}` : ''}`; + const url = `https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/2299acaf-70ee-47e3-a6fc-56dcc678d651/codex/agente-pessoal/financas/${email}${queryString ? `?${queryString}` : ''}`; const response = await axios.get(url, { headers }); - // A API retorna um array com um único objeto if (Array.isArray(response.data) && response.data.length > 0) { const expensesResponse = response.data[0]; - + // Valida e limpa o array de dados, removendo objetos vazios if (expensesResponse.data && Array.isArray(expensesResponse.data)) { // Filtra objetos vazios (sem propriedades ou apenas com propriedades vazias) @@ -483,7 +361,7 @@ class UserProfileService { // Verifica se o objeto tem pelo menos uma propriedade válida return item && typeof item === 'object' && Object.keys(item).length > 0 && item.id; }); - + // Se após filtrar não há dados, garante que data seja um array vazio if (expensesResponse.data.length === 0) { expensesResponse.data = []; @@ -496,7 +374,7 @@ class UserProfileService { expensesResponse.total_registros = 0; expensesResponse.total_paginas = 0; } - + return expensesResponse; } @@ -521,42 +399,33 @@ class UserProfileService { throw { success: false, message: error instanceof Error ? error.message : 'Erro ao buscar despesas', - status: error && typeof error === 'object' && 'response' in error - ? (error as { response?: { status?: number } }).response?.status + status: error && typeof error === 'object' && 'response' in error + ? (error as { response?: { status?: number } }).response?.status : undefined, }; } } - /** - * Obtém a lista de categorias de despesas - * - * @returns Promise com a lista de categorias - */ async getCategories(): Promise { try { const axios = (await import('axios')).default; - - // Obtém o token JWT para autenticação + const token = await GlobalFunctions.getToken(); const apiKey = import.meta.env.VITE_API_KEY || ''; - - // Prepara headers de autenticação + const headers: Record = { 'Content-Type': 'application/json', }; - - // Adiciona API key (obrigatória) + if (apiKey) { headers['apikey'] = apiKey; } - - // Adiciona token JWT se disponível + if (token) { headers['Authorization'] = `Bearer ${token}`; } - const response = await axios.get(this.GET_CATEGORIES_ENDPOINT, { headers }); + const response = await axios.get('https://prod-hgtx-intelligence-n8n.hgtx.com.br/webhook/codex/agente-pessoal/categorias', { headers }); // A API retorna um array de categorias if (Array.isArray(response.data)) { @@ -566,12 +435,10 @@ class UserProfileService { return []; } catch (error: unknown) { console.error('Erro ao buscar categorias:', error); - - // Retorna array vazio em caso de erro para não quebrar a aplicação + return []; } } } -// Exporta instância única (Singleton) -export const userProfileService = new UserProfileService(); +export const personalAgent = new PersonalAgent();