import { useMemo, useState } from "react"; import { Users, Plus, Trash2, ShieldCheck, Shield } from "lucide-react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { Button } from "@/components/button"; import { managerPost } from "@/main-axios"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; interface SystemUser { name: string; uid: number; shell: string; } interface UsersData { users: SystemUser[]; sudoers: string[]; } export function UserManagerCard({ hostId }: { hostId: number | null }) { const { t } = useTranslation(); const { data, loading, error, refresh } = useManagerData( hostId, "users", ); const [newUser, setNewUser] = useState(""); const [filter, setFilter] = useState(""); const [busy, setBusy] = useState(null); const sudoers = new Set(data?.sudoers ?? []); const users = useMemo( () => (data?.users ?? []).filter( (u) => !filter || u.name.toLowerCase().includes(filter.toLowerCase()), ), [data?.users, filter], ); const action = async (act: string, username: string, group?: string) => { if (hostId == null) return; setBusy(username); try { const res = await managerPost<{ success: boolean; output: string }>( hostId, "users", { action: act, username, group }, "action", ); if (res.success) { toast.success(t("hostMetrics.managers.actionDone", { name: username })); if (act === "create") setNewUser(""); refresh(); } else { toast.error(res.output || t("hostMetrics.managers.actionFailed")); } } catch (e) { toast.error(extractError(e).message); } finally { setBusy(null); } }; return ( } loading={loading} error={error} onRefresh={refresh} >
setNewUser(e.target.value)} placeholder={t("hostMetrics.managers.newUsername")} className="h-7 flex-1 border border-border bg-background px-2 text-xs outline-none focus:ring-1 focus:ring-ring" />
{users.map((u) => { const isSudoer = sudoers.has(u.name); return (
{u.name} {isSudoer && ( )} {u.uid}
); })}
); }