'use client'; import { useState } from 'react'; import { Header } from '@/components/layouts/header'; import { Card, CardContent, CardHeader, CardTitle, Button, Input, Label, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@horux/shared-ui'; import { useAuthStore } from '@/stores/auth-store'; import { isGlobalAdminRfc, type PlatformRole } from '@horux/shared'; import { useStaff, useSearchUsers, useGrantRole, useRevokeRole } from '@/lib/hooks/use-platform-staff'; import { ShieldAlert, Shield, ShieldCheck, HeadphonesIcon, TrendingUp, DollarSign, UserPlus, X, Loader2, Search, Cpu } from 'lucide-react'; const ROLE_META: Record = { platform_admin: { label: 'Admin', desc: 'Todo: gestión staff, precios, clientes, facturas', icon: ShieldCheck, color: 'bg-red-100 text-red-700 border-red-200' }, platform_ti: { label: 'TI', desc: 'Equipo de TI. Mismos permisos que Admin (diferencia solo en trazabilidad)', icon: Cpu, color: 'bg-slate-100 text-slate-700 border-slate-200' }, platform_support: { label: 'Support', desc: 'Ver tenants, resolver tickets', icon: HeadphonesIcon, color: 'bg-blue-100 text-blue-700 border-blue-200' }, platform_sales: { label: 'Vendedor', desc: 'Enviar invitaciones a nuevos despachos', icon: TrendingUp, color: 'bg-green-100 text-green-700 border-green-200' }, platform_finance: { label: 'Finance', desc: 'Pagos, facturas manuales, editar precios', icon: DollarSign, color: 'bg-amber-100 text-amber-700 border-amber-200' }, }; const ALL_ROLES: PlatformRole[] = ['platform_admin', 'platform_ti', 'platform_support', 'platform_sales', 'platform_finance']; export default function StaffPage() { const { user } = useAuthStore(); const isGlobalAdmin = isGlobalAdminRfc(user?.tenantRfc, user?.role, user?.platformRoles); const { data: staff = [], isLoading } = useStaff(); const grantRole = useGrantRole(); const revokeRole = useRevokeRole(); const [addOpen, setAddOpen] = useState(false); const [searchQ, setSearchQ] = useState(''); const { data: candidates = [] } = useSearchUsers(searchQ); const [pickedUserId, setPickedUserId] = useState(null); const [pickedRole, setPickedRole] = useState('platform_support'); if (!isGlobalAdmin) { return ( <>

Acceso restringido

Solo platform_admin puede gestionar staff.

); } const handleGrant = async () => { if (!pickedUserId) return; try { await grantRole.mutateAsync({ userId: pickedUserId, role: pickedRole }); setAddOpen(false); setSearchQ(''); setPickedUserId(null); } catch (err: any) { alert(err?.response?.data?.message || err?.message || 'Error al asignar rol'); } }; const handleRevoke = async (userId: string, role: PlatformRole, userEmail: string) => { if (!confirm(`¿Quitar el rol "${ROLE_META[role].label}" a ${userEmail}?`)) return; try { await revokeRole.mutateAsync({ userId, role }); } catch (err: any) { alert(err?.response?.data?.message || err?.message || 'Error al quitar rol'); } }; return ( <>

Staff interno de Horux 360 con poderes transversales. platform_admin implica todos los otros roles.

Equipo ({staff.length}) {isLoading ? (

Cargando...

) : staff.length === 0 ? (

Todavía no hay staff. Agrega al primer miembro con el botón arriba.

) : (
{staff.map(s => ( ))}
Usuario Tenant origen Roles Acciones
{s.nombre}
{s.email}
{s.tenant ? (
{s.tenant.nombre}
{s.tenant.rfc}
) : }
{s.roles.map(r => { const meta = ROLE_META[r]; const Icon = meta.icon; return ( {meta.label} ); })}
)}
Descripción de roles
{ALL_ROLES.map(r => { const m = ROLE_META[r]; const Icon = m.icon; return (
{m.label}

{m.desc}

); })}
{/* Add staff dialog */} Agregar rol de staff Busca al usuario por email o nombre y asígnale un rol de plataforma.
{ setSearchQ(e.target.value); setPickedUserId(null); }} placeholder="email o nombre (min 2 caracteres)" className="pl-8" />
{searchQ.length >= 2 && candidates.length > 0 && !pickedUserId && (
{candidates.map(c => ( ))}
)}
{ALL_ROLES.map(r => { const m = ROLE_META[r]; const Icon = m.icon; return ( ); })}
); }