"use client"; import { Info, UserPlus } from "lucide-react"; import { useCallback, useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { AddStaffDialog } from "@/components/settings/add-staff-dialog"; import { EmployeeDetailDialog, type StaffMember, } from "@/components/settings/employee-detail-dialog"; import { specialtyLabel } from "@/lib/staff"; import { SettingsCard, SettingsSection, } from "@/components/settings/settings-parts"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogClose, DialogDescription, DialogFooter, DialogHeader, DialogPopup, DialogTitle, } from "@/components/ui/dialog"; import { ROLE_LABELS } from "@/lib/access"; import { apiFetch } from "@/lib/api-client"; import { authClient } from "@/lib/auth-client"; import { notify } from "@/lib/toast"; function roleLabel(role?: string | null): string { if (!role) return ROLE_LABELS.member; return (ROLE_LABELS as Record)[role] ?? role; } function initials(name?: string | null, email?: string | null): string { const source = name?.trim() || email?.trim() || "?"; return ( source .split(/\s+/) .map((w) => w[0]) .filter(Boolean) .join("") .slice(0, 2) .toUpperCase() || "?" ); } export function CareTeamPanel({ initialMemberId, }: { initialMemberId?: string; }) { const { t } = useTranslation(); const { data: session } = authClient.useSession(); const [members, setMembers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [adding, setAdding] = useState(false); const [selected, setSelected] = useState(null); const [pendingRemove, setPendingRemove] = useState(null); const [removing, setRemoving] = useState(false); const load = useCallback(async () => { try { const data = await apiFetch("/api/staff"); setMembers(data); setError(null); } catch (err) { setError( err instanceof Error ? err.message : t("settings.careTeam.loadError"), ); } finally { setLoading(false); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { void load(); }, [load]); // Deep-link: open a specific member (e.g. from a password-reset system card). const appliedDeepLink = useRef(false); useEffect(() => { if (appliedDeepLink.current || !initialMemberId || members.length === 0) return; const target = members.find((m) => m.userId === initialMemberId); if (target) { setSelected(target); appliedDeepLink.current = true; } }, [initialMemberId, members]); const myRole = members.find((m) => m.userId === session?.user?.id)?.role; const canManage = myRole === "owner" || myRole === "admin"; const confirmRemove = async () => { if (!pendingRemove || removing) return; setRemoving(true); const { error: err } = await authClient.organization.removeMember({ memberIdOrEmail: pendingRemove.id, }); setRemoving(false); if (err) { notify.error( t("settings.careTeam.remove.failedTitle"), err.message ?? t("settings.careTeam.remove.failedBody"), ); return; } notify.success( t("settings.careTeam.remove.removedTitle"), t("settings.careTeam.remove.removedBody", { name: pendingRemove.name ?? pendingRemove.email ?? "", }), ); setPendingRemove(null); void load(); }; return ( {error && (

{error}

)} {canManage && (

{t("settings.careTeam.clickHint")}

)} {loading ? (

{t("settings.careTeam.loading")}

) : ( members.map((m) => { const isSelf = m.userId === session?.user?.id; // Prefer the login username; fall back to email for owners who // signed up by email. const secondary = m.username ? `@${m.username}` : m.email; const body = ( <> {initials(m.name, m.email)}

{m.name || m.email || m.userId} {isSelf && ( {t("settings.careTeam.you")} )}

{secondary && (

{secondary}

)}
{specialtyLabel(t, m.specialty) && ( {specialtyLabel(t, m.specialty)} )} {roleLabel(m.role)} ); // Admins click a row to open the employee detail dialog (view // permissions, change role, remove). Non-managers see a static row. return canManage ? ( ) : (
{body}
); }) )}
{canManage && ( void load()} onOpenChange={setAdding} open={adding} /> )} {/* Click a member to view details, change role, or remove. */} void load()} onOpenChange={(o) => !o && setSelected(null)} onRemove={(m) => { setSelected(null); setPendingRemove(m); }} open={selected !== null} /> {/* Confirm before removing a member — destructive and not reversible. */} !o && setPendingRemove(null)} open={pendingRemove !== null} > {t("settings.careTeam.remove.title")} {t("settings.careTeam.remove.description", { name: pendingRemove?.name ?? pendingRemove?.email ?? t("settings.careTeam.remove.thisMember"), })} }> {t("settings.careTeam.remove.cancel")}
); }