Ajuste na coluna de pedidos
This commit is contained in:
@@ -230,6 +230,7 @@ export function OrderDetail({ order, timelineEvents }: OrderDetailProps) {
|
|||||||
} else if (window.history.length > 2) {
|
} else if (window.history.length > 2) {
|
||||||
goBack();
|
goBack();
|
||||||
} else {
|
} else {
|
||||||
|
// Usar a função que limpa parâmetros ao navegar para orders/find
|
||||||
goToOrdersFind();
|
goToOrdersFind();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
DropdownMenuCheckboxItem,
|
DropdownMenuCheckboxItem,
|
||||||
} from "@/src/components/ui/dropdown-menu";
|
} from "@/src/components/ui/dropdown-menu";
|
||||||
|
import { useOrderItemTableColumns } from "@/src/hooks/useOrderItemTableColumns";
|
||||||
|
import { NewColumnsNotification } from "@/src/components/ui/NewColumnsNotification";
|
||||||
|
|
||||||
interface Item {
|
interface Item {
|
||||||
quantity: number | null | undefined;
|
quantity: number | null | undefined;
|
||||||
@@ -58,180 +60,23 @@ export function OrderItemsTable({
|
|||||||
itemsError,
|
itemsError,
|
||||||
onViewDetails,
|
onViewDetails,
|
||||||
}: OrderItemsTableProps) {
|
}: OrderItemsTableProps) {
|
||||||
// Carregar as colunas visíveis do localStorage na inicialização
|
const {
|
||||||
const initVisibleColumns = () => {
|
visibleColumns,
|
||||||
try {
|
columnOrder,
|
||||||
const saved = localStorage.getItem('visibleOrderItemColumns');
|
getColumnClass,
|
||||||
if (saved) {
|
getOrderedVisibleColumns,
|
||||||
const parsed = JSON.parse(saved);
|
resetColumnOrder,
|
||||||
if (Array.isArray(parsed) && parsed.length > 0) {
|
toggleColumn,
|
||||||
return parsed;
|
selectAllColumns,
|
||||||
}
|
unselectAllColumns,
|
||||||
}
|
isColumnVisible,
|
||||||
} catch (error) {
|
handleDragStart,
|
||||||
console.error('Erro ao carregar configurações de colunas:', error);
|
handleDragEnd,
|
||||||
}
|
handleDragOver,
|
||||||
return ALL_COLUMNS;
|
handleDrop,
|
||||||
};
|
newColumnsDetected,
|
||||||
|
dismissNewColumnsNotification,
|
||||||
// Inicializar a ordem das colunas
|
} = useOrderItemTableColumns(ALL_COLUMNS);
|
||||||
const initColumnOrder = () => {
|
|
||||||
try {
|
|
||||||
const saved = localStorage.getItem('orderItemColumnsOrder');
|
|
||||||
if (saved) {
|
|
||||||
const parsed = JSON.parse(saved);
|
|
||||||
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao carregar ordem das colunas:', error);
|
|
||||||
}
|
|
||||||
return ALL_COLUMNS;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estado para controlar quais colunas estão visíveis
|
|
||||||
const [visibleColumns, setVisibleColumns] = useState<string[]>(initVisibleColumns);
|
|
||||||
// Estado para controlar a ordem das colunas
|
|
||||||
const [columnOrder, setColumnOrder] = useState<string[]>(initColumnOrder);
|
|
||||||
// Estado para rastrear coluna sendo arrastada
|
|
||||||
const [draggedColumn, setDraggedColumn] = useState<string | null>(null);
|
|
||||||
|
|
||||||
// Salvar as colunas visíveis no localStorage sempre que elas mudarem
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
localStorage.setItem('visibleOrderItemColumns', JSON.stringify(visibleColumns));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao salvar configurações de colunas:', error);
|
|
||||||
}
|
|
||||||
}, [visibleColumns]);
|
|
||||||
|
|
||||||
// Salvar a ordem das colunas no localStorage
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
localStorage.setItem('orderItemColumnsOrder', JSON.stringify(columnOrder));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao salvar ordem das colunas:', error);
|
|
||||||
}
|
|
||||||
}, [columnOrder]);
|
|
||||||
|
|
||||||
// Função para alternar a visibilidade de uma coluna
|
|
||||||
const toggleColumn = (column: string) => {
|
|
||||||
setVisibleColumns((current) => {
|
|
||||||
if (current.includes(column)) {
|
|
||||||
return current.filter((c) => c !== column);
|
|
||||||
} else {
|
|
||||||
return [...current, column];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Função para selecionar todas as colunas
|
|
||||||
const selectAllColumns = () => {
|
|
||||||
setVisibleColumns(ALL_COLUMNS);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Função para desmarcar todas as colunas
|
|
||||||
const unselectAllColumns = () => {
|
|
||||||
// Mantém pelo menos uma coluna para garantir que a tabela não fique vazia
|
|
||||||
setVisibleColumns(["Código"]);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Função para verificar se uma coluna está visível
|
|
||||||
const isColumnVisible = (column: string) => visibleColumns.includes(column);
|
|
||||||
|
|
||||||
// Funções para drag & drop
|
|
||||||
const handleDragStart = (e: React.DragEvent<HTMLDivElement>, column: string) => {
|
|
||||||
setDraggedColumn(column);
|
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
|
||||||
e.dataTransfer.setData('text/plain', column);
|
|
||||||
|
|
||||||
// Adicionar um estilo visual para o elemento sendo arrastado
|
|
||||||
if (e.currentTarget) {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (e.currentTarget) {
|
|
||||||
e.currentTarget.classList.add('opacity-50');
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDragEnd = (e: React.DragEvent<HTMLDivElement>) => {
|
|
||||||
setDraggedColumn(null);
|
|
||||||
e.currentTarget.classList.remove('opacity-50');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.dataTransfer.dropEffect = 'move';
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDrop = (e: React.DragEvent<HTMLDivElement>, targetColumn: string) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (!draggedColumn || draggedColumn === targetColumn) return;
|
|
||||||
|
|
||||||
// Reordenar as colunas
|
|
||||||
const newColumnOrder = [...columnOrder];
|
|
||||||
const draggedIndex = newColumnOrder.indexOf(draggedColumn);
|
|
||||||
const targetIndex = newColumnOrder.indexOf(targetColumn);
|
|
||||||
|
|
||||||
if (draggedIndex !== -1 && targetIndex !== -1) {
|
|
||||||
newColumnOrder.splice(draggedIndex, 1);
|
|
||||||
newColumnOrder.splice(targetIndex, 0, draggedColumn);
|
|
||||||
setColumnOrder(newColumnOrder);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getColumnClass = (title: string) => {
|
|
||||||
const textRight = ["Preço Unitário", "Preço Total", "Quantidade"];
|
|
||||||
const cellWidth: { [key: string]: string } = {
|
|
||||||
"Código": "w-20",
|
|
||||||
"Descrição": "w-56",
|
|
||||||
"Embalagem": "w-24",
|
|
||||||
"Cor": "w-20",
|
|
||||||
"F. Estoque": "w-24",
|
|
||||||
"Tipo Entrega": "w-28",
|
|
||||||
"Quantidade": "w-24",
|
|
||||||
"Preço Unitário": "w-24",
|
|
||||||
"Preço Total": "w-24",
|
|
||||||
"Departamento": "w-48",
|
|
||||||
"Marca": "w-24",
|
|
||||||
};
|
|
||||||
|
|
||||||
let classes = "";
|
|
||||||
|
|
||||||
// Não aplicar whitespace-nowrap para Departamento
|
|
||||||
if (title !== "Departamento") {
|
|
||||||
classes += "whitespace-nowrap ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alinhar à direita
|
|
||||||
if (textRight.includes(title)) {
|
|
||||||
classes += "text-right ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aplicar larguras
|
|
||||||
if (cellWidth[title]) {
|
|
||||||
classes += cellWidth[title] + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
return classes;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Função para ordenar as colunas visíveis na ordem definida pelo usuário
|
|
||||||
const getOrderedVisibleColumns = () => {
|
|
||||||
// Primeiro, filtrar as colunas que são visíveis
|
|
||||||
const visibleColumnSet = new Set(visibleColumns);
|
|
||||||
|
|
||||||
// Depois, ordenar as colunas de acordo com a ordem definida pelo usuário
|
|
||||||
return columnOrder.filter(column => visibleColumnSet.has(column));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Resetar a ordem das colunas
|
|
||||||
const resetColumnOrder = () => {
|
|
||||||
setColumnOrder(ALL_COLUMNS);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEvent = (e: React.SyntheticEvent) => {
|
const handleEvent = (e: React.SyntheticEvent) => {
|
||||||
const element = e.currentTarget;
|
const element = e.currentTarget;
|
||||||
@@ -261,6 +106,10 @@ const handleEvent = (e: React.SyntheticEvent) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border-0">
|
<div className="rounded-md border-0">
|
||||||
|
<NewColumnsNotification
|
||||||
|
newColumns={newColumnsDetected}
|
||||||
|
onDismiss={dismissNewColumnsNotification}
|
||||||
|
/>
|
||||||
<div className="flex justify-end mb-2 gap-2">
|
<div className="flex justify-end mb-2 gap-2">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { SelectedOrderItems } from "./SelectedOrderItems";
|
|||||||
import { RefreshCw, ChevronLeft, ChevronRight } from "lucide-react";
|
import { RefreshCw, ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import { useOrderData } from "../../../src/hooks/useOrderData";
|
import { useOrderData } from "../../../src/hooks/useOrderData";
|
||||||
import { useSort } from "@/src/hooks/useSort";
|
import { useSort } from "@/src/hooks/useSort";
|
||||||
|
import { NewColumnsNotification } from "@/src/components/ui/NewColumnsNotification";
|
||||||
|
|
||||||
export type ColumnKey =
|
export type ColumnKey =
|
||||||
| "Data"
|
| "Data"
|
||||||
@@ -28,14 +29,17 @@ export type ColumnKey =
|
|||||||
| "Valor"
|
| "Valor"
|
||||||
| "Peso(kg)"
|
| "Peso(kg)"
|
||||||
| "Carregamento"
|
| "Carregamento"
|
||||||
|
| "Dt Carregamento"
|
||||||
| "Cobrança"
|
| "Cobrança"
|
||||||
| "Trasportadora"
|
| "Trasportadora"
|
||||||
| "Praça"
|
| "Praça"
|
||||||
| "Nota fiscal"
|
| "Nota fiscal"
|
||||||
| "Dt Faturamento"
|
| "Dt Faturamento"
|
||||||
|
| "Motorista"
|
||||||
|
| "Placa"
|
||||||
|
|
||||||
const ALL_COLUMNS: ColumnKey[] = [
|
const ALL_COLUMNS: ColumnKey[] = [
|
||||||
"Data", "Data previsão de entrega", "Agendamento", "Pedido", "Tipo Pedido", "Cliente", "Vendedor", "Filial", "Situação", "Rota", "Valor", "Peso(kg)", "Carregamento", "Cobrança", "Trasportadora", "Praça", "Nota fiscal", "Dt Faturamento", "TV 7"
|
"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"
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface OrdersTableProps {
|
export interface OrdersTableProps {
|
||||||
@@ -103,6 +107,7 @@ export function OrdersTable({
|
|||||||
"Valor": (order: Order) => parseFloat(String(order.totalValue || "0")),
|
"Valor": (order: Order) => parseFloat(String(order.totalValue || "0")),
|
||||||
"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 || ""),
|
||||||
// Add other column accessors as needed
|
// Add other column accessors as needed
|
||||||
}), []);
|
}), []);
|
||||||
|
|
||||||
@@ -126,6 +131,8 @@ export function OrdersTable({
|
|||||||
handleDragEnd,
|
handleDragEnd,
|
||||||
handleDragOver,
|
handleDragOver,
|
||||||
handleDrop,
|
handleDrop,
|
||||||
|
newColumnsDetected,
|
||||||
|
dismissNewColumnsNotification,
|
||||||
} = useOrderTableColumns(ALL_COLUMNS);
|
} = useOrderTableColumns(ALL_COLUMNS);
|
||||||
|
|
||||||
const { tableRef } = useKeyboardNavigation({
|
const { tableRef } = useKeyboardNavigation({
|
||||||
@@ -248,6 +255,10 @@ export function OrdersTable({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-md border-0" ref={tableRef} tabIndex={0}>
|
<div className="rounded-md border-0" ref={tableRef} tabIndex={0}>
|
||||||
|
<NewColumnsNotification
|
||||||
|
newColumns={newColumnsDetected}
|
||||||
|
onDismiss={dismissNewColumnsNotification}
|
||||||
|
/>
|
||||||
{renderHeaderControls()}
|
{renderHeaderControls()}
|
||||||
{renderOrdersTable()}
|
{renderOrdersTable()}
|
||||||
<SelectedOrderItems
|
<SelectedOrderItems
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const ColumnHeader = memo(({
|
|||||||
onSort?: (column: string) => void;
|
onSort?: (column: string) => void;
|
||||||
}) => {
|
}) => {
|
||||||
// Determinar se esta coluna é ordenável
|
// Determinar se esta coluna é ordenável
|
||||||
const isSortable = ["Data", "Valor", "Peso(kg)", "Pedido", "Dt Faturamento"].includes(title);
|
const isSortable = ["Data", "Valor", "Peso(kg)", "Pedido", "Dt Faturamento", "Dt Carregamento"].includes(title);
|
||||||
|
|
||||||
// Verificar se esta coluna está sendo ordenada
|
// Verificar se esta coluna está sendo ordenada
|
||||||
const isSorted = sortConfig && sortConfig.key === title;
|
const isSorted = sortConfig && sortConfig.key === title;
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ export const orderCellRenderers: Record<OrderColumn, React.FC<CellRenderProps>>
|
|||||||
[OrderColumn.Value]: ({ order }) => <>{formatCurrency(order.amount || 0)}</>,
|
[OrderColumn.Value]: ({ order }) => <>{formatCurrency(order.amount || 0)}</>,
|
||||||
[OrderColumn.Weight]: ({ order }) => <>{order.totalWeigth}</>,
|
[OrderColumn.Weight]: ({ order }) => <>{order.totalWeigth}</>,
|
||||||
[OrderColumn.Shipment]: ({ order }) => <>{order.shipmentId}</>,
|
[OrderColumn.Shipment]: ({ order }) => <>{order.shipmentId}</>,
|
||||||
|
[OrderColumn.ShipmentDate]: ({ order }) => <>{formatDateSafe(order.shipmentDate)}</>,
|
||||||
[OrderColumn.Billing]: ({ order }) => <>{order.billingName}</>,
|
[OrderColumn.Billing]: ({ order }) => <>{order.billingName}</>,
|
||||||
[OrderColumn.Carrier]: ({ order }) => <>{order.carrier}</>,
|
[OrderColumn.Carrier]: ({ order }) => <>{order.carrier}</>,
|
||||||
[OrderColumn.Place]: ({ order }) => <>{order.deliveryLocal}</>,
|
[OrderColumn.Place]: ({ order }) => <>{order.deliveryLocal}</>,
|
||||||
@@ -89,4 +90,6 @@ export const orderCellRenderers: Record<OrderColumn, React.FC<CellRenderProps>>
|
|||||||
[OrderColumn.InvoiceDate]: ({ order }) => <>{formatDateSafe(order.invoiceDate)}</>,
|
[OrderColumn.InvoiceDate]: ({ order }) => <>{formatDateSafe(order.invoiceDate)}</>,
|
||||||
[OrderColumn.DeliveryDate]: ({ order }) => <>{order.deliveryDate ? formatDateSafe(order.deliveryDate) : "-"}</>,
|
[OrderColumn.DeliveryDate]: ({ order }) => <>{order.deliveryDate ? formatDateSafe(order.deliveryDate) : "-"}</>,
|
||||||
[OrderColumn.SchedulerDelivery]: ({ order }) => <>{order.schedulerDelivery || "-"}</>,
|
[OrderColumn.SchedulerDelivery]: ({ order }) => <>{order.schedulerDelivery || "-"}</>,
|
||||||
|
[OrderColumn.Driver]: ({ order }) => <>{order.driver || "-"}</>,
|
||||||
|
[OrderColumn.CarIdentification]: ({ order }) => <>{order.carIdentification || "-"}</>,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,10 +15,13 @@ export const columnClasses: Record<OrderColumn, string> = {
|
|||||||
[OrderColumn.Value]: "p-2 whitespace-nowrap text-right border-r border-gray-200 text-xs",
|
[OrderColumn.Value]: "p-2 whitespace-nowrap text-right border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.Weight]: "p-2 whitespace-nowrap text-right border-r border-gray-200 text-xs",
|
[OrderColumn.Weight]: "p-2 whitespace-nowrap text-right border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.Shipment]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
[OrderColumn.Shipment]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
|
[OrderColumn.ShipmentDate]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.Billing]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
[OrderColumn.Billing]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.Carrier]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
[OrderColumn.Carrier]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.Place]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
[OrderColumn.Place]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.Invoice]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
[OrderColumn.Invoice]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.InvoiceDate]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
[OrderColumn.InvoiceDate]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
[OrderColumn.DeliveryDate]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
[OrderColumn.DeliveryDate]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
|
[OrderColumn.Driver]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
|
[OrderColumn.CarIdentification]: "p-2 whitespace-nowrap border-r border-gray-200 text-xs",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,10 +15,13 @@ export enum OrderColumn {
|
|||||||
Value = "Valor",
|
Value = "Valor",
|
||||||
Weight = "Peso(kg)",
|
Weight = "Peso(kg)",
|
||||||
Shipment = "Carregamento",
|
Shipment = "Carregamento",
|
||||||
|
ShipmentDate = "Dt Carregamento",
|
||||||
Billing = "Cobrança",
|
Billing = "Cobrança",
|
||||||
Carrier = "Trasportadora",
|
Carrier = "Trasportadora",
|
||||||
Place = "Praça",
|
Place = "Praça",
|
||||||
Invoice = "Nota fiscal",
|
Invoice = "Nota fiscal",
|
||||||
InvoiceDate = "Dt Faturamento"
|
InvoiceDate = "Dt Faturamento",
|
||||||
|
Driver = "Motorista",
|
||||||
|
CarIdentification = "Placa"
|
||||||
}
|
}
|
||||||
|
|
||||||
29
src/components/ui/ClearAndNavigateButton.tsx
Normal file
29
src/components/ui/ClearAndNavigateButton.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { Button } from "@/src/components/ui/button";
|
||||||
|
import { useOrderSearch } from "@/src/hooks/useOrderSearch";
|
||||||
|
|
||||||
|
interface ClearAndNavigateButtonProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link";
|
||||||
|
size?: "default" | "sm" | "lg" | "icon";
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ClearAndNavigateButton({
|
||||||
|
children,
|
||||||
|
variant = "outline",
|
||||||
|
size = "default",
|
||||||
|
className
|
||||||
|
}: ClearAndNavigateButtonProps) {
|
||||||
|
const { clearAndNavigateToOrders } = useOrderSearch(8);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant={variant}
|
||||||
|
size={size}
|
||||||
|
onClick={clearAndNavigateToOrders}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
37
src/components/ui/NewColumnsNotification.tsx
Normal file
37
src/components/ui/NewColumnsNotification.tsx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { Alert, AlertDescription } from "@/src/components/ui/alert";
|
||||||
|
import { X, Info } from "lucide-react";
|
||||||
|
import { Button } from "@/src/components/ui/button";
|
||||||
|
|
||||||
|
interface NewColumnsNotificationProps {
|
||||||
|
newColumns: string[];
|
||||||
|
onDismiss: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NewColumnsNotification({ newColumns, onDismiss }: NewColumnsNotificationProps) {
|
||||||
|
if (newColumns.length === 0) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert className="mb-4 border-blue-200 bg-blue-50">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="flex items-start gap-2">
|
||||||
|
<Info className="h-4 w-4 text-blue-600 mt-0.5" />
|
||||||
|
<AlertDescription className="text-blue-800">
|
||||||
|
<span className="font-medium">Novas colunas detectadas:</span>{" "}
|
||||||
|
{newColumns.join(", ")}.
|
||||||
|
<span className="text-blue-600 text-sm">
|
||||||
|
{" "}Elas foram automaticamente adicionadas à sua visualização.
|
||||||
|
</span>
|
||||||
|
</AlertDescription>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={onDismiss}
|
||||||
|
className="h-6 w-6 p-0 text-blue-600 hover:text-blue-800 hover:bg-blue-100"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -27,6 +27,16 @@ export function useNavigation() {
|
|||||||
router.push("/orders/find");
|
router.push("/orders/find");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Função para navegar para orders/find limpando parâmetros da URL
|
||||||
|
const goToOrdersFindClean = () => {
|
||||||
|
router.push("/orders/find");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Função para navegar para outras páginas limpando parâmetros
|
||||||
|
const navigateToClean = (path: string) => {
|
||||||
|
router.push(path);
|
||||||
|
};
|
||||||
|
|
||||||
// Helper to build URL with search params
|
// Helper to build URL with search params
|
||||||
const buildUrl = (base: string, params: Record<string, string>) => {
|
const buildUrl = (base: string, params: Record<string, string>) => {
|
||||||
const url = new URL(base, window.location.origin);
|
const url = new URL(base, window.location.origin);
|
||||||
@@ -46,6 +56,8 @@ export function useNavigation() {
|
|||||||
goBack,
|
goBack,
|
||||||
goToHome,
|
goToHome,
|
||||||
goToOrdersFind,
|
goToOrdersFind,
|
||||||
|
goToOrdersFindClean,
|
||||||
|
navigateToClean,
|
||||||
buildUrl
|
buildUrl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
52
src/hooks/useOrderItemTableColumns.ts
Normal file
52
src/hooks/useOrderItemTableColumns.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { useCallback } from "react";
|
||||||
|
import { useTableColumns } from "./useTableColumns";
|
||||||
|
|
||||||
|
export function useOrderItemTableColumns(allColumns: string[]) {
|
||||||
|
const tableColumns = useTableColumns({
|
||||||
|
allColumns,
|
||||||
|
storageKey: "OrderItem",
|
||||||
|
defaultVisibleColumns: allColumns,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Memoizar as classes de colunas para evitar recálculos desnecessários
|
||||||
|
const getColumnClass = useCallback((title: string) => {
|
||||||
|
const textRight = ["Preço Unitário", "Preço Total", "Quantidade"];
|
||||||
|
const cellWidth: { [key: string]: string } = {
|
||||||
|
"Código": "w-20",
|
||||||
|
"Descrição": "w-56",
|
||||||
|
"Embalagem": "w-24",
|
||||||
|
"Cor": "w-20",
|
||||||
|
"F. Estoque": "w-24",
|
||||||
|
"Tipo Entrega": "w-28",
|
||||||
|
"Quantidade": "w-24",
|
||||||
|
"Preço Unitário": "w-24",
|
||||||
|
"Preço Total": "w-24",
|
||||||
|
"Departamento": "w-48",
|
||||||
|
"Marca": "w-24",
|
||||||
|
};
|
||||||
|
|
||||||
|
let classes = "";
|
||||||
|
|
||||||
|
// Não aplicar whitespace-nowrap para Departamento
|
||||||
|
if (title !== "Departamento") {
|
||||||
|
classes += "whitespace-nowrap ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alinhar à direita
|
||||||
|
if (textRight.includes(title)) {
|
||||||
|
classes += "text-right ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplicar larguras
|
||||||
|
if (cellWidth[title]) {
|
||||||
|
classes += cellWidth[title] + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...tableColumns,
|
||||||
|
getColumnClass,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import { extractApiData } from "@/src/utils/api-helpers";
|
|||||||
import { useSearchParams, useRouter } from "next/navigation";
|
import { useSearchParams, useRouter } from "next/navigation";
|
||||||
import { clientesApi } from "@/src/lib/api"
|
import { clientesApi } from "@/src/lib/api"
|
||||||
import { setStorage, getStorage } from "@/src/utils/storage";
|
import { setStorage, getStorage } from "@/src/utils/storage";
|
||||||
|
import { clearUrlAndNavigate } from "@/src/utils/url-helpers";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Função de utilidade para aplicar debounce em funções
|
* Função de utilidade para aplicar debounce em funções
|
||||||
@@ -66,6 +67,7 @@ interface UseOrderSearchReturn {
|
|||||||
handleCustomerFilter: (value: string) => Promise<void>;
|
handleCustomerFilter: (value: string) => Promise<void>;
|
||||||
setInitialOrders: (savedOrders: Order[], savedPage: number, savedHasSearched: boolean) => void;
|
setInitialOrders: (savedOrders: Order[], savedPage: number, savedHasSearched: boolean) => void;
|
||||||
clearStoredParams: () => void;
|
clearStoredParams: () => void;
|
||||||
|
clearAndNavigateToOrders: () => void;
|
||||||
handleMultiInputChange: (field: keyof OrderSearchParams, values: string[]) => void;
|
handleMultiInputChange: (field: keyof OrderSearchParams, values: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,6 +659,16 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
|||||||
setStorage("orderSearchParams", null);
|
setStorage("orderSearchParams", null);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Função para limpar parâmetros e navegar para orders/find
|
||||||
|
const clearAndNavigateToOrders = useCallback(() => {
|
||||||
|
// Limpar parâmetros do localStorage
|
||||||
|
setStorage("orderSearchParams", null);
|
||||||
|
// Limpar parâmetros do estado
|
||||||
|
setSearchParams({});
|
||||||
|
// Limpar URL e navegar
|
||||||
|
clearUrlAndNavigate("/orders/find");
|
||||||
|
}, [setSearchParams]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manipula a seleção de múltiplos valores em filtros de seleção
|
* Manipula a seleção de múltiplos valores em filtros de seleção
|
||||||
*
|
*
|
||||||
@@ -701,6 +713,7 @@ export function useOrderSearch(ordersPerPage: number = 8): UseOrderSearchReturn
|
|||||||
handleCustomerFilter,
|
handleCustomerFilter,
|
||||||
setInitialOrders,
|
setInitialOrders,
|
||||||
clearStoredParams,
|
clearStoredParams,
|
||||||
|
clearAndNavigateToOrders,
|
||||||
handleMultiInputChange
|
handleMultiInputChange
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +1,12 @@
|
|||||||
import { useState, useEffect, useMemo, useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { ChevronDown, ChevronUp } from "lucide-react";
|
import { useTableColumns } from "./useTableColumns";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function useOrderTableColumns(allColumns: string[]) {
|
export function useOrderTableColumns(allColumns: string[]) {
|
||||||
// Carregar as colunas visíveis do localStorage na inicialização
|
const tableColumns = useTableColumns({
|
||||||
const initVisibleColumns = () => {
|
allColumns,
|
||||||
try {
|
storageKey: "Order",
|
||||||
const saved = localStorage.getItem('visibleOrderColumns');
|
defaultVisibleColumns: allColumns,
|
||||||
if (saved) {
|
});
|
||||||
const parsed = JSON.parse(saved);
|
|
||||||
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao carregar configurações de colunas:', error);
|
|
||||||
}
|
|
||||||
return allColumns;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Inicializar a ordem das colunas
|
|
||||||
const initColumnOrder = () => {
|
|
||||||
try {
|
|
||||||
const saved = localStorage.getItem('orderColumnsOrder');
|
|
||||||
if (saved) {
|
|
||||||
const parsed = JSON.parse(saved);
|
|
||||||
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao carregar ordem das colunas:', error);
|
|
||||||
}
|
|
||||||
return allColumns;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estado para controlar quais colunas estão visíveis
|
|
||||||
const [visibleColumns, setVisibleColumns] = useState<string[]>(initVisibleColumns);
|
|
||||||
// Estado para controlar a ordem das colunas
|
|
||||||
const [columnOrder, setColumnOrder] = useState<string[]>(initColumnOrder);
|
|
||||||
// Estado para rastrear coluna sendo arrastada
|
|
||||||
const [draggedColumn, setDraggedColumn] = useState<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
const savedAllColumns = localStorage.getItem('allOrderColumns');
|
|
||||||
if (savedAllColumns) {
|
|
||||||
const parsedAllColumns = JSON.parse(savedAllColumns);
|
|
||||||
if (JSON.stringify(parsedAllColumns) !== JSON.stringify(allColumns)) {
|
|
||||||
localStorage.removeItem('visibleOrderColumns');
|
|
||||||
localStorage.removeItem('orderColumnsOrder');
|
|
||||||
localStorage.setItem('allOrderColumns', JSON.stringify(allColumns));
|
|
||||||
// Recarregar a página para aplicar as novas colunas
|
|
||||||
window.location.reload();
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
localStorage.setItem('allOrderColumns', JSON.stringify(allColumns));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao verificar as colunas no localStorage:', error);
|
|
||||||
}
|
|
||||||
}, [allColumns]);
|
|
||||||
|
|
||||||
// Salvar as colunas visíveis no localStorage sempre que elas mudarem
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
localStorage.setItem('visibleOrderColumns', JSON.stringify(visibleColumns));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao salvar configurações de colunas:', error);
|
|
||||||
}
|
|
||||||
}, [visibleColumns]);
|
|
||||||
|
|
||||||
// Salvar a ordem das colunas no localStorage
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
localStorage.setItem('orderColumnsOrder', JSON.stringify(columnOrder));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao salvar ordem das colunas:', error);
|
|
||||||
}
|
|
||||||
}, [columnOrder]);
|
|
||||||
|
|
||||||
// Memoizar as classes de colunas para evitar recálculos desnecessários
|
// Memoizar as classes de colunas para evitar recálculos desnecessários
|
||||||
const getColumnClass = useCallback((title: string) => {
|
const getColumnClass = useCallback((title: string) => {
|
||||||
@@ -98,12 +23,15 @@ export function useOrderTableColumns(allColumns: string[]) {
|
|||||||
"Valor": "w-20",
|
"Valor": "w-20",
|
||||||
"Peso(kg)": "w-20",
|
"Peso(kg)": "w-20",
|
||||||
"Carregamento": "w-28",
|
"Carregamento": "w-28",
|
||||||
|
"Dt Carregamento": "w-28",
|
||||||
"Cobrança": "w-28",
|
"Cobrança": "w-28",
|
||||||
"Praça": "w-20",
|
"Praça": "w-20",
|
||||||
"Nota fiscal": "w-20",
|
"Nota fiscal": "w-20",
|
||||||
"Dt Faturamento": "w-28",
|
"Dt Faturamento": "w-28",
|
||||||
"Rota": "w-24",
|
"Rota": "w-24",
|
||||||
"Trasportadora": "w-28",
|
"Trasportadora": "w-28",
|
||||||
|
"Motorista": "w-24",
|
||||||
|
"Placa": "w-32",
|
||||||
};
|
};
|
||||||
|
|
||||||
let classes = "whitespace-nowrap ";
|
let classes = "whitespace-nowrap ";
|
||||||
@@ -121,103 +49,8 @@ export function useOrderTableColumns(allColumns: string[]) {
|
|||||||
return classes;
|
return classes;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Funções para drag & drop
|
|
||||||
const handleDragStart = useCallback((e: React.DragEvent<HTMLDivElement>, column: string) => {
|
|
||||||
setDraggedColumn(column);
|
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
|
||||||
e.dataTransfer.setData('text/plain', column);
|
|
||||||
|
|
||||||
const target = e.currentTarget as HTMLDivElement; // salve a referência antes
|
|
||||||
|
|
||||||
// aplique a classe imediatamente (sem setTimeout)
|
|
||||||
target.classList.add('opacity-50');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
|
|
||||||
const handleDragEnd = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
|
||||||
setDraggedColumn(null);
|
|
||||||
e.currentTarget.classList.remove('opacity-50');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.dataTransfer.dropEffect = 'move';
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDrop = useCallback((e: React.DragEvent<HTMLDivElement>, targetColumn: string) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (!draggedColumn || draggedColumn === targetColumn) return;
|
|
||||||
|
|
||||||
// Reordenar as colunas
|
|
||||||
const newColumnOrder = [...columnOrder];
|
|
||||||
const draggedIndex = newColumnOrder.indexOf(draggedColumn);
|
|
||||||
const targetIndex = newColumnOrder.indexOf(targetColumn);
|
|
||||||
|
|
||||||
if (draggedIndex !== -1 && targetIndex !== -1) {
|
|
||||||
newColumnOrder.splice(draggedIndex, 1);
|
|
||||||
newColumnOrder.splice(targetIndex, 0, draggedColumn);
|
|
||||||
setColumnOrder(newColumnOrder);
|
|
||||||
}
|
|
||||||
}, [draggedColumn, columnOrder]);
|
|
||||||
|
|
||||||
// Função para alternar a visibilidade de uma coluna
|
|
||||||
const toggleColumn = useCallback((column: string) => {
|
|
||||||
setVisibleColumns((current) => {
|
|
||||||
if (current.includes(column)) {
|
|
||||||
return current.filter((c) => c !== column);
|
|
||||||
} else {
|
|
||||||
return [...current, column];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Função para selecionar todas as colunas
|
|
||||||
const selectAllColumns = useCallback(() => {
|
|
||||||
setVisibleColumns(allColumns);
|
|
||||||
}, [allColumns]);
|
|
||||||
|
|
||||||
// Função para desmarcar todas as colunas
|
|
||||||
const unselectAllColumns = useCallback(() => {
|
|
||||||
// Mantém pelo menos uma coluna para garantir que a tabela não fique vazia
|
|
||||||
setVisibleColumns(["Pedido"]);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Função para verificar se uma coluna está visível
|
|
||||||
const isColumnVisible = useCallback((column: string) => {
|
|
||||||
return visibleColumns.includes(column);
|
|
||||||
}, [visibleColumns]);
|
|
||||||
|
|
||||||
// Função para ordenar as colunas visíveis na ordem definida pelo usuário
|
|
||||||
// Memoizando o resultado para evitar recálculos desnecessários
|
|
||||||
const getOrderedVisibleColumns = useCallback(() => {
|
|
||||||
// Primeiro, filtrar as colunas que são visíveis
|
|
||||||
const visibleColumnSet = new Set(visibleColumns);
|
|
||||||
|
|
||||||
// Depois, ordenar as colunas de acordo com a ordem definida pelo usuário
|
|
||||||
return columnOrder.filter(column => visibleColumnSet.has(column));
|
|
||||||
}, [visibleColumns, columnOrder]);
|
|
||||||
|
|
||||||
// Resetar a ordem das colunas
|
|
||||||
const resetColumnOrder = useCallback(() => {
|
|
||||||
setColumnOrder(allColumns);
|
|
||||||
}, [allColumns]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
visibleColumns,
|
...tableColumns,
|
||||||
columnOrder,
|
|
||||||
getColumnClass,
|
getColumnClass,
|
||||||
getOrderedVisibleColumns,
|
|
||||||
resetColumnOrder,
|
|
||||||
toggleColumn,
|
|
||||||
selectAllColumns,
|
|
||||||
unselectAllColumns,
|
|
||||||
isColumnVisible,
|
|
||||||
handleDragStart,
|
|
||||||
handleDragEnd,
|
|
||||||
handleDragOver,
|
|
||||||
handleDrop
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
217
src/hooks/useTableColumns.ts
Normal file
217
src/hooks/useTableColumns.ts
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
import { useState, useEffect, useCallback } from "react";
|
||||||
|
|
||||||
|
interface UseTableColumnsOptions {
|
||||||
|
allColumns: string[];
|
||||||
|
storageKey: string;
|
||||||
|
defaultVisibleColumns?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useTableColumns({
|
||||||
|
allColumns,
|
||||||
|
storageKey,
|
||||||
|
defaultVisibleColumns
|
||||||
|
}: UseTableColumnsOptions) {
|
||||||
|
// Carregar as colunas visíveis do localStorage na inicialização
|
||||||
|
const initVisibleColumns = () => {
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem(`visible${storageKey}Columns`);
|
||||||
|
if (saved) {
|
||||||
|
const parsed = JSON.parse(saved);
|
||||||
|
if (Array.isArray(parsed) && parsed.length > 0) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao carregar configurações de colunas:', error);
|
||||||
|
}
|
||||||
|
return defaultVisibleColumns || allColumns;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inicializar a ordem das colunas
|
||||||
|
const initColumnOrder = () => {
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem(`${storageKey}ColumnsOrder`);
|
||||||
|
if (saved) {
|
||||||
|
const parsed = JSON.parse(saved);
|
||||||
|
if (Array.isArray(parsed) && parsed.length > 0) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao carregar ordem das colunas:', error);
|
||||||
|
}
|
||||||
|
return allColumns;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Estado para controlar quais colunas estão visíveis
|
||||||
|
const [visibleColumns, setVisibleColumns] = useState<string[]>(initVisibleColumns);
|
||||||
|
// Estado para controlar a ordem das colunas
|
||||||
|
const [columnOrder, setColumnOrder] = useState<string[]>(initColumnOrder);
|
||||||
|
// Estado para rastrear coluna sendo arrastada
|
||||||
|
const [draggedColumn, setDraggedColumn] = useState<string | null>(null);
|
||||||
|
// Estado para notificar sobre novas colunas
|
||||||
|
const [newColumnsDetected, setNewColumnsDetected] = useState<string[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
const savedAllColumns = localStorage.getItem(`all${storageKey}Columns`);
|
||||||
|
if (savedAllColumns) {
|
||||||
|
const parsedAllColumns = JSON.parse(savedAllColumns);
|
||||||
|
if (JSON.stringify(parsedAllColumns) !== JSON.stringify(allColumns)) {
|
||||||
|
// Detectar novas colunas
|
||||||
|
const newColumns = allColumns.filter(col => !parsedAllColumns.includes(col));
|
||||||
|
|
||||||
|
if (newColumns.length > 0) {
|
||||||
|
// Adicionar novas colunas às colunas visíveis
|
||||||
|
setVisibleColumns(prev => {
|
||||||
|
const updated = [...prev, ...newColumns];
|
||||||
|
// Remover duplicatas
|
||||||
|
return [...new Set(updated)];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Atualizar a ordem das colunas incluindo as novas
|
||||||
|
setColumnOrder(prev => {
|
||||||
|
const updated = [...prev, ...newColumns];
|
||||||
|
// Remover duplicatas
|
||||||
|
return [...new Set(updated)];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Notificar sobre as novas colunas
|
||||||
|
setNewColumnsDetected(newColumns);
|
||||||
|
|
||||||
|
// Limpar a notificação após 5 segundos
|
||||||
|
setTimeout(() => {
|
||||||
|
setNewColumnsDetected([]);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Salvar as novas colunas no localStorage
|
||||||
|
localStorage.setItem(`all${storageKey}Columns`, JSON.stringify(allColumns));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
localStorage.setItem(`all${storageKey}Columns`, JSON.stringify(allColumns));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao verificar as colunas no localStorage:', error);
|
||||||
|
}
|
||||||
|
}, [allColumns, storageKey]);
|
||||||
|
|
||||||
|
// Salvar as colunas visíveis no localStorage sempre que elas mudarem
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(`visible${storageKey}Columns`, JSON.stringify(visibleColumns));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao salvar configurações de colunas:', error);
|
||||||
|
}
|
||||||
|
}, [visibleColumns, storageKey]);
|
||||||
|
|
||||||
|
// Salvar a ordem das colunas no localStorage
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(`${storageKey}ColumnsOrder`, JSON.stringify(columnOrder));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao salvar ordem das colunas:', error);
|
||||||
|
}
|
||||||
|
}, [columnOrder, storageKey]);
|
||||||
|
|
||||||
|
// Funções para drag & drop
|
||||||
|
const handleDragStart = useCallback((e: React.DragEvent<HTMLDivElement>, column: string) => {
|
||||||
|
setDraggedColumn(column);
|
||||||
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
|
e.dataTransfer.setData('text/plain', column);
|
||||||
|
|
||||||
|
const target = e.currentTarget as HTMLDivElement;
|
||||||
|
target.classList.add('opacity-50');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDragEnd = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
setDraggedColumn(null);
|
||||||
|
e.currentTarget.classList.remove('opacity-50');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.dataTransfer.dropEffect = 'move';
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDrop = useCallback((e: React.DragEvent<HTMLDivElement>, targetColumn: string) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!draggedColumn || draggedColumn === targetColumn) return;
|
||||||
|
|
||||||
|
// Reordenar as colunas
|
||||||
|
const newColumnOrder = [...columnOrder];
|
||||||
|
const draggedIndex = newColumnOrder.indexOf(draggedColumn);
|
||||||
|
const targetIndex = newColumnOrder.indexOf(targetColumn);
|
||||||
|
|
||||||
|
if (draggedIndex !== -1 && targetIndex !== -1) {
|
||||||
|
newColumnOrder.splice(draggedIndex, 1);
|
||||||
|
newColumnOrder.splice(targetIndex, 0, draggedColumn);
|
||||||
|
setColumnOrder(newColumnOrder);
|
||||||
|
}
|
||||||
|
}, [draggedColumn, columnOrder]);
|
||||||
|
|
||||||
|
// Função para alternar a visibilidade de uma coluna
|
||||||
|
const toggleColumn = useCallback((column: string) => {
|
||||||
|
setVisibleColumns((current) => {
|
||||||
|
if (current.includes(column)) {
|
||||||
|
return current.filter((c) => c !== column);
|
||||||
|
} else {
|
||||||
|
return [...current, column];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Função para selecionar todas as colunas
|
||||||
|
const selectAllColumns = useCallback(() => {
|
||||||
|
setVisibleColumns(allColumns);
|
||||||
|
}, [allColumns]);
|
||||||
|
|
||||||
|
// Função para desmarcar todas as colunas
|
||||||
|
const unselectAllColumns = useCallback(() => {
|
||||||
|
// Mantém pelo menos uma coluna para garantir que a tabela não fique vazia
|
||||||
|
const firstColumn = allColumns[0] || "Código";
|
||||||
|
setVisibleColumns([firstColumn]);
|
||||||
|
}, [allColumns]);
|
||||||
|
|
||||||
|
// Função para verificar se uma coluna está visível
|
||||||
|
const isColumnVisible = useCallback((column: string) => {
|
||||||
|
return visibleColumns.includes(column);
|
||||||
|
}, [visibleColumns]);
|
||||||
|
|
||||||
|
// Função para ordenar as colunas visíveis na ordem definida pelo usuário
|
||||||
|
const getOrderedVisibleColumns = useCallback(() => {
|
||||||
|
// Primeiro, filtrar as colunas que são visíveis
|
||||||
|
const visibleColumnSet = new Set(visibleColumns);
|
||||||
|
|
||||||
|
// Depois, ordenar as colunas de acordo com a ordem definida pelo usuário
|
||||||
|
return columnOrder.filter(column => visibleColumnSet.has(column));
|
||||||
|
}, [visibleColumns, columnOrder]);
|
||||||
|
|
||||||
|
// Resetar a ordem das colunas
|
||||||
|
const resetColumnOrder = useCallback(() => {
|
||||||
|
setColumnOrder(allColumns);
|
||||||
|
}, [allColumns]);
|
||||||
|
|
||||||
|
// Função para limpar a notificação de novas colunas
|
||||||
|
const dismissNewColumnsNotification = useCallback(() => {
|
||||||
|
setNewColumnsDetected([]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
visibleColumns,
|
||||||
|
columnOrder,
|
||||||
|
getOrderedVisibleColumns,
|
||||||
|
resetColumnOrder,
|
||||||
|
toggleColumn,
|
||||||
|
selectAllColumns,
|
||||||
|
unselectAllColumns,
|
||||||
|
isColumnVisible,
|
||||||
|
handleDragStart,
|
||||||
|
handleDragEnd,
|
||||||
|
handleDragOver,
|
||||||
|
handleDrop,
|
||||||
|
newColumnsDetected,
|
||||||
|
dismissNewColumnsNotification,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ 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 || "http://10.40.0.2:8888";
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "https://portalapi.jurunense.com";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classe de erro personalizada para requisições de API.
|
* Classe de erro personalizada para requisições de API.
|
||||||
|
|||||||
@@ -71,4 +71,33 @@ export function buildUrl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limpa os parâmetros da URL atual e navega para uma nova URL
|
||||||
|
*
|
||||||
|
* @param path Caminho para navegar (sem parâmetros)
|
||||||
|
*/
|
||||||
|
export function clearUrlAndNavigate(path: string): void {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.history.replaceState({ path }, "", path);
|
||||||
|
window.location.href = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Limpa parâmetros específicos da URL atual
|
||||||
|
*
|
||||||
|
* @param paramsToRemove Array de parâmetros para remover
|
||||||
|
*/
|
||||||
|
export function clearUrlParams(paramsToRemove: string[]): void {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
|
||||||
|
paramsToRemove.forEach(param => {
|
||||||
|
url.searchParams.delete(param);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.history.replaceState({ path: url.pathname + url.search }, "", url.pathname + url.search);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user