feat: Implement orders page with table and order details tabs.
This commit is contained in:
parent
544d723f1b
commit
5d469f08a7
|
|
@ -14,7 +14,7 @@ import MoveToInboxIcon from '@mui/icons-material/MoveToInbox';
|
||||||
import TvIcon from '@mui/icons-material/Tv';
|
import TvIcon from '@mui/icons-material/Tv';
|
||||||
import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet';
|
import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet';
|
||||||
import { TabPanel } from './TabPanel';
|
import { TabPanel } from './TabPanel';
|
||||||
import { OrderItemsTable } from './OrderItemsTable';
|
import { OrderItemsTable } from './tabs/OrderItemsTable';
|
||||||
import { PreBoxPanel } from './tabs/PreBoxPanel';
|
import { PreBoxPanel } from './tabs/PreBoxPanel';
|
||||||
import { InformationPanel } from './tabs/InformationPanel';
|
import { InformationPanel } from './tabs/InformationPanel';
|
||||||
import { TimelinePanel } from './tabs/TimelinePanel';
|
import { TimelinePanel } from './tabs/TimelinePanel';
|
||||||
|
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import Paper from '@mui/material/Paper';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
|
||||||
import Alert from '@mui/material/Alert';
|
|
||||||
import { DataGridPremium } from '@mui/x-data-grid-premium';
|
|
||||||
import { useOrderItems } from '../hooks/useOrderItems';
|
|
||||||
import { createOrderItemsColumns } from './OrderItemsTableColumns';
|
|
||||||
import { OrderItem } from '../schemas/order.item.schema';
|
|
||||||
|
|
||||||
interface OrderItemsTableProps {
|
|
||||||
orderId: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const OrderItemsTable = ({ orderId }: OrderItemsTableProps) => {
|
|
||||||
const { data: items, isLoading, error } = useOrderItems(orderId);
|
|
||||||
|
|
||||||
const columns = useMemo(() => createOrderItemsColumns(), []);
|
|
||||||
|
|
||||||
const rows = useMemo(() => {
|
|
||||||
if (!Array.isArray(items) || items.length === 0) return [];
|
|
||||||
return items.map((item: OrderItem, index: number) => ({
|
|
||||||
id: `${orderId}-${item.productId}-${index}`,
|
|
||||||
...item,
|
|
||||||
}));
|
|
||||||
}, [items, orderId]);
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', py: 4 }}>
|
|
||||||
<CircularProgress size={40} />
|
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ ml: 2 }}>
|
|
||||||
Carregando itens do pedido...
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ mt: 2 }}>
|
|
||||||
<Alert severity="error">
|
|
||||||
{error instanceof Error
|
|
||||||
? `Erro ao carregar itens: ${error.message}`
|
|
||||||
: 'Erro ao carregar itens do pedido.'}
|
|
||||||
</Alert>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!items || items.length === 0) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ mt: 2 }}>
|
|
||||||
<Alert severity="info">Nenhum item encontrado para este pedido.</Alert>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Paper sx={{ boxShadow: 'none', border: 'none', backgroundColor: 'transparent', overflow: 'hidden' }}>
|
|
||||||
<DataGridPremium
|
|
||||||
rows={rows}
|
|
||||||
columns={columns}
|
|
||||||
density="compact"
|
|
||||||
autoHeight
|
|
||||||
hideFooter={rows.length <= 10}
|
|
||||||
initialState={{
|
|
||||||
pagination: {
|
|
||||||
paginationModel: {
|
|
||||||
pageSize: 10,
|
|
||||||
page: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
pageSizeOptions={[10, 25, 50]}
|
|
||||||
sx={{
|
|
||||||
border: '1px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
|
|
||||||
backgroundColor: 'background.paper',
|
|
||||||
'& .MuiDataGrid-root': {
|
|
||||||
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
|
|
||||||
border: 'none',
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-columnHeaders': {
|
|
||||||
backgroundColor: 'grey.50',
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
borderBottom: '2px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
|
|
||||||
minHeight: '40px !important',
|
|
||||||
maxHeight: '40px !important',
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-columnHeader': {
|
|
||||||
borderRight: '1px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
paddingLeft: '12px',
|
|
||||||
paddingRight: '12px',
|
|
||||||
'&:focus': {
|
|
||||||
outline: 'none',
|
|
||||||
},
|
|
||||||
'&:focus-within': {
|
|
||||||
outline: 'none',
|
|
||||||
},
|
|
||||||
'&:last-of-type': {
|
|
||||||
borderRight: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-row': {
|
|
||||||
borderBottom: '1px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
backgroundColor: 'background.paper',
|
|
||||||
minHeight: '36px !important',
|
|
||||||
maxHeight: '36px !important',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'action.hover',
|
|
||||||
},
|
|
||||||
'&:last-child': {
|
|
||||||
borderBottom: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-row:nth-of-type(even)': {
|
|
||||||
backgroundColor: 'grey.50',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'action.hover',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-cell': {
|
|
||||||
borderRight: '1px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
borderBottom: 'none',
|
|
||||||
paddingLeft: '12px',
|
|
||||||
paddingRight: '12px',
|
|
||||||
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
lineHeight: 1.2,
|
|
||||||
'&:focus': {
|
|
||||||
outline: 'none',
|
|
||||||
},
|
|
||||||
'&:focus-within': {
|
|
||||||
outline: 'none',
|
|
||||||
},
|
|
||||||
'&:last-of-type': {
|
|
||||||
borderRight: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-footerContainer': {
|
|
||||||
borderTop: '2px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
|
|
||||||
minHeight: '48px !important',
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
backgroundColor: 'grey.50',
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-aggregationColumnHeader': {
|
|
||||||
backgroundColor: 'grey.100',
|
|
||||||
fontWeight: 600,
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
borderBottom: '2px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-aggregationRow': {
|
|
||||||
backgroundColor: 'grey.100',
|
|
||||||
borderTop: '2px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
minHeight: '40px !important',
|
|
||||||
maxHeight: '40px !important',
|
|
||||||
},
|
|
||||||
'& .MuiDataGrid-aggregationCell': {
|
|
||||||
borderRight: '1px solid',
|
|
||||||
borderColor: 'divider',
|
|
||||||
paddingLeft: '12px',
|
|
||||||
paddingRight: '12px',
|
|
||||||
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
|
|
||||||
fontSize: '0.75rem',
|
|
||||||
fontWeight: 600,
|
|
||||||
'&:last-of-type': {
|
|
||||||
borderRight: 'none',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
localeText={{
|
|
||||||
noRowsLabel: 'Nenhum item encontrado.',
|
|
||||||
noResultsOverlayLabel: 'Nenhum resultado encontrado.',
|
|
||||||
footerTotalRows: 'Total de itens:',
|
|
||||||
footerTotalVisibleRows: (visibleCount, totalCount) =>
|
|
||||||
`${visibleCount.toLocaleString()} de ${totalCount.toLocaleString()}`,
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
pagination: {
|
|
||||||
labelRowsPerPage: 'Itens por página:',
|
|
||||||
labelDisplayedRows: ({ from, to, count }: { from: number; to: number; count: number }) => {
|
|
||||||
const pageSize = to >= from ? to - from + 1 : 10;
|
|
||||||
const currentPage = Math.floor((from - 1) / pageSize) + 1;
|
|
||||||
const totalPages = Math.ceil(count / pageSize);
|
|
||||||
return `${from}–${to} de ${count} | Página ${currentPage} de ${totalPages}`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { SearchBar } from './SearchBar';
|
import { SearchBar } from './SearchBar';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import Paper from '@mui/material/Paper';
|
import Paper from '@mui/material/Paper';
|
||||||
import { DataGridPremium, GridCellSelectionModel } from '@mui/x-data-grid-premium';
|
import { DataGridPremium, GridCellSelectionModel } from '@mui/x-data-grid-premium';
|
||||||
import { useOrders } from '../hooks/useOrders';
|
import { useOrders } from '../hooks/useOrders';
|
||||||
|
|
@ -31,14 +31,7 @@ export const OrderTable = () => {
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', py: 10, gap: 2 }}>
|
|
||||||
<CircularProgress size={80} />
|
|
||||||
<Typography variant="body2" color="text.secondary">Buscando pedidos...</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { Box, Typography } from '@mui/material';
|
||||||
export default function OrdersPage() {
|
export default function OrdersPage() {
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h4" fontWeight="700" mb={3}>
|
<Typography variant="h4" fontWeight="400" mb={3}>
|
||||||
Consultas de Pedidos
|
Consultas de Pedidos
|
||||||
</Typography>
|
</Typography>
|
||||||
<OrderTable />
|
<OrderTable />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue