import React, { useState, useEffect } from "react"; import { api } from "../services/api"; import { useAuth } from "../contexts/AuthContext"; import { Users, Plus, Shield, UserCheck, UserX, RefreshCw, X, AlertCircle, } from "lucide-react"; const ROLE_COLORS: Record = { owner: "text-fde bg-fde/15", admin: "text-amber-400 bg-amber-500/15", agent: "text-blue-400 bg-blue-500/15", viewer: "text-gray-400 bg-gray-500/15", }; export function UsersPage() { const { user: currentUser } = useAuth(); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [showInvite, setShowInvite] = useState(false); const [inviting, setInviting] = useState(false); const [inviteForm, setInviteForm] = useState({ email: "", name: "", role: "agent" }); const [error, setError] = useState(""); const fetchUsers = async () => { setLoading(true); try { const data = await api.getUsers(); setUsers(data); } catch (err) { console.error("Failed to fetch users:", err); } finally { setLoading(false); } }; useEffect(() => { fetchUsers(); }, []); const handleInvite = async (e: React.FormEvent) => { e.preventDefault(); setInviting(true); setError(""); try { const result = await api.invite(inviteForm.email, inviteForm.name, inviteForm.role); setShowInvite(false); setInviteForm({ email: "", name: "", role: "agent" }); alert(`User invited! Temporary password: ${result.temporaryPassword}`); await fetchUsers(); } catch (err: any) { setError(err.response?.data?.message || "Failed to invite user"); } finally { setInviting(false); } }; const handleToggleActive = async (userId: string, currentlyActive: boolean) => { try { if (currentlyActive) { await api.deleteUser(userId); } else { await api.updateUser(userId, { isActive: true }); } await fetchUsers(); } catch (err: any) { alert(err.response?.data?.message || "Failed to update user"); } }; const handleRoleChange = async (userId: string, role: string) => { try { await api.updateUser(userId, { role }); await fetchUsers(); } catch (err: any) { alert(err.response?.data?.message || "Failed to update role"); } }; const isAdmin = currentUser?.role === "owner" || currentUser?.role === "admin"; const formatDate = (dateStr: string) => { if (!dateStr) return "Never"; return new Date(dateStr).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", }); }; return (

Personnel

Manage your team members

{isAdmin && ( )}
{/* Invite modal */} {showInvite && (

Invite Operator

{error && (
{error}
)}
setInviteForm((p) => ({ ...p, name: e.target.value }))} required className="w-full px-3 py-2 bg-dark-bg border border-dark-border rounded-lg text-sm text-gray-200 focus:outline-none focus:border-od-green" placeholder="John Doe" />
setInviteForm((p) => ({ ...p, email: e.target.value }))} required className="w-full px-3 py-2 bg-dark-bg border border-dark-border rounded-lg text-sm text-gray-200 focus:outline-none focus:border-od-green" placeholder="user@company.com" />
)} {/* User list */} {loading ? (
Loading...
) : (
{isAdmin && } {users.map((u) => ( {isAdmin && ( )} ))}
User Role Status Last LoginActions
{u.name.charAt(0).toUpperCase()}

{u.name}

{u.email}

{isAdmin && u.role !== "owner" && u.id !== currentUser?.id ? ( ) : ( {u.role.charAt(0).toUpperCase() + u.role.slice(1)} )} {u.isActive ? : } {u.isActive ? "Active" : "Inactive"} {formatDate(u.lastLoginAt)} {u.role !== "owner" && u.id !== currentUser?.id && ( )}
)}
); }