import { useEffect, useState, type FormEvent, type ReactNode } from "react"; import { Copy, Plus, Users } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { getStoredToken, type AuthUser } from "@/lib/auth"; import { createInvitation, listInvitations, listUsers, type Invitation } from "@/lib/users"; import type { Client } from "@/lib/clients"; type UsersViewProps = { clients: Client[]; }; const roleLabels: Record = { super_admin: "Super-admin", agency_user: "Agência", client_viewer: "Cliente", }; export function UsersView({ clients }: UsersViewProps) { const [users, setUsers] = useState([]); const [invitations, setInvitations] = useState([]); const [email, setEmail] = useState(""); const [role, setRole] = useState("agency_user"); const [clientId, setClientId] = useState(""); const [createdURL, setCreatedURL] = useState(""); const [inviteStatus, setInviteStatus] = useState(""); const [isLoading, setIsLoading] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(""); useEffect(() => { void refresh(); }, []); async function refresh() { const token = getStoredToken(); if (!token) return; setIsLoading(true); setError(""); try { const [loadedUsers, loadedInvitations] = await Promise.all([listUsers(token), listInvitations(token)]); setUsers(loadedUsers); setInvitations(loadedInvitations); } catch (err) { setError(err instanceof Error ? err.message : "Não foi possível carregar acessos."); } finally { setIsLoading(false); } } async function handleInvite(event: FormEvent) { event.preventDefault(); const token = getStoredToken(); if (!token) return; setIsSubmitting(true); setError(""); setCreatedURL(""); setInviteStatus(""); try { const invitation = await createInvitation(token, { email, role, client_id: role === "client_viewer" ? clientId : undefined, }); setInvitations((current) => [invitation, ...current]); setEmail(""); setClientId(""); setCreatedURL(invitation.invitation_url ?? ""); setInviteStatus( invitation.email_sent ? "Convite criado e e-mail enviado." : invitation.email_error || "Convite criado. Configure o SMTP para enviar por e-mail ou copie o link abaixo.", ); } catch (err) { setError(err instanceof Error ? err.message : "Não foi possível criar o convite."); } finally { setIsSubmitting(false); } } async function copyInvitationURL() { if (!createdURL) return; await navigator.clipboard.writeText(createdURL); } return (

Gestão de Acessos

Gerencie usuários da agência e clientes.

Convidar usuário
setEmail(event.target.value)} required />
{inviteStatus && (
{inviteStatus}
)} {createdURL && (
Link do convite
)} {error && (
{error}
)}
{users.map((user) => (

{user.name}

{user.email}

{roleLabels[user.role]}
))}
{invitations.map((invitation) => (

{invitation.email}

{invitation.client_name ? `Cliente: ${invitation.client_name}` : "Acesso da agência"}

{invitation.accepted_at ? "Aceito" : roleLabels[invitation.role]}

Expira em {new Intl.DateTimeFormat("pt-BR", { dateStyle: "medium" }).format(new Date(invitation.expires_at))}

))}
); } function AccessList({ title, emptyText, isLoading, children }: { title: string; emptyText: string; isLoading: boolean; children: ReactNode }) { const hasChildren = Array.isArray(children) ? children.length > 0 : Boolean(children); return (

{title}

{isLoading &&

Carregando...

} {!isLoading && !hasChildren && (

{emptyText}

)} {!isLoading && hasChildren &&
{children}
}
); }