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:
		
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/CanillasPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/CanillasPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const CanillasPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de Canillas</Typography>; | ||||
| }; | ||||
| export default CanillasPage; | ||||
| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const CtrlDevolucionesPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión del Control de Devoluciones</Typography>; | ||||
| }; | ||||
| export default CtrlDevolucionesPage; | ||||
							
								
								
									
										88
									
								
								Frontend/src/pages/Distribucion/DistribucionIndexPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								Frontend/src/pages/Distribucion/DistribucionIndexPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| // src/pages/distribucion/DistribucionIndexPage.tsx | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import { Box, Tabs, Tab, Paper, Typography } from '@mui/material'; | ||||
| import { Outlet, useNavigate, useLocation, Link as RouterLink } from 'react-router-dom'; | ||||
|  | ||||
| // Define las sub-pestañas del módulo Distribución | ||||
| // El path es relativo a la ruta base del módulo (ej: /distribucion) | ||||
| const distribucionSubModules = [ | ||||
|   { label: 'E/S Canillas', path: 'es-canillas' }, // Se convertirá en /distribucion/es-canillas | ||||
|   { label: 'Ctrl. Devoluciones', path: 'control-devoluciones' }, | ||||
|   { label: 'E/S Distribuidores', path: 'es-distribuidores' }, | ||||
|   { label: 'Salidas Otros Dest.', path: 'salidas-otros-destinos' }, | ||||
|   { label: 'Canillas', path: 'canillas' }, | ||||
|   { label: 'Distribuidores', path: 'distribuidores' }, | ||||
|   { label: 'Publicaciones', path: 'publicaciones' }, | ||||
|   { label: 'Otros Destinos', path: 'otros-destinos' }, | ||||
|   { label: 'Zonas', path: 'zonas' }, | ||||
|   { label: 'Empresas', path: 'empresas' }, | ||||
| ]; | ||||
|  | ||||
| const DistribucionIndexPage: React.FC = () => { | ||||
|   const navigate = useNavigate(); | ||||
|   const location = useLocation(); | ||||
|   const [selectedSubTab, setSelectedSubTab] = useState<number | false>(false); | ||||
|  | ||||
|   // Sincronizar el sub-tab con la URL actual | ||||
|   useEffect(() => { | ||||
|     // location.pathname será algo como /distribucion/canillas | ||||
|     // Necesitamos extraer la última parte para compararla con los paths de subSubModules | ||||
|     const currentBasePath = '/distribucion'; // Ruta base de este módulo | ||||
|     const subPath = location.pathname.startsWith(currentBasePath + '/') | ||||
|                       ? location.pathname.substring(currentBasePath.length + 1) | ||||
|                       : (location.pathname === currentBasePath ? distribucionSubModules[0]?.path : undefined); // Si es /distribucion, selecciona el primero | ||||
|  | ||||
|     const activeTabIndex = distribucionSubModules.findIndex( | ||||
|       (subModule) => subModule.path === subPath | ||||
|     ); | ||||
|  | ||||
|     if (activeTabIndex !== -1) { | ||||
|       setSelectedSubTab(activeTabIndex); | ||||
|     } else { | ||||
|       // Si no coincide ninguna sub-ruta, pero estamos en /distribucion, ir al primer tab | ||||
|       if (location.pathname === currentBasePath && distribucionSubModules.length > 0) { | ||||
|          navigate(distribucionSubModules[0].path, { replace: true }); // Navegar a la primera sub-ruta | ||||
|          setSelectedSubTab(0); | ||||
|       } else { | ||||
|          setSelectedSubTab(false); // Ningún sub-tab activo | ||||
|       } | ||||
|     } | ||||
|   }, [location.pathname, navigate]); | ||||
|  | ||||
|   const handleSubTabChange = (_event: React.SyntheticEvent, newValue: number) => { | ||||
|     setSelectedSubTab(newValue); | ||||
|     navigate(distribucionSubModules[newValue].path); // Navega a la sub-ruta (ej: 'canillas') | ||||
|   }; | ||||
|  | ||||
|   return ( | ||||
|     <Box> | ||||
|       <Typography variant="h5" gutterBottom>Módulo de Distribución</Typography> | ||||
|       <Paper square elevation={1}> | ||||
|         <Tabs | ||||
|           value={selectedSubTab} | ||||
|           onChange={handleSubTabChange} | ||||
|           indicatorColor="primary" | ||||
|           textColor="primary" | ||||
|           variant="scrollable" | ||||
|           scrollButtons="auto" | ||||
|           aria-label="sub-módulos de distribución" | ||||
|         > | ||||
|           {distribucionSubModules.map((subModule) => ( | ||||
|             // Usar RouterLink para que el tab se comporte como un enlace y actualice la URL | ||||
|             // La navegación real la manejamos con navigate en handleSubTabChange | ||||
|             // para poder actualizar el estado del tab seleccionado. | ||||
|             // Podríamos usar `component={RouterLink} to={subModule.path}` también, | ||||
|             // pero manejarlo con navigate da más control sobre el estado. | ||||
|             <Tab key={subModule.path} label={subModule.label} /> | ||||
|           ))} | ||||
|         </Tabs> | ||||
|       </Paper> | ||||
|       <Box sx={{ pt: 2 }}> {/* Padding para el contenido de la sub-pestaña */} | ||||
|         {/* Outlet renderizará el componente de la sub-ruta activa (ej: CanillasPage) */} | ||||
|         <Outlet /> | ||||
|       </Box> | ||||
|     </Box> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| export default DistribucionIndexPage; | ||||
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/DistribuidoresPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/DistribuidoresPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const DistribuidoresPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de Distribuidores</Typography>; | ||||
| }; | ||||
| export default DistribuidoresPage; | ||||
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/ESCanillasPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/ESCanillasPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const ESCanillasPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de E/S de Canillas</Typography>; | ||||
| }; | ||||
| export default ESCanillasPage; | ||||
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/ESDistribuidoresPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/ESDistribuidoresPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const ESDistribuidoresPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de E/S de Distribuidores</Typography>; | ||||
| }; | ||||
| export default ESDistribuidoresPage; | ||||
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/EmpresasPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/EmpresasPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const EmpresasPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de Empresas</Typography>; | ||||
| }; | ||||
| export default EmpresasPage; | ||||
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/OtrosDestinosPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/OtrosDestinosPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const OtrosDestinosPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de Otros Destinos</Typography>; | ||||
| }; | ||||
| export default OtrosDestinosPage; | ||||
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/PublicacionesPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/PublicacionesPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const PublicacionesPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de Publicaciones</Typography>; | ||||
| }; | ||||
| export default PublicacionesPage; | ||||
| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const SalidastrosDestinosPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de Salidas a Otros Destinos</Typography>; | ||||
| }; | ||||
| export default SalidastrosDestinosPage; | ||||
							
								
								
									
										7
									
								
								Frontend/src/pages/Distribucion/ZonasPage.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Frontend/src/pages/Distribucion/ZonasPage.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import { Typography } from '@mui/material'; | ||||
|  | ||||
| const ZonasPage: React.FC = () => { | ||||
|   return <Typography variant="h6">Página de Gestión de Zonas</Typography>; | ||||
| }; | ||||
| export default ZonasPage; | ||||
		Reference in New Issue
	
	Block a user