import axios, { AxiosError, AxiosInstance, InternalAxiosRequestConfig, } from 'axios'; import { getAccessToken, handleTokenRefresh, } from '../../login/utils/tokenRefresh'; import { OrderFilters, orderApiParamsSchema, orderResponseSchema, ordersResponseSchema, storesResponseSchema, customersResponseSchema, sellersResponseSchema, unwrapApiData, } from '../schemas/order.schema'; import { orderItemsResponseSchema, OrderItem, shipmentResponseSchema, Shipment, cargoMovementResponseSchema, CargoMovement, cuttingItemResponseSchema, CuttingItem, } from '../schemas/order.item.schema'; import { Store } from '../schemas/store.schema'; import { Seller } from '../schemas/seller.schema'; import { Order } from '../types'; const ORDERS_API_URL = process.env.NEXT_PUBLIC_ORDERS_API_URL; export const ordersApi: AxiosInstance = axios.create({ baseURL: ORDERS_API_URL, withCredentials: true, headers: { 'Content-Type': 'application/json', }, }); /** * Adiciona o token de autenticação aos cabeçalhos da requisição. * Executa apenas no ambiente do navegador (verifica a existência do objeto window). * * @param {InternalAxiosRequestConfig} config - A configuração da requisição Axios * @returns {InternalAxiosRequestConfig} A configuração modificada com o cabeçalho Authorization */ const addToken = (config: InternalAxiosRequestConfig) => { if (globalThis.window !== undefined) { const token = getAccessToken(); if (token && config.headers) { config.headers.Authorization = `Bearer ${token}`; } } return config; }; ordersApi.interceptors.request.use(addToken); /** * Trata erros de resposta das requisições da API. * Tenta atualizar o token de autenticação se a requisição falhar. * * @param {AxiosError} error - O objeto de erro do Axios * @returns {Promise} Resultado da tentativa de atualização do token * @throws {AxiosError} Se não houver configuração de requisição original disponível */ const handleResponseError = async (error: AxiosError) => { const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean; }; if (!originalRequest) { throw error; } return handleTokenRefresh(error, originalRequest, ordersApi); }; ordersApi.interceptors.response.use( (response) => response, handleResponseError ); export const orderService = { /** * Busca pedidos com base nos filtros fornecidos. * Utiliza Zod para limpar e transformar os parâmetros automaticamente. * * @param {OrderFilters} filters - Critérios de filtro para buscar pedidos * @returns {Promise} Array de pedidos que correspondem aos filtros */ findOrders: async (filters: OrderFilters): Promise => { const cleanParams = orderApiParamsSchema.parse(filters); const response = await ordersApi.get('/api/v1/orders/find', { params: cleanParams, }); return unwrapApiData(response, ordersResponseSchema, []); }, /** * Busca um pedido específico pelo seu ID. * * @param {number} id - O identificador único do pedido * @returns {Promise} O pedido com o ID especificado, ou null se não encontrado */ findById: async (id: number): Promise => { const response = await ordersApi.get(`/orders/${id}`); return unwrapApiData(response, orderResponseSchema, null); }, /** * Recupera todas as lojas disponíveis. * * @returns {Promise} Array de todas as lojas, ou array vazio se nenhuma for encontrada */ findStores: async (): Promise => { const response = await ordersApi.get('/api/v1/data-consult/stores'); return unwrapApiData(response, storesResponseSchema, []); }, /** * Busca clientes por nome. * Retorna array vazio se o termo de busca tiver menos de 2 caracteres. * * @param {string} name - O nome do cliente a ser buscado (mínimo 2 caracteres) * @returns {Promise>} Array de clientes correspondentes com os campos id, name e estcob */ findCustomers: async ( name: string ): Promise> => { if (!name || name.trim().length < 2) return []; const response = await ordersApi.get( `/api/v1/clientes/${encodeURIComponent(name)}` ); return unwrapApiData(response, customersResponseSchema, []); }, findSellers: async (): Promise => { const response = await ordersApi.get('/api/v1/data-consult/sellers'); return unwrapApiData(response, sellersResponseSchema, []); }, findOrderItems: async (orderId: number): Promise => { const response = await ordersApi.get(`/api/v1/orders/itens/${orderId}`); return unwrapApiData(response, orderItemsResponseSchema, []); }, findDelivery: async ( orderId: number, includeCompletedDeliveries: boolean = true ): Promise => { const response = await ordersApi.get( `/api/v1/orders/delivery/${orderId}`, { params: { includeCompletedDeliveries }, } ); return unwrapApiData(response, shipmentResponseSchema, []); }, findCargoMovement: async (orderId: number): Promise => { const response = await ordersApi.get( `/api/v1/orders/transfer/${orderId}` ); return unwrapApiData(response, cargoMovementResponseSchema, []); }, findCuttingItems: async (orderId: number): Promise => { const response = await ordersApi.get( `/api/v1/orders/cut-itens/${orderId}` ); return unwrapApiData(response, cuttingItemResponseSchema, []); }, };