feat: implementa busca de produtos com API externa e corrige URL base
- Adiciona integração com API de produtos em http://10.1.1.212:8805/api/v1/data-consult/products/{id} - Corrige mapeamento de resposta da API para formato Product interface - Atualiza ProductSearchInput para usar description como nome do produto - Corrige API_BASE_URL adicionando protocolo http:// para evitar URLs relativas - Resolve erro 404 causado por URLs malformadas em requisições de API
This commit is contained in:
@@ -11,7 +11,7 @@ import { clearUrlAndNavigate } from "@/src/utils/url-helpers";
|
||||
/**
|
||||
* Função de utilidade para aplicar debounce em funções
|
||||
* Evita execuções repetidas em curtos intervalos de tempo
|
||||
*
|
||||
*
|
||||
* @template T - Tipo da função a ser debounced
|
||||
* @param {T} callback - Função a aplicar debounce
|
||||
* @param {number} delay - Tempo de espera em ms
|
||||
@@ -84,31 +84,32 @@ const paramMapping: Record<string, keyof OrderSearchParams> = {
|
||||
createDateEnd: "createDateEnd",
|
||||
customerId: "customerId",
|
||||
document: "document",
|
||||
invoiceNumber: "invoiceNumber"
|
||||
invoiceNumber: "invoiceNumber",
|
||||
productId: "productId"
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook personalizado para gerenciar a consulta e exibição de pedidos
|
||||
* Gerencia busca, paginação, armazenamento de parâmetros e detalhes de pedidos
|
||||
*
|
||||
*
|
||||
* @param {number} ordersPerPage - Número de pedidos a serem exibidos por página
|
||||
* @returns {UseOrderSearchReturn} Objeto contendo estado e funções para lidar com pedidos
|
||||
*/
|
||||
export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn {
|
||||
const router = useRouter();
|
||||
const urlSearchParams = useSearchParams();
|
||||
|
||||
|
||||
// Inicializar searchParams com valores da URL ou do localStorage ou um objeto vazio
|
||||
const [searchParams, setSearchParams] = useState<OrderSearchParams>(() => {
|
||||
const params: OrderSearchParams = {};
|
||||
|
||||
|
||||
// Tentar recuperar do localStorage primeiro
|
||||
const savedParams = getStorage("orderSearchParams");
|
||||
|
||||
|
||||
if (savedParams) {
|
||||
return savedParams;
|
||||
}
|
||||
|
||||
|
||||
// Se não houver no localStorage, extrair valores da URL para o estado
|
||||
Object.entries(paramMapping).forEach(([urlParam, stateParam]) => {
|
||||
const value = urlSearchParams.get(urlParam);
|
||||
@@ -117,7 +118,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
(params as any)[stateParam] = value;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Tratamento especial para parâmetros que podem ser arrays
|
||||
const typeParam = urlSearchParams.get('type');
|
||||
if (typeParam) {
|
||||
@@ -128,10 +129,10 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
params.type = typeParam;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return params;
|
||||
});
|
||||
|
||||
|
||||
const [orders, setOrders] = useState<Order[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -147,7 +148,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
// Detectar parâmetro origem=detalhe para realizar pesquisa automática ao retornar
|
||||
const origin = urlSearchParams.get("origem");
|
||||
|
||||
|
||||
// Limpar todos os campos relacionados ao cliente
|
||||
const clearCustomerFields = useCallback(() => {
|
||||
setSearchParams(prev => ({
|
||||
@@ -158,12 +159,21 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
selectedCustomer: null,
|
||||
}));
|
||||
}, []);
|
||||
|
||||
// Efeito para realizar pesquisa automática quando a página é carregada
|
||||
|
||||
// Limpar todos os campos relacionados ao produto
|
||||
const clearProductFields = useCallback(() => {
|
||||
setSearchParams(prev => ({
|
||||
...prev,
|
||||
productId: "",
|
||||
selectedProduct: null,
|
||||
}));
|
||||
}, []);
|
||||
|
||||
// Efeito para realizar pesquisa automática quando a página é carregada
|
||||
// e há parâmetros de pesquisa na URL ou se estamos voltando da página de detalhes
|
||||
useEffect(() => {
|
||||
const hasSearchParams = Object.keys(searchParams).length > 0;
|
||||
|
||||
|
||||
// Se temos parâmetros de busca e vamos retornando da página de detalhes,
|
||||
// ou se temos parâmetros e ainda não realizamos a pesquisa
|
||||
if ((hasSearchParams && origin === "detalhe") || (hasSearchParams && !hasSearched)) {
|
||||
@@ -177,7 +187,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
*/
|
||||
const updateUrlWithSearchParams = useCallback(() => {
|
||||
const urlParams = new URLSearchParams();
|
||||
|
||||
|
||||
// Adicionar apenas parâmetros com valores
|
||||
Object.entries(searchParams).forEach(([key, value]) => {
|
||||
if (value) {
|
||||
@@ -189,15 +199,15 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Preservar parâmetro origem se existir
|
||||
if (origin) {
|
||||
urlParams.append("origem", origin);
|
||||
}
|
||||
|
||||
|
||||
// Salvar no localStorage
|
||||
setStorage("orderSearchParams", searchParams);
|
||||
|
||||
|
||||
// Atualizar URL sem causar recarregamento da página
|
||||
const url = window.location.pathname + (urlParams.toString() ? `?${urlParams.toString()}` : "");
|
||||
window.history.replaceState({ path: url }, "", url);
|
||||
@@ -206,7 +216,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
/**
|
||||
* Executa a busca de pedidos com base nos parâmetros definidos
|
||||
* Valida datas, formata parâmetros e faz a chamada à API
|
||||
*
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const handleSearch = async () => {
|
||||
@@ -236,27 +246,30 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
// Transform the ALL value to empty string for the API call
|
||||
const paramsToSend: OrderSearchParams = { ...searchParams };
|
||||
|
||||
// Remover o campo selectedCustomer antes de enviar para a API
|
||||
|
||||
// Remover campos que não devem ser enviados para a API
|
||||
if (paramsToSend.selectedCustomer) {
|
||||
delete paramsToSend.selectedCustomer;
|
||||
}
|
||||
|
||||
if (paramsToSend.selectedProduct) {
|
||||
delete paramsToSend.selectedProduct;
|
||||
}
|
||||
|
||||
// Se tiver customerId definido, remover name e document para evitar conflito
|
||||
if (paramsToSend.customerId) {
|
||||
delete paramsToSend.name;
|
||||
delete paramsToSend.document;
|
||||
}
|
||||
|
||||
|
||||
// Se temos o nome do vendedor mas não temos o ID, tentar buscar o ID primeiro
|
||||
if (paramsToSend.sellerName && !paramsToSend.sellerId) {
|
||||
try {
|
||||
const sellers = await dataConsultApi.getSellers();
|
||||
if (Array.isArray(sellers)) {
|
||||
const matchingSeller = sellers.find((seller: any) =>
|
||||
const matchingSeller = sellers.find((seller: any) =>
|
||||
seller.name.toLowerCase().includes(paramsToSend.sellerName?.toLowerCase() || '')
|
||||
);
|
||||
|
||||
|
||||
if (matchingSeller) {
|
||||
// Extrair código numérico (887 de "887 - SAL-SIMONI")
|
||||
if (matchingSeller.name && matchingSeller.name.includes("-")) {
|
||||
@@ -276,18 +289,18 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
console.error("Erro ao buscar vendedores:", err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mapear invoiceNumber para invoiceId que é o que a API espera
|
||||
if (paramsToSend.invoiceNumber) {
|
||||
paramsToSend.invoiceId = paramsToSend.invoiceNumber;
|
||||
delete paramsToSend.invoiceNumber;
|
||||
}
|
||||
|
||||
|
||||
// Remover campos que a API não espera
|
||||
if ('nfe' in paramsToSend) {
|
||||
delete paramsToSend.nfe;
|
||||
}
|
||||
|
||||
|
||||
if (paramsToSend.codfilial === "ALL") {
|
||||
paramsToSend.codfilial = "";
|
||||
}
|
||||
@@ -305,7 +318,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
// Construir manualmente o queryParams para lidar com arrays
|
||||
const queryParams = new URLSearchParams();
|
||||
|
||||
|
||||
Object.entries(paramsToSend).forEach(([key, value]) => {
|
||||
if ((key === 'type' || key === 'status' || key === 'deliveryType') && Array.isArray(value)) {
|
||||
// Unir os valores do array em uma única string separada por vírgula
|
||||
@@ -314,21 +327,21 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
queryParams.append(key, String(value));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const queryString = queryParams.toString();
|
||||
const response = await ordersApi.findOrders(paramsToSend, queryString);
|
||||
setOrders(extractApiData<Order>(response));
|
||||
setError(null);
|
||||
|
||||
|
||||
// Reset selected order and items when new search is performed
|
||||
setSelectedOrderId(null);
|
||||
setOrderItems([]);
|
||||
setCutItems([]);
|
||||
|
||||
|
||||
// Reset pagination state
|
||||
setCurrentPage(1);
|
||||
setVisibleOrdersCount(ordersPerPage);
|
||||
|
||||
|
||||
// Atualizar a URL com os parâmetros de pesquisa
|
||||
updateUrlWithSearchParams();
|
||||
} catch (err) {
|
||||
@@ -342,13 +355,13 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
/**
|
||||
* Manipula alterações em campos de entrada do formulário
|
||||
* Atualiza o estado searchParams com o novo valor
|
||||
*
|
||||
*
|
||||
* @param {keyof OrderSearchParams} field - Nome do campo a atualizar
|
||||
* @param {any} value - Novo valor para o campo
|
||||
*/
|
||||
const handleInputChange = (field: keyof OrderSearchParams, value: any) => {
|
||||
// Garantir que valores apropriados sejam tratados como arrays
|
||||
if ((field === 'type' || field === 'status' || field === 'deliveryType') &&
|
||||
if ((field === 'type' || field === 'status' || field === 'deliveryType') &&
|
||||
typeof value === 'string' && value !== '') {
|
||||
// Converter string para array com um único item
|
||||
setSearchParams((prev) => ({
|
||||
@@ -370,7 +383,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
/**
|
||||
* Seleciona um cliente após busca, preenchendo campos relacionados
|
||||
*
|
||||
*
|
||||
* @param {Cliente | null} customer - Cliente selecionado ou null para limpar
|
||||
*/
|
||||
const handleCustomerSelect = (customer: Cliente | null) => {
|
||||
@@ -378,7 +391,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
clearCustomerFields();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
setSearchParams((prev) => ({
|
||||
...prev,
|
||||
selectedCustomer: customer,
|
||||
@@ -391,7 +404,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
/**
|
||||
* Manipula clique em linha da tabela de pedidos
|
||||
* Carrega detalhes do pedido selecionado
|
||||
*
|
||||
*
|
||||
* @param {string} orderId - ID do pedido selecionado
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@@ -435,14 +448,14 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
// Pagination calculations - corrigir para garantir 8 itens por página
|
||||
const totalPages = Math.ceil(orders.length / ordersPerPage);
|
||||
|
||||
|
||||
// Calcular o índice inicial baseado na página atual
|
||||
const indexOfFirstOrder = (currentPage - 1) * ordersPerPage;
|
||||
// Calcular o índice final
|
||||
const indexOfLastOrder = Math.min(indexOfFirstOrder + ordersPerPage, orders.length);
|
||||
// Selecionar apenas os itens da página atual
|
||||
const currentOrders = orders.slice(indexOfFirstOrder, indexOfLastOrder);
|
||||
|
||||
|
||||
// Navigate to next page
|
||||
const goToNextPage = useCallback(() => {
|
||||
if (currentPage < totalPages) {
|
||||
@@ -490,7 +503,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
/**
|
||||
* Identifica o tipo de entrada para busca de cliente
|
||||
* Diferencia entre ID, documento ou nome baseado no formato
|
||||
*
|
||||
*
|
||||
* @param {string} value - Valor de entrada a ser analisado
|
||||
* @returns {'id' | 'document' | 'name'} Tipo identificado da entrada
|
||||
*/
|
||||
@@ -503,7 +516,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
/**
|
||||
* Busca cliente por ID
|
||||
*
|
||||
*
|
||||
* @param {string} value - ID do cliente a ser buscado
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@@ -514,10 +527,10 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
clearCustomerFields();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let customerData: any = null;
|
||||
const inputType = identifyInputType(value);
|
||||
|
||||
|
||||
// Atualizar o campo apropriado com base no tipo de entrada
|
||||
setSearchParams(prev => ({
|
||||
...prev,
|
||||
@@ -525,7 +538,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
document: inputType === 'document' ? value : "",
|
||||
name: inputType === 'name' ? value : "",
|
||||
}));
|
||||
|
||||
|
||||
// Buscar cliente pelo tipo correto
|
||||
if (inputType === 'id') {
|
||||
const response = await dataConsultApi.getCustomer(value);
|
||||
@@ -538,7 +551,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
customerData = response[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (customerData) {
|
||||
// Create customer object from response
|
||||
const customer: Customer = {
|
||||
@@ -546,7 +559,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
name: customerData.name,
|
||||
document: customerData.document || ""
|
||||
};
|
||||
|
||||
|
||||
// Update selected customer in form state
|
||||
setSearchParams(prev => ({
|
||||
...prev,
|
||||
@@ -564,21 +577,21 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
/**
|
||||
* Busca cliente por nome
|
||||
*
|
||||
*
|
||||
* @param {string} value - Nome parcial ou completo para busca
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const searchCustomerByName = async (value: string) => {
|
||||
if (!value || value.length < 2) return;
|
||||
|
||||
|
||||
try {
|
||||
const matches = await clientesApi.search(value);
|
||||
if (matches.length > 0) {
|
||||
const c = matches[0];
|
||||
|
||||
|
||||
const clientId = c.id || "";
|
||||
const clientName = c.name || "";
|
||||
|
||||
|
||||
setSearchParams(prev => ({
|
||||
...prev,
|
||||
customerId: clientId,
|
||||
@@ -596,14 +609,14 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
setError("Erro ao buscar cliente. Por favor, tente novamente.");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Criar versão com debounce da função de busca
|
||||
const debouncedSearchCustomer = useDebounce(searchCustomerByName, 500);
|
||||
|
||||
/**
|
||||
* Manipula entrada de filtro de cliente
|
||||
* Identifica o tipo de filtro e direciona para a busca apropriada
|
||||
*
|
||||
*
|
||||
* @param {string} value - Termo de busca (ID, documento ou nome)
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@@ -613,7 +626,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
clearCustomerFields();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Atualiza o campo de nome no estado
|
||||
setSearchParams(prev => ({
|
||||
...prev,
|
||||
@@ -624,11 +637,11 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
// Se ainda está digitando poucas letras, apenas atualiza o estado
|
||||
if (value.length < 2) return;
|
||||
|
||||
|
||||
// Aciona a busca com debounce para evitar chamadas excessivas à API
|
||||
debouncedSearchCustomer(value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Restaura o estado da pesquisa com dados previamente salvos
|
||||
* Útil para preservar o estado ao voltar da página de detalhes
|
||||
@@ -638,12 +651,12 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
setCurrentPage(savedPage);
|
||||
setHasSearched(savedHasSearched);
|
||||
setVisibleOrdersCount(ordersPerPage * savedPage);
|
||||
|
||||
|
||||
// Calcular total de páginas
|
||||
const calculatedTotalPages = Math.ceil(savedOrders.length / ordersPerPage);
|
||||
// Como não temos acesso direto à função setTotalPages, calcular localmente
|
||||
const totalPages = calculatedTotalPages;
|
||||
|
||||
|
||||
// Atualizar pedidos da página atual
|
||||
const indexOfLastOrder = savedPage * ordersPerPage;
|
||||
const indexOfFirstOrder = indexOfLastOrder - ordersPerPage;
|
||||
@@ -671,7 +684,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
|
||||
/**
|
||||
* Manipula a seleção de múltiplos valores em filtros de seleção
|
||||
*
|
||||
*
|
||||
* @param {string} field - Nome do campo no objeto searchParams
|
||||
* @param {string[]} values - Array de valores selecionados
|
||||
*/
|
||||
@@ -716,4 +729,4 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
||||
clearAndNavigateToOrders,
|
||||
handleMultiInputChange
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user