michangarrito-frontend-v2/src/App.tsx
rckrdmrd 00691fd1f7 [SPRINT-6] feat: Agregar paginas Tokens y CodiSpei
MCH-019 - Tienda de Tokens:
- Tokens.tsx con balance, paquetes y historial de uso
- Integracion con billingApi para checkout Stripe
- Visualizacion de costos por servicio

MCH-024 - CoDi/SPEI:
- CodiSpei.tsx con tabs CoDi y SPEI
- Generacion de QR CoDi para cobros
- Visualizacion de CLABE virtual
- Historial de transacciones

Actualizaciones:
- App.tsx: Rutas /tokens y /codi-spei
- Layout.tsx: Enlaces en navegacion
- api.ts: billingApi y subscriptionsApi

Sprint 6 - Frontend completado

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 04:32:43 -06:00

100 lines
3.4 KiB
TypeScript

import { BrowserRouter, Routes, Route, Navigate, Outlet } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { AuthProvider, useAuth } from './contexts/AuthContext';
import { Layout } from './components/Layout';
import { Dashboard } from './pages/Dashboard';
import { Products } from './pages/Products';
import { Orders } from './pages/Orders';
import { Customers } from './pages/Customers';
import { Fiado } from './pages/Fiado';
import { Inventory } from './pages/Inventory';
import { Settings } from './pages/Settings';
import { Referrals } from './pages/Referrals';
import { Invoices } from './pages/Invoices';
import { Marketplace } from './pages/Marketplace';
import { Tokens } from './pages/Tokens';
import { CodiSpei } from './pages/CodiSpei';
import Login from './pages/Login';
import Register from './pages/Register';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
retry: 1,
},
},
});
// Protected route wrapper
function ProtectedRoute() {
const { isAuthenticated, isLoading } = useAuth();
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-emerald-600"></div>
</div>
);
}
return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
}
// Public route wrapper (redirect if authenticated)
function PublicRoute() {
const { isAuthenticated, isLoading } = useAuth();
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-emerald-600"></div>
</div>
);
}
return isAuthenticated ? <Navigate to="/dashboard" replace /> : <Outlet />;
}
function App() {
return (
<QueryClientProvider client={queryClient}>
<AuthProvider>
<BrowserRouter>
<Routes>
{/* Public routes */}
<Route element={<PublicRoute />}>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Route>
{/* Protected routes */}
<Route element={<ProtectedRoute />}>
<Route path="/" element={<Layout />}>
<Route index element={<Navigate to="/dashboard" replace />} />
<Route path="dashboard" element={<Dashboard />} />
<Route path="products" element={<Products />} />
<Route path="orders" element={<Orders />} />
<Route path="customers" element={<Customers />} />
<Route path="fiado" element={<Fiado />} />
<Route path="inventory" element={<Inventory />} />
<Route path="referrals" element={<Referrals />} />
<Route path="invoices" element={<Invoices />} />
<Route path="marketplace" element={<Marketplace />} />
<Route path="tokens" element={<Tokens />} />
<Route path="codi-spei" element={<CodiSpei />} />
<Route path="settings" element={<Settings />} />
</Route>
</Route>
{/* Catch all */}
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</BrowserRouter>
</AuthProvider>
</QueryClientProvider>
);
}
export default App;