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:
JuruSysadmin
2025-07-25 15:17:36 -03:00
parent a967e2774d
commit 85d202298f
8 changed files with 474 additions and 115 deletions

View File

@@ -23,6 +23,7 @@ import { CustomerSearchInput } from "@/src/components/orders/CustomerSearchInput
import { useCallback, useState, useEffect } from "react"; import { useCallback, useState, useEffect } from "react";
import { User, useAuthValidation } from "../../../hooks/useAuthValidation"; import { User, useAuthValidation } from "../../../hooks/useAuthValidation";
import { SellerSearchInput } from "@/src/components/orders/SellerSearchInput"; import { SellerSearchInput } from "@/src/components/orders/SellerSearchInput";
import { ProductSearchInput } from "@/src/components/orders/ProductSearchInput";
/** /**
* Página de Consulta de Pedidos * Página de Consulta de Pedidos
@@ -161,6 +162,36 @@ export default function FindOrdersPage() {
/> />
</div> </div>
<div className="filter-field">
<ProductSearchInput
id="productSearch"
label="Produto"
placeholder="Buscar por código, nome ou descrição"
value={searchParams.productId || ""}
onChange={(value) => handleInputChange("productId", value)}
onSelect={(product) => {
if (product) {
handleInputChange("productId", product.id);
setSearchParams(prev => ({
...prev,
selectedProduct: product
}));
} else {
handleInputChange("productId", "");
setSearchParams(prev => ({
...prev,
selectedProduct: null
}));
}
}}
selectedProduct={searchParams.selectedProduct || null}
aria-label="Buscar Produto"
/>
</div>
<div className="flex gap-4"> <div className="flex gap-4">
<div className="filter-small-field"> <div className="filter-small-field">
<FilterInput <FilterInput
@@ -413,8 +444,6 @@ export default function FindOrdersPage() {
visibleOrdersCount={visibleOrdersCount} visibleOrdersCount={visibleOrdersCount}
stores={stores} stores={stores}
transfers={[]} transfers={[]}
status={status}
leadtime={leadtime}
/> />
</CardContent> </CardContent>
</Card> </Card>

View File

@@ -20,41 +20,44 @@ import { Badge } from "../../components/ui/badge";
import { ordersApi } from "../../lib/api"; import { ordersApi } from "../../lib/api";
/** /**
* Represents a timeline event in an order's lifecycle * Representa um evento na linha do tempo do ciclo de vida de um pedido
* @typedef {Object} Leadtime
* @property {string} etapas - Descrição da etapa
* @property {string} descricao - Descrição detalhada do evento
* @property {string} date - Data e hora do evento
* @property {string} codigoFuncionario - ID do funcionário responsável
* @property {string} nomeFuncionario - Nome do funcionário responsável
* @property {string} numeroPedido - Número do pedido associado
* @property {LucideIcon} [icon] - Ícone para o evento
* @property {string} [status] - Rótulo de status do evento
* @property {string} [color] - Tema de cor do evento
*/ */
interface Leadtime { interface Leadtime {
/** Description of the stage/step */
etapas: string; etapas: string;
/** Detailed description of the event */
descricao: string; descricao: string;
/** Date and time of the event */
date: string; date: string;
/** Employee ID who handled this step */
codigoFuncionario: string; codigoFuncionario: string;
/** Employee name who handled this step */
nomeFuncionario: string; nomeFuncionario: string;
/** Order number associated with this event */
numeroPedido: string; numeroPedido: string;
/** Icon to display for this event */
icon?: LucideIcon; icon?: LucideIcon;
/** Status label for this event */
status?: string; status?: string;
/** Color theme for this event */
color?: string; color?: string;
} }
/** /**
* Props for the Timeline component * Propriedades do componente Timeline
* @typedef {Object} TimelineProps
* @property {string} [orderId] - ID do pedido para buscar dados da linha do tempo
* @property {string} [className] - Classe CSS opcional
*/ */
interface TimelineProps { interface TimelineProps {
/** Order ID to fetch timeline data for */
orderId?: string; orderId?: string;
/** Optional CSS class name */
className?: string; className?: string;
} }
/** /**
* Configuration for different order status types * Configuração para diferentes tipos de status do pedido
* @type {Record<string, {icon: LucideIcon, color: string, status: string}>}
*/ */
const statusConfig: Record< const statusConfig: Record<
string, string,
@@ -75,7 +78,8 @@ const statusConfig: Record<
}; };
/** /**
* Keywords used to match description text to status types * Palavras-chave usadas para mapear descrições de etapas para tipos de status
* @type {Object}
*/ */
const statusKeywords = { const statusKeywords = {
pedido: ['venda realizada', 'pedido', 'receb'], pedido: ['venda realizada', 'pedido', 'receb'],
@@ -87,9 +91,9 @@ const statusKeywords = {
}; };
/** /**
* Determines the status configuration based on the event description * Determina a configuração de status com base na descrição do evento
* @param descricao - The description text to analyze * @param {string} descricao - Texto da descrição a ser analisado
* @returns The matching status configuration object * @returns {{icon: LucideIcon, color: string, status: string}} Objeto de configuração de status correspondente
*/ */
function getStatusConfig(descricao: string): { icon: LucideIcon; color: string; status: string } { function getStatusConfig(descricao: string): { icon: LucideIcon; color: string; status: string } {
const desc = descricao?.toLowerCase().trim() || ""; const desc = descricao?.toLowerCase().trim() || "";
@@ -102,9 +106,9 @@ function getStatusConfig(descricao: string): { icon: LucideIcon; color: string;
} }
/** /**
* Formats a date string to localized date and time format * Formata uma string de data para o formato local brasileiro (DD/MM/AAAA HH:MM)
* @param dateString - The date string to format * @param {string} dateString - String de data a ser formatada
* @returns Formatted date string in Brazilian format (DD/MM/YYYY HH:MM) * @returns {string} Data formatada
*/ */
function formatDate(dateString: string): string { function formatDate(dateString: string): string {
try { try {
@@ -123,9 +127,9 @@ function formatDate(dateString: string): string {
} }
/** /**
* Formats a date string to show only the time portion * Formata uma string de data para exibir apenas o horário (HH:MM)
* @param dateString - The date string to format * @param {string} dateString - String de data a ser formatada
* @returns Formatted time string in Brazilian format (HH:MM) * @returns {string} Horário formatado
*/ */
function formatTimeOnly(dateString: string): string { function formatTimeOnly(dateString: string): string {
try { try {
@@ -141,10 +145,10 @@ function formatTimeOnly(dateString: string): string {
} }
/** /**
* Maps API data to the Leadtime interface with proper status configuration * Mapeia os dados da API para o formato Leadtime com configuração de status
* @param apiData - Raw API data * @param {any[]} apiData - Dados brutos da API
* @param defaultOrderId - Fallback order ID if not present in API data * @param {string} [defaultOrderId] - ID do pedido padrão caso não esteja presente nos dados
* @returns Array of processed Leadtime objects * @returns {Leadtime[]} Array de objetos Leadtime processados
*/ */
function mapApiDataToLeadtimes(apiData: any[], defaultOrderId: string = ""): Leadtime[] { function mapApiDataToLeadtimes(apiData: any[], defaultOrderId: string = ""): Leadtime[] {
return apiData.map((item) => { return apiData.map((item) => {
@@ -164,7 +168,9 @@ function mapApiDataToLeadtimes(apiData: any[], defaultOrderId: string = ""): Lea
} }
/** /**
* Timeline component that displays the history of events for an order * Componente Timeline que exibe o histórico de eventos de um pedido
* @param {TimelineProps} props
* @returns {JSX.Element}
*/ */
export default function Timeline({ orderId = "", className }: TimelineProps) { export default function Timeline({ orderId = "", className }: TimelineProps) {
const [leadtimes, setLeadtimes] = useState<Leadtime[]>([]); const [leadtimes, setLeadtimes] = useState<Leadtime[]>([]);

View File

@@ -38,6 +38,7 @@ export type ColumnKey =
| "Motorista" | "Motorista"
| "Placa" | "Placa"
const ALL_COLUMNS: ColumnKey[] = [ const ALL_COLUMNS: ColumnKey[] = [
"Data", "Data previsão de entrega", "Agendamento", "Pedido", "Tipo Pedido", "Cliente", "Vendedor", "Filial", "Situação", "Dt Carregamento", "Rota", "Valor", "Peso(kg)", "Carregamento", "Cobrança", "Trasportadora", "Praça", "Nota fiscal", "Dt Faturamento", "TV 7", "Motorista", "Placa" "Data", "Data previsão de entrega", "Agendamento", "Pedido", "Tipo Pedido", "Cliente", "Vendedor", "Filial", "Situação", "Dt Carregamento", "Rota", "Valor", "Peso(kg)", "Carregamento", "Cobrança", "Trasportadora", "Praça", "Nota fiscal", "Dt Faturamento", "TV 7", "Motorista", "Placa"
]; ];
@@ -87,12 +88,10 @@ export function OrdersTable({
}: OrdersTableProps) { }: OrdersTableProps) {
const { getStoreName } = useStoreNameResolver(stores); const { getStoreName } = useStoreNameResolver(stores);
// Find the selected order based on selectedOrderId
const selectedOrder = useMemo(() => const selectedOrder = useMemo(() =>
selectedOrderId ? orders.find(order => order.orderId === selectedOrderId) : undefined selectedOrderId ? orders.find(order => order.orderId === selectedOrderId) : undefined
, [selectedOrderId, orders]); , [selectedOrderId, orders]);
// Use custom hook for order-related data fetching
const { const {
orderStatus, orderStatus,
orderLeadtime, orderLeadtime,
@@ -108,7 +107,6 @@ export function OrdersTable({
"Peso(kg)": (order: Order) => parseFloat(String(order.totalWeigth || "0")), "Peso(kg)": (order: Order) => parseFloat(String(order.totalWeigth || "0")),
"Dt Faturamento": (order: Order) => new Date(order.invoiceDate || ""), "Dt Faturamento": (order: Order) => new Date(order.invoiceDate || ""),
"Dt Carregamento": (order: Order) => new Date(order.shipmentDate || ""), "Dt Carregamento": (order: Order) => new Date(order.shipmentDate || ""),
// Add other column accessors as needed
}), []); }), []);
// Use our custom sort hook // Use our custom sort hook

View File

@@ -7,6 +7,16 @@ import {
import { OrderRowExpandable } from "./tabela-pedidos/components/OrderRowExpandable"; import { OrderRowExpandable } from "./tabela-pedidos/components/OrderRowExpandable";
import { Order } from "@/src/components/types"; import { Order } from "@/src/components/types";
/**
* Propriedades para o componente OrdersTableBody
* @typedef {Object} OrdersTableBodyProps
* @property {Order[]} orders - Lista completa de pedidos
* @property {Order[]} currentOrders - Lista de pedidos filtrados/paginados
* @property {string|null} selectedOrderId - ID do pedido selecionado
* @property {string[]} visibleColumns - Colunas visíveis na tabela
* @property {(storeId?: string) => string} getStoreName - Função para obter o nome da loja
* @property {(orderId: string) => void} handleRowClick - Função chamada ao clicar em uma linha
*/
interface OrdersTableBodyProps { interface OrdersTableBodyProps {
orders: Order[]; orders: Order[];
currentOrders: Order[]; currentOrders: Order[];
@@ -16,7 +26,11 @@ interface OrdersTableBodyProps {
handleRowClick: (orderId: string) => void; handleRowClick: (orderId: string) => void;
} }
// Componente de linha vazia memoizado /**
* Linha vazia exibida quando não há pedidos
* @param {{ colSpan: number }} props
* @returns {JSX.Element}
*/
const EmptyRow = memo(({ colSpan }: { colSpan: number }) => ( const EmptyRow = memo(({ colSpan }: { colSpan: number }) => (
<TableRow> <TableRow>
<TableCell colSpan={colSpan} className="h-24 text-center text-xs"> <TableCell colSpan={colSpan} className="h-24 text-center text-xs">
@@ -25,7 +39,11 @@ const EmptyRow = memo(({ colSpan }: { colSpan: number }) => (
</TableRow> </TableRow>
)); ));
// Componente de linha de pedido memoizado /**
* Linha de pedido individual, expansível
* @param {{ order: Order, isSelected: boolean, visibleColumns: string[], onSelect: (orderId: string) => void, getStoreName: (storeId?: string) => string }} props
* @returns {JSX.Element}
*/
const OrderRow = memo(({ const OrderRow = memo(({
order, order,
isSelected, isSelected,
@@ -39,11 +57,11 @@ const OrderRow = memo(({
onSelect: (orderId: string) => void; onSelect: (orderId: string) => void;
getStoreName: (storeId?: string) => string; getStoreName: (storeId?: string) => string;
}) => { }) => {
// Create a new order object with the store name only (without ID prefix) // Cria um novo objeto de pedido com o nome da loja
const orderWithStore = { const orderWithStore = {
...order, ...order,
store: getStoreName(order.storeId), store: getStoreName(order.storeId),
storeId: order.storeId, // Preserve original storeId storeId: order.storeId, // Mantém o storeId original
}; };
return ( return (
@@ -60,7 +78,11 @@ const OrderRow = memo(({
); );
}); });
// Componente principal memoizado /**
* Corpo da tabela de pedidos, renderiza linhas de pedidos ou linha vazia
* @param {OrdersTableBodyProps} props
* @returns {JSX.Element}
*/
function OrdersTableBodyComponent({ function OrdersTableBodyComponent({
orders, orders,
currentOrders, currentOrders,
@@ -69,7 +91,7 @@ function OrdersTableBodyComponent({
getStoreName, getStoreName,
handleRowClick, handleRowClick,
}: OrdersTableBodyProps) { }: OrdersTableBodyProps) {
// Renderização condicional baseada na presença de orders, memoizada // Renderização condicional baseada na presença de pedidos
const content = useMemo(() => { const content = useMemo(() => {
if (orders.length === 0) { if (orders.length === 0) {
return <EmptyRow colSpan={visibleColumns.length} />; return <EmptyRow colSpan={visibleColumns.length} />;
@@ -90,4 +112,8 @@ function OrdersTableBodyComponent({
return <TableBody>{content}</TableBody>; return <TableBody>{content}</TableBody>;
} }
/**
* Exporta o componente memoizado do corpo da tabela de pedidos
* @type {React.NamedExoticComponent<OrdersTableBodyProps>}
*/
export const OrdersTableBody = memo(OrdersTableBodyComponent); export const OrdersTableBody = memo(OrdersTableBodyComponent);

View File

@@ -0,0 +1,256 @@
"use client";
import * as React from "react";
import { Check, ChevronsUpDown, Package, Loader2, X } from "lucide-react";
import { cn } from "@/src/lib/utils";
import { Button } from "@/src/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/src/components/ui/command";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/src/components/ui/popover";
import { dataConsultApi } from "@/src/lib/api";
import { Product } from "@/src/components/types";
import { Label } from "@/src/components/ui/label";
import { Badge } from "@/src/components/ui/badge";
interface ProductSearchInputProps {
id: string;
label: string;
placeholder: string;
value: string;
onChange: (value: string) => void;
onSelect: (product: Product | null) => void;
selectedProduct: Product | null;
disabled?: boolean;
"aria-label"?: string;
}
/**
* Componente de busca de produtos com autocompletar
* Permite buscar produtos por código, nome ou descrição
*/
export function ProductSearchInput({
id,
label,
placeholder,
value,
onChange,
onSelect,
selectedProduct,
disabled = false,
"aria-label": ariaLabel,
}: ProductSearchInputProps) {
const [open, setOpen] = React.useState(false);
const [products, setProducts] = React.useState<Product[]>([]);
const [loading, setLoading] = React.useState(false);
const [searchQuery, setSearchQuery] = React.useState("");
const [searchError, setSearchError] = React.useState<string | null>(null);
const searchInputRef = React.useRef<HTMLInputElement>(null);
// Buscar produtos baseado na query
const searchProducts = React.useCallback(async (query: string) => {
if (!query || query.length < 2) {
setProducts([]);
return;
}
try {
setLoading(true);
setSearchError(null);
const response = await dataConsultApi.getProducts(query);
if (response.success && response.data && response.data.length > 0) {
// Mapear os dados da API para o formato Product
const mappedProducts = response.data.map((product: any) => ({
id: product.id?.toString() || "",
code: product.manufacturerCode || "",
name: product.description || product.name || "",
description: product.description || product.name || "",
brand: product.brand || "",
department: product.department || "",
color: product.color || "",
}));
setProducts(mappedProducts.slice(0, 50)); // Limitar a 50 resultados
} else {
setSearchError(`Nenhum produto encontrado para "${query}"`);
setProducts([]);
}
} catch (error) {
console.error("Erro ao buscar produtos:", error);
setSearchError("Erro ao buscar produtos");
setProducts([]);
} finally {
setLoading(false);
}
}, []);
// Debounce para a busca
React.useEffect(() => {
const timer = setTimeout(() => {
if (open && searchQuery.length >= 2) {
searchProducts(searchQuery);
}
}, 300);
return () => clearTimeout(timer);
}, [searchQuery, searchProducts, open]);
// Selecionar produto
const handleSelectProduct = (product: Product) => {
onSelect(product);
setOpen(false);
setSearchQuery("");
};
// Limpar seleção
const handleClearSelection = (e?: React.MouseEvent) => {
if (e) {
e.stopPropagation();
}
onSelect(null);
onChange("");
setSearchQuery("");
setProducts([]);
};
// Quando o componente monta ou o valor muda
React.useEffect(() => {
// Se temos um value mas não temos selectedProduct, executar busca inicial
if (value && !selectedProduct && !loading && !open) {
searchProducts(value);
}
}, [value, selectedProduct, searchProducts, loading, open]);
return (
<div className="flex flex-col space-y-1">
<div className="flex justify-between items-center">
<Label
htmlFor={id}
className="text-xs font-medium"
>
{label}
{selectedProduct && (
<Badge variant="outline" className="ml-2 text-xs py-0">
{selectedProduct.code ? `Cód: ${selectedProduct.code}` : `ID: ${selectedProduct.id}`}
</Badge>
)}
</Label>
</div>
{searchError && (
<p className="text-xs text-red-500 mt-0.5">{searchError}</p>
)}
<div className="relative">
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
aria-label={ariaLabel || "Selecione um produto"}
disabled={disabled}
className={cn(
"w-full justify-between h-8 transition-all",
selectedProduct ? "pr-8" : "text-muted-foreground",
disabled && "opacity-50 cursor-not-allowed"
)}
>
{selectedProduct ? (
<div className="flex items-center gap-2 overflow-hidden">
<Package className="h-4 w-4 shrink-0" />
<span className="truncate">
{selectedProduct.name}
{selectedProduct.code ? ` (${selectedProduct.code})` : ""}
</span>
</div>
) : (
<span className="truncate">{placeholder}</span>
)}
{selectedProduct ? null : (
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
)}
</Button>
</PopoverTrigger>
{selectedProduct && (
<div
className="absolute right-0 top-0 h-full flex items-center pr-2"
onClick={(e) => {
e.stopPropagation();
handleClearSelection();
}}
>
<X className="h-4 w-4 cursor-pointer" />
<span className="sr-only">Limpar seleção</span>
</div>
)}
<PopoverContent className="min-w-[400px] p-0">
<Command>
<CommandInput
ref={searchInputRef}
placeholder="Buscar produto por código, nome ou descrição..."
value={searchQuery}
onValueChange={setSearchQuery}
className="h-9"
/>
{loading && (
<div className="flex items-center justify-center py-6">
<Loader2 className="h-6 w-6 animate-spin text-gray-400" />
</div>
)}
{!loading && (
<>
<CommandEmpty>
{searchQuery.length >= 2
? "Nenhum produto encontrado com esse termo"
: "Digite pelo menos 2 caracteres para buscar"}
</CommandEmpty>
{products.length > 0 && (
<CommandGroup heading="Produtos">
<CommandList>
{products.map((product, index) => (
<CommandItem
key={product.id || product.code || `product-${index}`}
value={product.name}
onSelect={() => handleSelectProduct(product)}
>
<Package className="mr-2 h-4 w-4" />
<div className="flex flex-col">
<span className="font-medium">{product.name}</span>
<div className="flex gap-2 text-xs text-gray-500">
{product.code && (
<span>Cód: {product.code}</span>
)}
{product.brand && (
<span>Marca: {product.brand}</span>
)}
{product.department && (
<span>Depto: {product.department}</span>
)}
</div>
</div>
</CommandItem>
))}
</CommandList>
</CommandGroup>
)}
</>
)}
</Command>
</PopoverContent>
</Popover>
</div>
</div>
);
}

View File

@@ -18,6 +18,18 @@ export interface TimelineEvent {
user?: string; user?: string;
} }
export interface productsSearchParams {
productId?: string;
description?: string;
pacth?: string;
color?: string;
stockId?: string;
quantity?: string;
salePrice?: string;
department?: string;
brand?: string;
}
export interface cutitens { export interface cutitens {
productId: number; productId: number;
description: string; description: string;
@@ -202,6 +214,16 @@ export type PaymentStatus =
document?: string; document?: string;
} }
export interface Product {
id: string;
code: string;
name: string;
description?: string;
brand?: string;
department?: string;
color?: string;
}
/** /**
@@ -241,6 +263,8 @@ export interface OrderSearchParams {
deliveryLocal?: string; deliveryLocal?: string;
/** ID do vendedor */ /** ID do vendedor */
sellerId?: string | number; sellerId?: string | number;
/** Nome do vendedor */
sellerName?: string;
/** Documento do cliente (CPF/CNPJ) - duplicado para compatibilidade */ /** Documento do cliente (CPF/CNPJ) - duplicado para compatibilidade */
document?: string; document?: string;
/** Número da nota fiscal */ /** Número da nota fiscal */
@@ -251,6 +275,10 @@ export interface OrderSearchParams {
invoiceId?: string; invoiceId?: string;
/** Número da nota fiscal (NFe) */ /** Número da nota fiscal (NFe) */
nfe?: string; nfe?: string;
/** ID do produto para busca */
productId?: string;
/** Produto selecionado pelo componente de busca */
selectedProduct?: Product | null;
} }
export interface CustomerSearchParams { export interface CustomerSearchParams {

View File

@@ -84,7 +84,8 @@ const paramMapping: Record<string, keyof OrderSearchParams> = {
createDateEnd: "createDateEnd", createDateEnd: "createDateEnd",
customerId: "customerId", customerId: "customerId",
document: "document", document: "document",
invoiceNumber: "invoiceNumber" invoiceNumber: "invoiceNumber",
productId: "productId"
}; };
/** /**
@@ -159,6 +160,15 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
})); }));
}, []); }, []);
// 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 // 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 // e há parâmetros de pesquisa na URL ou se estamos voltando da página de detalhes
useEffect(() => { useEffect(() => {
@@ -237,10 +247,13 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
// Transform the ALL value to empty string for the API call // Transform the ALL value to empty string for the API call
const paramsToSend: OrderSearchParams = { ...searchParams }; 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) { if (paramsToSend.selectedCustomer) {
delete paramsToSend.selectedCustomer; delete paramsToSend.selectedCustomer;
} }
if (paramsToSend.selectedProduct) {
delete paramsToSend.selectedProduct;
}
// Se tiver customerId definido, remover name e document para evitar conflito // Se tiver customerId definido, remover name e document para evitar conflito
if (paramsToSend.customerId) { if (paramsToSend.customerId) {

View File

@@ -2,7 +2,10 @@ import { leadtime } from "../components/types";
import { Cliente } from "../components/types"; import { Cliente } from "../components/types";
// URL base da API // URL base da API
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "https://portalapi.jurunense.com"; //const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "https://portalapi.jurunense.com";
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://10.1.1.212:8805";
/** /**
* Classe de erro personalizada para requisições de API. * Classe de erro personalizada para requisições de API.
@@ -179,10 +182,10 @@ export const dataConsultApi = {
/** /**
* @param {string} filter - Filtro de produto (nome ou código). * @param {string} filter - Filtro de produto (nome ou código).
* @returns {Promise<any[]>} Produtos filtrados. * @returns {Promise<{success: boolean, data: any[]}>} Produtos filtrados.
*/ */
getProducts: (filter: string) => getProducts: (filter: string) =>
fetchApi<any[]>(`/api/v1/data-consult/products/${filter}`), fetchApi<{ success: boolean; data: any[] }>(`/api/v1/data-consult/products/${filter}`),
/** @returns {Promise<any[]>} Todos os produtos */ /** @returns {Promise<any[]>} Todos os produtos */
getAllProducts: () => fetchApi<any[]>("/api/v1/data-consult/all"), getAllProducts: () => fetchApi<any[]>("/api/v1/data-consult/all"),