- Add billing-usage feature module with types, API clients, hooks, and components - Create PlanCard, PlanSelector, SubscriptionStatusBadge, InvoiceList, UsageSummaryCard, CouponInput components - Add BillingPage, PlansPage, InvoicesPage, UsagePage - Update routes to include billing section Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
321 lines
7.5 KiB
TypeScript
321 lines
7.5 KiB
TypeScript
import { lazy, Suspense } from 'react';
|
|
import { createBrowserRouter, Navigate } from 'react-router-dom';
|
|
import { ProtectedRoute } from './ProtectedRoute';
|
|
import { DashboardLayout } from '@app/layouts/DashboardLayout';
|
|
import { FullPageSpinner } from '@components/atoms/Spinner';
|
|
|
|
// Lazy load pages
|
|
const LoginPage = lazy(() => import('@pages/auth/LoginPage'));
|
|
const RegisterPage = lazy(() => import('@pages/auth/RegisterPage'));
|
|
const ForgotPasswordPage = lazy(() => import('@pages/auth/ForgotPasswordPage'));
|
|
const DashboardPage = lazy(() => import('@pages/dashboard/DashboardPage'));
|
|
const NotFoundPage = lazy(() => import('@pages/NotFoundPage'));
|
|
|
|
// Users pages
|
|
const UsersListPage = lazy(() => import('@pages/users/UsersListPage'));
|
|
const UserDetailPage = lazy(() => import('@pages/users/UserDetailPage'));
|
|
const UserCreatePage = lazy(() => import('@pages/users/UserCreatePage'));
|
|
const UserEditPage = lazy(() => import('@pages/users/UserEditPage'));
|
|
|
|
// Companies pages
|
|
const CompaniesListPage = lazy(() => import('@pages/companies/CompaniesListPage'));
|
|
const CompanyDetailPage = lazy(() => import('@pages/companies/CompanyDetailPage'));
|
|
const CompanyCreatePage = lazy(() => import('@pages/companies/CompanyCreatePage'));
|
|
const CompanyEditPage = lazy(() => import('@pages/companies/CompanyEditPage'));
|
|
|
|
// Partners pages
|
|
const PartnersListPage = lazy(() => import('@pages/partners/PartnersListPage'));
|
|
const PartnerDetailPage = lazy(() => import('@pages/partners/PartnerDetailPage'));
|
|
const PartnerCreatePage = lazy(() => import('@pages/partners/PartnerCreatePage'));
|
|
const PartnerEditPage = lazy(() => import('@pages/partners/PartnerEditPage'));
|
|
|
|
// Billing pages
|
|
const BillingPage = lazy(() => import('@pages/billing/BillingPage').then(m => ({ default: m.BillingPage })));
|
|
const PlansPage = lazy(() => import('@pages/billing/PlansPage').then(m => ({ default: m.PlansPage })));
|
|
const InvoicesPage = lazy(() => import('@pages/billing/InvoicesPage').then(m => ({ default: m.InvoicesPage })));
|
|
const UsagePage = lazy(() => import('@pages/billing/UsagePage').then(m => ({ default: m.UsagePage })));
|
|
|
|
function LazyWrapper({ children }: { children: React.ReactNode }) {
|
|
return <Suspense fallback={<FullPageSpinner />}>{children}</Suspense>;
|
|
}
|
|
|
|
function DashboardWrapper({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<ProtectedRoute>
|
|
<DashboardLayout>
|
|
<LazyWrapper>{children}</LazyWrapper>
|
|
</DashboardLayout>
|
|
</ProtectedRoute>
|
|
);
|
|
}
|
|
|
|
export const router = createBrowserRouter([
|
|
// Public routes
|
|
{
|
|
path: '/login',
|
|
element: (
|
|
<LazyWrapper>
|
|
<LoginPage />
|
|
</LazyWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/register',
|
|
element: (
|
|
<LazyWrapper>
|
|
<RegisterPage />
|
|
</LazyWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/forgot-password',
|
|
element: (
|
|
<LazyWrapper>
|
|
<ForgotPasswordPage />
|
|
</LazyWrapper>
|
|
),
|
|
},
|
|
|
|
// Protected routes
|
|
{
|
|
path: '/',
|
|
element: <Navigate to="/dashboard" replace />,
|
|
},
|
|
{
|
|
path: '/dashboard',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<DashboardPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
|
|
// Users routes
|
|
{
|
|
path: '/users',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<UsersListPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/users/new',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<UserCreatePage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/users/:id',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<UserDetailPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/users/:id/edit',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<UserEditPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
// Companies routes
|
|
{
|
|
path: '/companies',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<CompaniesListPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/companies/new',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<CompanyCreatePage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/companies/:id',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<CompanyDetailPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/companies/:id/edit',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<CompanyEditPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
|
|
// Partners routes
|
|
{
|
|
path: '/partners',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<PartnersListPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/partners/new',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<PartnerCreatePage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/partners/:id',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<PartnerDetailPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/partners/:id/edit',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<PartnerEditPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/inventory/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Módulo de Inventario - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/sales/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Módulo de Ventas - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/purchases/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Módulo de Compras - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/financial/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Módulo Financiero - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/projects/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Módulo de Proyectos - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/crm/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Módulo CRM - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/hr/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Módulo RRHH - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/settings/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Configuración - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
|
|
// Billing routes
|
|
{
|
|
path: '/billing',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<BillingPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/billing/plans',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<PlansPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/billing/invoices',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<InvoicesPage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/billing/usage',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<UsagePage />
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
{
|
|
path: '/billing/*',
|
|
element: (
|
|
<DashboardWrapper>
|
|
<div className="text-center text-gray-500">Sección de facturación - En desarrollo</div>
|
|
</DashboardWrapper>
|
|
),
|
|
},
|
|
|
|
// Error pages
|
|
{
|
|
path: '/unauthorized',
|
|
element: (
|
|
<div className="flex min-h-screen items-center justify-center">
|
|
<div className="text-center">
|
|
<h1 className="text-4xl font-bold text-gray-900">403</h1>
|
|
<p className="mt-2 text-gray-600">No tienes permiso para acceder a esta página</p>
|
|
</div>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
path: '*',
|
|
element: (
|
|
<LazyWrapper>
|
|
<NotFoundPage />
|
|
</LazyWrapper>
|
|
),
|
|
},
|
|
]);
|