feat: invitaciones trial como pestaña en admin usuarios + sidebar
- Quitado Invitaciones Trial del sidebar (4 layouts) - Agregado tab Invitaciones Trial dentro de /admin/usuarios - Componente reutilizable invitaciones-trial-tab.tsx - Agregada nueva opcion Tareas en el sidebar principal
This commit is contained in:
@@ -0,0 +1,252 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Button, Input, Label, Card, CardContent, CardHeader, CardTitle, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@horux/shared-ui';
|
||||||
|
import { getAllInvitations, createInvitation, cancelInvitation } from '@/lib/api/trial-invitations';
|
||||||
|
import { getTenants } from '@/lib/api/tenants';
|
||||||
|
import { Gift, X, Clock, CheckCircle2, AlertTriangle, Loader2 } from 'lucide-react';
|
||||||
|
|
||||||
|
interface TenantOption {
|
||||||
|
id: string;
|
||||||
|
nombre: string;
|
||||||
|
rfc: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Invitation {
|
||||||
|
id: string;
|
||||||
|
tenantId: string;
|
||||||
|
plan: string;
|
||||||
|
durationDays: number;
|
||||||
|
status: string;
|
||||||
|
token: string;
|
||||||
|
sentAt: string;
|
||||||
|
expiresAt: string;
|
||||||
|
acceptedAt: string | null;
|
||||||
|
tenant: {
|
||||||
|
nombre: string;
|
||||||
|
rfc: string;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InvitacionesTrialTab() {
|
||||||
|
const [tenants, setTenants] = useState<TenantOption[]>([]);
|
||||||
|
const [invitations, setInvitations] = useState<Invitation[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [creating, setCreating] = useState(false);
|
||||||
|
const [selectedTenantId, setSelectedTenantId] = useState('');
|
||||||
|
const [durationDays, setDurationDays] = useState('30');
|
||||||
|
const [plan, setPlan] = useState('business_control');
|
||||||
|
const [message, setMessage] = useState<{ kind: 'ok' | 'err'; text: string } | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function loadData() {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const [tenantsData, invitationsData] = await Promise.all([
|
||||||
|
getTenants(),
|
||||||
|
getAllInvitations(),
|
||||||
|
]);
|
||||||
|
setTenants(tenantsData);
|
||||||
|
setInvitations(invitationsData);
|
||||||
|
} catch (err: any) {
|
||||||
|
setMessage({ kind: 'err', text: err?.response?.data?.message || 'Error al cargar datos' });
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCreate() {
|
||||||
|
if (!selectedTenantId || !durationDays) {
|
||||||
|
setMessage({ kind: 'err', text: 'Selecciona un despacho y duración' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCreating(true);
|
||||||
|
setMessage(null);
|
||||||
|
try {
|
||||||
|
await createInvitation({
|
||||||
|
tenantId: selectedTenantId,
|
||||||
|
plan,
|
||||||
|
durationDays: parseInt(durationDays, 10),
|
||||||
|
});
|
||||||
|
setMessage({ kind: 'ok', text: 'Invitación enviada correctamente' });
|
||||||
|
setSelectedTenantId('');
|
||||||
|
setDurationDays('30');
|
||||||
|
loadData();
|
||||||
|
} catch (err: any) {
|
||||||
|
setMessage({ kind: 'err', text: err?.response?.data?.message || 'Error al crear invitación' });
|
||||||
|
} finally {
|
||||||
|
setCreating(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCancel(id: string) {
|
||||||
|
if (!confirm('¿Seguro que quieres cancelar esta invitación?')) return;
|
||||||
|
try {
|
||||||
|
await cancelInvitation(id);
|
||||||
|
setMessage({ kind: 'ok', text: 'Invitación cancelada' });
|
||||||
|
loadData();
|
||||||
|
} catch (err: any) {
|
||||||
|
setMessage({ kind: 'err', text: err?.response?.data?.message || 'Error al cancelar' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusIcon(status: string) {
|
||||||
|
switch (status) {
|
||||||
|
case 'pending': return <Clock className="h-4 w-4 text-amber-500" />;
|
||||||
|
case 'accepted': return <CheckCircle2 className="h-4 w-4 text-green-500" />;
|
||||||
|
case 'expired': return <AlertTriangle className="h-4 w-4 text-red-500" />;
|
||||||
|
case 'cancelled': return <X className="h-4 w-4 text-gray-500" />;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusLabel(status: string) {
|
||||||
|
switch (status) {
|
||||||
|
case 'pending': return 'Pendiente';
|
||||||
|
case 'accepted': return 'Aceptada';
|
||||||
|
case 'expired': return 'Expirada';
|
||||||
|
case 'cancelled': return 'Cancelada';
|
||||||
|
default: return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
{/* Toast de resultado */}
|
||||||
|
{message && (
|
||||||
|
<div
|
||||||
|
className={`max-w-3xl rounded-lg px-4 py-3 text-sm ${
|
||||||
|
message.kind === 'ok'
|
||||||
|
? 'bg-green-50 dark:bg-green-950 border border-green-200 dark:border-green-800 text-green-800 dark:text-green-300'
|
||||||
|
: 'bg-red-50 dark:bg-red-950 border border-red-200 dark:border-red-800 text-red-800 dark:text-red-300'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{message.text}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Formulario de creación */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-lg">Nueva invitación</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="grid md:grid-cols-3 gap-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Despacho</Label>
|
||||||
|
<Select value={selectedTenantId} onValueChange={setSelectedTenantId}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Selecciona un despacho" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{tenants.map((t) => (
|
||||||
|
<SelectItem key={t.id} value={t.id}>
|
||||||
|
{t.nombre} ({t.rfc})
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Plan</Label>
|
||||||
|
<Select value={plan} onValueChange={setPlan}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="business_control">Business Control</SelectItem>
|
||||||
|
<SelectItem value="business_cloud">Enterprise</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>Duración (días)</Label>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
min={1}
|
||||||
|
max={365}
|
||||||
|
value={durationDays}
|
||||||
|
onChange={(e) => setDurationDays(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button onClick={handleCreate} disabled={creating}>
|
||||||
|
{creating ? <Loader2 className="h-4 w-4 animate-spin mr-2" /> : <Gift className="h-4 w-4 mr-2" />}
|
||||||
|
Enviar invitación
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Tabla de invitaciones */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-lg">Historial de invitaciones</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{loading ? (
|
||||||
|
<div className="flex justify-center py-8">
|
||||||
|
<Loader2 className="h-6 w-6 animate-spin text-primary" />
|
||||||
|
</div>
|
||||||
|
) : invitations.length === 0 ? (
|
||||||
|
<p className="text-muted-foreground text-center py-8">No hay invitaciones enviadas</p>
|
||||||
|
) : (
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b">
|
||||||
|
<th className="text-left py-2 px-3">Despacho</th>
|
||||||
|
<th className="text-left py-2 px-3">Plan</th>
|
||||||
|
<th className="text-left py-2 px-3">Días</th>
|
||||||
|
<th className="text-left py-2 px-3">Estado</th>
|
||||||
|
<th className="text-left py-2 px-3">Enviado</th>
|
||||||
|
<th className="text-left py-2 px-3">Expira</th>
|
||||||
|
<th className="text-left py-2 px-3"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{invitations.map((inv) => (
|
||||||
|
<tr key={inv.id} className="border-b hover:bg-muted/50">
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<div className="font-medium">{inv.tenant?.nombre || '—'}</div>
|
||||||
|
<div className="text-xs text-muted-foreground">{inv.tenant?.rfc || '—'}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
{inv.plan === 'business_control' ? 'Business Control' : inv.plan === 'business_cloud' ? 'Enterprise' : inv.plan}
|
||||||
|
</td>
|
||||||
|
<td className="py-2 px-3">{inv.durationDays}</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
{statusIcon(inv.status)}
|
||||||
|
{statusLabel(inv.status)}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
{new Date(inv.sentAt).toLocaleDateString('es-MX')}
|
||||||
|
</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
{new Date(inv.expiresAt).toLocaleDateString('es-MX')}
|
||||||
|
</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
{inv.status === 'pending' && (
|
||||||
|
<button
|
||||||
|
onClick={() => handleCancel(inv.id)}
|
||||||
|
className="text-destructive hover:underline text-xs"
|
||||||
|
>
|
||||||
|
Cancelar
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { DashboardShell } from '@/components/layouts/dashboard-shell';
|
import { DashboardShell } from '@/components/layouts/dashboard-shell';
|
||||||
import { Card, CardContent, CardHeader, CardTitle, Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@horux/shared-ui';
|
import { Card, CardContent, CardHeader, CardTitle, Button, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Tabs, TabsList, TabsTrigger, TabsContent } from '@horux/shared-ui';
|
||||||
import { useAllUsuarios, useCreateUsuarioGlobal, useUpdateUsuarioGlobal, useDeleteUsuarioGlobal } from '@/lib/hooks/use-usuarios';
|
import { useAllUsuarios, useCreateUsuarioGlobal, useUpdateUsuarioGlobal, useDeleteUsuarioGlobal } from '@/lib/hooks/use-usuarios';
|
||||||
import { getTenants, type Tenant } from '@/lib/api/tenants';
|
import { getTenants, type Tenant } from '@/lib/api/tenants';
|
||||||
import { useAuthStore } from '@/stores/auth-store';
|
import { useAuthStore } from '@/stores/auth-store';
|
||||||
import { isGlobalAdminRfc } from '@horux/shared';
|
import { isGlobalAdminRfc } from '@horux/shared';
|
||||||
import { Users, Pencil, Trash2, Shield, Eye, Calculator, Building2, X, Check, UserCog, UserCheck, User, Briefcase, Plus } from 'lucide-react';
|
import { Users, Pencil, Trash2, Shield, Eye, Calculator, Building2, X, Check, UserCog, UserCheck, User, Briefcase, Plus } from 'lucide-react';
|
||||||
import { cn } from '@horux/shared-ui';
|
import { cn } from '@horux/shared-ui';
|
||||||
|
import InvitacionesTrialTab from '../_components/invitaciones-trial-tab';
|
||||||
|
|
||||||
// Mapa de roles + fallback defensivo. El fork despacho introduce roles
|
// Mapa de roles + fallback defensivo. El fork despacho introduce roles
|
||||||
// adicionales (cfo, supervisor, auxiliar, cliente) que no estaban en
|
// adicionales (cfo, supervisor, auxiliar, cliente) que no estaban en
|
||||||
@@ -43,6 +44,7 @@ export default function AdminUsuariosPage() {
|
|||||||
const [editingUser, setEditingUser] = useState<EditingUser | null>(null);
|
const [editingUser, setEditingUser] = useState<EditingUser | null>(null);
|
||||||
const [filterTenant, setFilterTenant] = useState<string>('all');
|
const [filterTenant, setFilterTenant] = useState<string>('all');
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
const [activeTab, setActiveTab] = useState('usuarios');
|
||||||
const [showCreateForm, setShowCreateForm] = useState(false);
|
const [showCreateForm, setShowCreateForm] = useState(false);
|
||||||
const [createFormData, setCreateFormData] = useState({
|
const [createFormData, setCreateFormData] = useState({
|
||||||
email: '',
|
email: '',
|
||||||
@@ -152,6 +154,13 @@ export default function AdminUsuariosPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardShell title="Administracion de Usuarios">
|
<DashboardShell title="Administracion de Usuarios">
|
||||||
|
<Tabs value={activeTab} onValueChange={setActiveTab} defaultValue="usuarios" className="space-y-4">
|
||||||
|
<TabsList>
|
||||||
|
<TabsTrigger value="usuarios">Usuarios</TabsTrigger>
|
||||||
|
<TabsTrigger value="invitaciones-trial">Invitaciones Trial</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="usuarios">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Filtros */}
|
{/* Filtros */}
|
||||||
<Card>
|
<Card>
|
||||||
@@ -425,6 +434,12 @@ export default function AdminUsuariosPage() {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="invitaciones-trial">
|
||||||
|
<InvitacionesTrialTab />
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
</DashboardShell>
|
</DashboardShell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
ClipboardList,
|
ClipboardList,
|
||||||
CreditCard,
|
CreditCard,
|
||||||
Gift,
|
Gift,
|
||||||
|
CheckSquare2,
|
||||||
UserCog,
|
UserCog,
|
||||||
Shield,
|
Shield,
|
||||||
FileWarning,
|
FileWarning,
|
||||||
@@ -56,6 +57,7 @@ const navigation: NavItem[] = [
|
|||||||
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
||||||
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
||||||
|
{ name: 'Tareas', href: '/tareas', icon: CheckSquare2, roles: ['owner', 'cfo', 'contador', 'auxiliar', 'supervisor'] },
|
||||||
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
||||||
];
|
];
|
||||||
@@ -64,7 +66,6 @@ const adminNavigation: NavItem[] = [
|
|||||||
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
||||||
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
||||||
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
||||||
{ name: 'Invitaciones Trial', href: '/admin/invitaciones-trial', icon: Gift },
|
|
||||||
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
ClipboardList,
|
ClipboardList,
|
||||||
CreditCard,
|
CreditCard,
|
||||||
Gift,
|
Gift,
|
||||||
|
CheckSquare2,
|
||||||
UserCog,
|
UserCog,
|
||||||
Shield,
|
Shield,
|
||||||
FileWarning,
|
FileWarning,
|
||||||
@@ -55,6 +56,7 @@ const navigation: NavItem[] = [
|
|||||||
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
||||||
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
||||||
|
{ name: 'Tareas', href: '/tareas', icon: CheckSquare2, roles: ['owner', 'cfo', 'contador', 'auxiliar', 'supervisor'] },
|
||||||
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
||||||
];
|
];
|
||||||
@@ -63,7 +65,6 @@ const adminNavigation: NavItem[] = [
|
|||||||
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
||||||
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
||||||
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
||||||
{ name: 'Invitaciones Trial', href: '/admin/invitaciones-trial', icon: Gift },
|
|
||||||
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
ClipboardList,
|
ClipboardList,
|
||||||
ListChecks,
|
ListChecks,
|
||||||
Gift,
|
Gift,
|
||||||
|
CheckSquare2,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useAuthStore } from '@/stores/auth-store';
|
import { useAuthStore } from '@/stores/auth-store';
|
||||||
import { logout } from '@/lib/api/auth';
|
import { logout } from '@/lib/api/auth';
|
||||||
@@ -59,6 +60,7 @@ const navigation: NavItem[] = [
|
|||||||
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
||||||
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
||||||
|
{ name: 'Tareas', href: '/tareas', icon: CheckSquare2, roles: ['owner', 'cfo', 'contador', 'auxiliar', 'supervisor'] },
|
||||||
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
||||||
];
|
];
|
||||||
@@ -67,7 +69,6 @@ const adminNavigation: NavItem[] = [
|
|||||||
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
||||||
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
||||||
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
||||||
{ name: 'Invitaciones Trial', href: '/admin/invitaciones-trial', icon: Gift },
|
|
||||||
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
ClipboardList,
|
ClipboardList,
|
||||||
CreditCard,
|
CreditCard,
|
||||||
Gift,
|
Gift,
|
||||||
|
CheckSquare2,
|
||||||
UserCog,
|
UserCog,
|
||||||
Shield,
|
Shield,
|
||||||
FileWarning,
|
FileWarning,
|
||||||
@@ -56,6 +57,7 @@ const navigation: NavItem[] = [
|
|||||||
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
{ name: 'Carteras', href: '/carteras', icon: ClipboardList, roles: ['supervisor', 'auxiliar'] },
|
||||||
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
{ name: 'Contribuyentes', href: '/contribuyentes', icon: Building2, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
{ name: 'Usuarios', href: '/usuarios', icon: Users, roles: ['owner', 'cfo'] },
|
||||||
|
{ name: 'Tareas', href: '/tareas', icon: CheckSquare2, roles: ['owner', 'cfo', 'contador', 'auxiliar', 'supervisor'] },
|
||||||
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
{ name: 'Planes', href: '/configuracion/planes-despacho', icon: CreditCard, roles: ['owner', 'cfo'] },
|
||||||
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
{ name: 'Configuracion', href: '/configuracion', icon: Settings, roles: ['owner', 'cfo'] },
|
||||||
];
|
];
|
||||||
@@ -64,7 +66,6 @@ const adminNavigation: NavItem[] = [
|
|||||||
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
{ name: 'Clientes', href: '/clientes', icon: Building2 },
|
||||||
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
{ name: 'Admin Usuarios', href: '/admin/usuarios', icon: UserCog },
|
||||||
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
{ name: 'Staff', href: '/admin/staff', icon: Shield },
|
||||||
{ name: 'Invitaciones Trial', href: '/admin/invitaciones-trial', icon: Gift },
|
|
||||||
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
{ name: 'Audit Log', href: '/admin/audit-log', icon: FileWarning },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user