Fix navigation and routing for client users
- Sidebar: Show proper navigation for client/employee roles - App.tsx: Add HomeRedirect to route users based on role - Client users now go directly to their company detail page - Added AnalystRoute to protect ClientesList Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,29 @@ function AdminRoute({ children }: { children: React.ReactNode }) {
|
|||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function AnalystRoute({ children }: { children: React.ReactNode }) {
|
||||||
|
const { isAdmin, isAnalista } = useAuth();
|
||||||
|
|
||||||
|
if (!isAdmin && !isAnalista) {
|
||||||
|
return <Navigate to="/" replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Componente para redirigir a la página correcta según el rol
|
||||||
|
function HomeRedirect() {
|
||||||
|
const { user, isCliente, isEmpleado } = useAuth();
|
||||||
|
|
||||||
|
// Si es cliente o empleado, redirigir a su empresa
|
||||||
|
if ((isCliente || isEmpleado) && user?.cliente_id) {
|
||||||
|
return <Navigate to={`/clientes/${user.cliente_id}`} replace />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si es admin o analista, ir a lista de clientes
|
||||||
|
return <Navigate to="/clientes" replace />;
|
||||||
|
}
|
||||||
|
|
||||||
function AppRoutes() {
|
function AppRoutes() {
|
||||||
const { user, loading } = useAuth();
|
const { user, loading } = useAuth();
|
||||||
|
|
||||||
@@ -68,13 +91,24 @@ function AppRoutes() {
|
|||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Route index element={<Navigate to="/clientes" replace />} />
|
<Route index element={<HomeRedirect />} />
|
||||||
<Route path="clientes" element={<ClientesList />} />
|
|
||||||
|
{/* Lista de clientes - solo admin/analista */}
|
||||||
|
<Route
|
||||||
|
path="clientes"
|
||||||
|
element={
|
||||||
|
<AnalystRoute>
|
||||||
|
<ClientesList />
|
||||||
|
</AnalystRoute>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Detalle de cliente - todos pueden ver (con restricciones en backend) */}
|
||||||
<Route path="clientes/:id" element={<ClienteDetail />} />
|
<Route path="clientes/:id" element={<ClienteDetail />} />
|
||||||
<Route path="dashboard/:clienteId/:reporteId" element={<Dashboard />} />
|
<Route path="dashboard/:clienteId/:reporteId" element={<Dashboard />} />
|
||||||
<Route path="reportes/:id" element={<ReporteView />} />
|
<Route path="reportes/:id" element={<ReporteView />} />
|
||||||
|
|
||||||
{/* Rutas de administración */}
|
{/* Rutas de administración - solo admin */}
|
||||||
<Route path="admin" element={<AdminRoute><Navigate to="/admin/usuarios" replace /></AdminRoute>} />
|
<Route path="admin" element={<AdminRoute><Navigate to="/admin/usuarios" replace /></AdminRoute>} />
|
||||||
<Route path="admin/usuarios" element={<AdminRoute><AdminUsuarios /></AdminRoute>} />
|
<Route path="admin/usuarios" element={<AdminRoute><AdminUsuarios /></AdminRoute>} />
|
||||||
<Route path="admin/giros" element={<AdminRoute><AdminGiros /></AdminRoute>} />
|
<Route path="admin/giros" element={<AdminRoute><AdminGiros /></AdminRoute>} />
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ import { NavLink } from 'react-router-dom';
|
|||||||
import { useAuth } from '../../context/AuthContext';
|
import { useAuth } from '../../context/AuthContext';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
const navItems = [
|
|
||||||
{ name: 'Clientes', path: '/clientes', icon: '🏢', roles: ['admin', 'analista'] },
|
|
||||||
{ name: 'Mi Empresa', path: '/clientes', icon: '📊', roles: ['cliente', 'empleado'] },
|
|
||||||
];
|
|
||||||
|
|
||||||
const adminItems = [
|
const adminItems = [
|
||||||
{ name: 'Usuarios', path: '/admin/usuarios', icon: '👥' },
|
{ name: 'Usuarios', path: '/admin/usuarios', icon: '👥' },
|
||||||
{ name: 'Giros', path: '/admin/giros', icon: '🏷️' },
|
{ name: 'Giros', path: '/admin/giros', icon: '🏷️' },
|
||||||
@@ -15,11 +10,27 @@ const adminItems = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default function Sidebar() {
|
export default function Sidebar() {
|
||||||
const { user, isAdmin } = useAuth();
|
const { user, isAdmin, isAnalista, isCliente, isEmpleado } = useAuth();
|
||||||
|
|
||||||
const filteredNavItems = navItems.filter(
|
// Determinar navegación principal según rol
|
||||||
(item) => item.roles.includes(user?.role || '')
|
const getMainNavItems = () => {
|
||||||
);
|
if (isAdmin || isAnalista) {
|
||||||
|
return [
|
||||||
|
{ name: 'Clientes', path: '/clientes', icon: '🏢' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((isCliente || isEmpleado) && user?.cliente_id) {
|
||||||
|
return [
|
||||||
|
{ name: 'Mi Empresa', path: `/clientes/${user.cliente_id}`, icon: '🏢' },
|
||||||
|
{ name: 'Dashboard', path: `/clientes/${user.cliente_id}`, icon: '📊' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const mainNavItems = getMainNavItems();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="fixed left-0 top-0 h-screen w-64 bg-horux-dark text-white flex flex-col z-50">
|
<aside className="fixed left-0 top-0 h-screen w-64 bg-horux-dark text-white flex flex-col z-50">
|
||||||
@@ -34,9 +45,9 @@ export default function Sidebar() {
|
|||||||
<div className="text-xs uppercase text-gray-500 font-semibold mb-2 px-3">
|
<div className="text-xs uppercase text-gray-500 font-semibold mb-2 px-3">
|
||||||
Principal
|
Principal
|
||||||
</div>
|
</div>
|
||||||
{filteredNavItems.map((item) => (
|
{mainNavItems.map((item, index) => (
|
||||||
<NavLink
|
<NavLink
|
||||||
key={item.path}
|
key={`${item.path}-${index}`}
|
||||||
to={item.path}
|
to={item.path}
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
clsx(
|
clsx(
|
||||||
@@ -52,6 +63,7 @@ export default function Sidebar() {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{/* Sección de administración - solo para admin */}
|
||||||
{isAdmin && (
|
{isAdmin && (
|
||||||
<>
|
<>
|
||||||
<div className="text-xs uppercase text-gray-500 font-semibold mt-6 mb-2 px-3">
|
<div className="text-xs uppercase text-gray-500 font-semibold mt-6 mb-2 px-3">
|
||||||
@@ -82,7 +94,7 @@ export default function Sidebar() {
|
|||||||
<div className="p-4 border-t border-gray-700">
|
<div className="p-4 border-t border-gray-700">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-10 h-10 rounded-full bg-horux-accent flex items-center justify-center text-lg">
|
<div className="w-10 h-10 rounded-full bg-horux-accent flex items-center justify-center text-lg">
|
||||||
{user?.nombre?.charAt(0).toUpperCase()}
|
{user?.nombre?.charAt(0).toUpperCase() || '?'}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm font-medium truncate">{user?.nombre}</p>
|
<p className="text-sm font-medium truncate">{user?.nombre}</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user