Fase 3:
- Backend API: Autenticación y autorización básicas con JWT implementadas. Cambio de contraseña funcional. Módulo "Tipos de Pago" (CRUD completo) implementado en el backend (Controlador, Servicio, Repositorio) usando Dapper, transacciones y con lógica de historial. Se incluyen permisos en el token JWT. - Frontend React: Estructura base con Vite, TypeScript, MUI. Contexto de autenticación (AuthContext) que maneja el estado del usuario y el token. Página de Login. Modal de Cambio de Contraseña (forzado y opcional). Hook usePermissions para verificar permisos. Página GestionarTiposPagoPage con tabla, paginación, filtro, modal para crear/editar, y menú de acciones, respetando permisos. Layout principal (MainLayout) con navegación por Tabs (funcionalidad básica de navegación). Estructura de enrutamiento (AppRoutes) que maneja rutas públicas, protegidas y anidadas para módulos.
This commit is contained in:
@@ -1,63 +1,125 @@
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||
// src/routes/AppRoutes.tsx
|
||||
import React, { type JSX } from 'react';
|
||||
import { BrowserRouter, Routes, Route, Navigate, Outlet } from 'react-router-dom';
|
||||
import LoginPage from '../pages/LoginPage';
|
||||
import HomePage from '../pages/HomePage'; // Crearemos esta página simple
|
||||
import HomePage from '../pages/HomePage';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import ChangePasswordPage from '../pages/ChangePasswordPage'; // Crearemos esta
|
||||
import MainLayout from '../layouts/MainLayout'; // Crearemos este
|
||||
import MainLayout from '../layouts/MainLayout';
|
||||
import { Typography } from '@mui/material';
|
||||
|
||||
// Componente para proteger rutas
|
||||
// Distribución
|
||||
import DistribucionIndexPage from '../pages/Distribucion/DistribucionIndexPage';
|
||||
import ESCanillasPage from '../pages/Distribucion/ESCanillasPage';
|
||||
import ControlDevolucionesPage from '../pages/Distribucion/ControlDevolucionesPage';
|
||||
import ESDistribuidoresPage from '../pages/Distribucion/ESDistribuidoresPage';
|
||||
import SalidasOtrosDestinosPage from '../pages/Distribucion/SalidasOtrosDestinosPage';
|
||||
import CanillasPage from '../pages/Distribucion/CanillasPage';
|
||||
import DistribuidoresPage from '../pages/Distribucion/DistribuidoresPage';
|
||||
import PublicacionesPage from '../pages/Distribucion/PublicacionesPage';
|
||||
import OtrosDestinosPage from '../pages/Distribucion/OtrosDestinosPage';
|
||||
import ZonasPage from '../pages/Distribucion/ZonasPage';
|
||||
import EmpresasPage from '../pages/Distribucion/EmpresasPage';
|
||||
|
||||
// Contables
|
||||
import ContablesIndexPage from '../pages/Contables/ContablesIndexPage';
|
||||
import GestionarTiposPagoPage from '../pages/Contables/GestionarTiposPagoPage'; // Asumiendo que lo moviste aquí
|
||||
|
||||
// --- ProtectedRoute y PublicRoute SIN CAMBIOS ---
|
||||
const ProtectedRoute: React.FC<{ children: JSX.Element }> = ({ children }) => {
|
||||
const { isAuthenticated, isLoading } = useAuth();
|
||||
|
||||
if (isLoading) {
|
||||
// Muestra algo mientras verifica el token (ej: un spinner)
|
||||
return <div>Cargando...</div>;
|
||||
}
|
||||
|
||||
return isAuthenticated ? children : <Navigate to="/login" replace />;
|
||||
const { isAuthenticated, isLoading } = useAuth();
|
||||
// console.log("ProtectedRoute Check:", { path: window.location.pathname, isAuthenticated, isLoading });
|
||||
if (isLoading) return null;
|
||||
if (!isAuthenticated) {
|
||||
// console.log("ProtectedRoute: Not authenticated, redirecting to /login");
|
||||
return <Navigate to="/login" replace />;
|
||||
}
|
||||
// console.log("ProtectedRoute: Authenticated, rendering children");
|
||||
return children;
|
||||
};
|
||||
|
||||
// Componente para rutas públicas (redirige si ya está logueado)
|
||||
const PublicRoute: React.FC<{ children: JSX.Element }> = ({ children }) => {
|
||||
const { isAuthenticated, isLoading } = useAuth();
|
||||
|
||||
if (isLoading) {
|
||||
return <div>Cargando...</div>;
|
||||
// console.log("PublicRoute Check:", { path: window.location.pathname, isAuthenticated, isLoading });
|
||||
if (isLoading) return null;
|
||||
if (isAuthenticated) {
|
||||
// console.log("PublicRoute: Authenticated, redirecting to /");
|
||||
return <Navigate to="/" replace />;
|
||||
}
|
||||
|
||||
return !isAuthenticated ? children : <Navigate to="/" replace />;
|
||||
// console.log("PublicRoute: Not authenticated, rendering children");
|
||||
return children;
|
||||
};
|
||||
// --- Fin Protected/Public ---
|
||||
|
||||
const MainLayoutWrapper: React.FC = () => (
|
||||
<MainLayout>
|
||||
<Outlet />
|
||||
</MainLayout>
|
||||
);
|
||||
|
||||
// Placeholder simple
|
||||
const PlaceholderPage: React.FC<{ moduleName: string }> = ({ moduleName }) => (
|
||||
<Typography variant="h5" sx={{ p:2 }}>Página Principal del Módulo: {moduleName}</Typography>
|
||||
);
|
||||
|
||||
const AppRoutes = () => {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
{/* Rutas Públicas */}
|
||||
<Route path="/login" element={<PublicRoute><LoginPage /></PublicRoute>} />
|
||||
<Route path="/change-password" element={<ProtectedRoute><ChangePasswordPage /></ProtectedRoute>} /> {/* Asumimos que se accede logueado */}
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Routes> {/* Un solo <Routes> de nivel superior */}
|
||||
<Route path="/login" element={<PublicRoute><LoginPage /></PublicRoute>} />
|
||||
|
||||
{/* Rutas Protegidas dentro del Layout Principal */}
|
||||
<Route
|
||||
path="/*" // Captura todas las demás rutas
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<MainLayout> {/* Layout que tendrá la navegación principal */}
|
||||
{/* Aquí irán las rutas de los módulos */}
|
||||
<Routes>
|
||||
<Route index element={<HomePage />} /> {/* Página por defecto al loguearse */}
|
||||
{/* <Route path="/usuarios" element={<GestionUsuariosPage />} /> */}
|
||||
{/* <Route path="/zonas" element={<GestionZonasPage />} /> */}
|
||||
{/* ... otras rutas de módulos ... */}
|
||||
<Route path="*" element={<Navigate to="/" replace />} /> {/* Redirige rutas no encontradas al home */}
|
||||
</Routes>
|
||||
</MainLayout>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
{/* Rutas Protegidas que usan el MainLayout */}
|
||||
<Route
|
||||
path="/" // La ruta padre para todas las secciones protegidas
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<MainLayoutWrapper/>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
>
|
||||
{/* Rutas hijas que se renderizarán en el Outlet de MainLayoutWrapper */}
|
||||
<Route index element={<HomePage />} /> {/* Para la ruta exacta "/" */}
|
||||
|
||||
{/* Módulo de Distribución (anidado) */}
|
||||
<Route path="distribucion" element={<DistribucionIndexPage />}>
|
||||
<Route index element={<Navigate to="es-canillas" replace />} />
|
||||
<Route path="es-canillas" element={<ESCanillasPage />} />
|
||||
<Route path="control-devoluciones" element={<ControlDevolucionesPage />} />
|
||||
<Route path="es-distribuidores" element={<ESDistribuidoresPage />} />
|
||||
<Route path="salidas-otros-destinos" element={<SalidasOtrosDestinosPage />} />
|
||||
<Route path="canillas" element={<CanillasPage />} />
|
||||
<Route path="distribuidores" element={<DistribuidoresPage />} />
|
||||
<Route path="publicaciones" element={<PublicacionesPage />} />
|
||||
<Route path="otros-destinos" element={<OtrosDestinosPage />} />
|
||||
<Route path="zonas" element={<ZonasPage />} />
|
||||
<Route path="empresas" element={<EmpresasPage />} />
|
||||
</Route>
|
||||
|
||||
{/* Módulo Contable (anidado) */}
|
||||
<Route path="contables" element={<ContablesIndexPage />}>
|
||||
<Route index element={<Navigate to="tipos-pago" replace />} />
|
||||
<Route path="tipos-pago" element={<GestionarTiposPagoPage />} />
|
||||
{/* Futuras sub-rutas de contables aquí */}
|
||||
</Route>
|
||||
|
||||
{/* Otros Módulos Principales (estos son "finales", no tienen más hijos) */}
|
||||
<Route path="impresion" element={<PlaceholderPage moduleName="Impresión" />} />
|
||||
<Route path="reportes" element={<PlaceholderPage moduleName="Reportes" />} />
|
||||
<Route path="radios" element={<PlaceholderPage moduleName="Radios" />} />
|
||||
{/* <Route path="usuarios" element={<PlaceholderPage moduleName="Usuarios" />} /> */}
|
||||
|
||||
{/* Ruta catch-all DENTRO del layout protegido */}
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Route> {/* Cierre de la ruta padre "/" */}
|
||||
|
||||
{/* Podrías tener un catch-all global aquí si una ruta no coincide EN ABSOLUTO,
|
||||
pero el path="*" dentro de la ruta "/" ya debería manejar la mayoría de los casos
|
||||
después de un login exitoso.
|
||||
Si un usuario no autenticado intenta una ruta inválida, ProtectedRoute lo manda a /login.
|
||||
*/}
|
||||
{/* <Route path="*" element={<Navigate to="/login" replace />} /> */}
|
||||
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppRoutes;
|
||||
Reference in New Issue
Block a user