- Contatos: grid de cards 3 colunas, botão "Novo Contato" no topo da página - Sync ERP↔SAR corrigido: vw_contatos aceita formato COR#<id>, trigger normaliza id_empresa (9001→1) - CTR + NF-e: layout 50/50 — lista de títulos abertos com badge vencido/a vencer e lista de notas com botão copiar chave NF-e - Histórico de pedidos: UNION SAR+ERP, top 5 + modal "Ver todos" - Produtos mais comprados: top 5 com último preço + modal "Ver todos" - Novos endpoints: ctr-list, notas, orders-history, top-produtos - AppShell: overflow-x travado, sem scroll horizontal na aplicação Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
168 lines
4.0 KiB
TypeScript
168 lines
4.0 KiB
TypeScript
import {
|
|
createRouter,
|
|
createRootRoute,
|
|
createRoute,
|
|
Outlet,
|
|
notFound,
|
|
} from '@tanstack/react-router';
|
|
import { Typography } from 'antd';
|
|
import { AppShell } from '../components/layout/AppShell';
|
|
import { RepPainel } from '../cockpits/rep/RepPainel';
|
|
import { ClientsPage } from '../cockpits/rep/ClientsPage';
|
|
import { ClientDetailPage } from '../cockpits/rep/ClientDetailPage';
|
|
import { OrdersPage } from '../cockpits/rep/OrdersPage';
|
|
import { OrderDetailPage } from '../cockpits/rep/OrderDetailPage';
|
|
import { OrderPrintPage } from '../cockpits/rep/OrderPrintPage';
|
|
import { NewClientPage } from '../cockpits/rep/NewClientPage';
|
|
import { NewOrderPage } from '../cockpits/rep/NewOrderPage';
|
|
import { CatalogPage } from '../cockpits/rep/CatalogPage';
|
|
import { OrdersErpPage } from '../cockpits/rep/OrdersErpPage';
|
|
import { RelatoriosPage } from '../cockpits/rep/RelatoriosPage';
|
|
import { ApprovalQueuePage } from '../cockpits/supervisor/ApprovalQueuePage';
|
|
import { SupervisorPainel } from '../cockpits/supervisor/SupervisorPainel';
|
|
import { authStore } from './auth-store';
|
|
|
|
function getRoleFromToken(): string {
|
|
const token = authStore.get();
|
|
if (!token) return 'rep';
|
|
try {
|
|
const payload = JSON.parse(atob(token.split('.')[1] ?? ''));
|
|
return (payload.role as string) ?? 'rep';
|
|
} catch {
|
|
return 'rep';
|
|
}
|
|
}
|
|
|
|
function HomeRoute() {
|
|
const role = getRoleFromToken();
|
|
return role === 'supervisor' || role === 'manager' ? <SupervisorPainel /> : <RepPainel />;
|
|
}
|
|
|
|
function NotFoundPage() {
|
|
return (
|
|
<div style={{ padding: 48, textAlign: 'center' }}>
|
|
<Typography.Title level={3} type="secondary">
|
|
Página não encontrada
|
|
</Typography.Title>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Suprime aviso de notFound não utilizado — usado via throw notFound() em loaders futuros.
|
|
void notFound;
|
|
|
|
const rootRoute = createRootRoute({
|
|
component: () => (
|
|
<AppShell>
|
|
<Outlet />
|
|
</AppShell>
|
|
),
|
|
notFoundComponent: NotFoundPage,
|
|
});
|
|
|
|
const indexRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/',
|
|
component: HomeRoute,
|
|
});
|
|
|
|
const rafaelRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/rep',
|
|
component: RepPainel,
|
|
});
|
|
|
|
const clientesRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/clientes',
|
|
component: ClientsPage,
|
|
});
|
|
|
|
const novoClienteRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/clientes/novo',
|
|
component: NewClientPage,
|
|
});
|
|
|
|
const clienteDetailRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/clientes/$id',
|
|
component: ClientDetailPage,
|
|
});
|
|
|
|
const pedidosRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/pedidos',
|
|
component: OrdersPage,
|
|
});
|
|
|
|
const novoOrderRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/pedidos/novo',
|
|
component: NewOrderPage,
|
|
});
|
|
|
|
const pedidoDetailRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/pedidos/$id',
|
|
component: OrderDetailPage,
|
|
});
|
|
|
|
const pedidoPrintRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/pedidos/$id/imprimir',
|
|
component: OrderPrintPage,
|
|
});
|
|
|
|
const catalogoRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/catalogo',
|
|
component: CatalogPage,
|
|
});
|
|
|
|
const pedidosErpRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/pedidos-erp',
|
|
component: OrdersErpPage,
|
|
});
|
|
|
|
const relatoriosRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/relatorios',
|
|
component: RelatoriosPage,
|
|
});
|
|
|
|
const aprovacoes = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: '/aprovacoes',
|
|
component: ApprovalQueuePage,
|
|
});
|
|
|
|
const routeTree = rootRoute.addChildren([
|
|
indexRoute,
|
|
rafaelRoute,
|
|
clientesRoute,
|
|
novoClienteRoute,
|
|
clienteDetailRoute,
|
|
pedidosRoute,
|
|
novoOrderRoute,
|
|
pedidoDetailRoute,
|
|
pedidoPrintRoute,
|
|
catalogoRoute,
|
|
pedidosErpRoute,
|
|
relatoriosRoute,
|
|
aprovacoes,
|
|
]);
|
|
|
|
export const router = createRouter({
|
|
routeTree,
|
|
defaultPreload: 'intent',
|
|
defaultPreloadStaleTime: 0,
|
|
});
|
|
|
|
declare module '@tanstack/react-router' {
|
|
interface Register {
|
|
router: typeof router;
|
|
}
|
|
}
|