import { useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; import { CareTeam } from "fhir/r4"; import { FhirCareTeamDisplay } from "../../../../components"; import { useFhirCareTeamBroadcast, useFhirCareTeams, useFhirCareTeamTargetedBroadcast, } from "../../../../hooks"; import { useAuthServiceContext, usePatientServiceContext } from "../../../../services"; import { useViewerIsPatient } from "../../../../hooks"; import { useCareTeamReadScope } from "../../../../hooks/useCareTeamReadScope"; import { Calendar, ChevronRight, Edit, FileText, Plus } from "lucide-react"; import { formatDateForDisplay } from "../../../../lib/utils.ts"; import { Sheet, SheetContent } from "../../../../components/ui/sheet.tsx"; import { Button } from "../../../../components/ui/button.tsx"; import { Skeleton } from "../../../../components/ui/skeleton.tsx"; import { isOutsideProvidersTeam } from "../../../../utils/outsideProviders.ts"; const CareTeams = () => { const navigate = useNavigate(); const { userRole, USER_ROLES } = useAuthServiceContext(); const viewerIsPatient = useViewerIsPatient(); const { loading: teamsLoading, error, answered, careTeamsList } = useFhirCareTeams(); // A read that has not answered is still loading, never an empty list. const loading = teamsLoading || !answered; const visibleCareTeams = careTeamsList.filter( (careTeam: CareTeam) => !isOutsideProvidersTeam(careTeam), ); // An open team belongs to the viewer, practice and patient it was opened for, and to that one opening: a // change of any retires it at once, and returning to the same practice or patient does not bring it back. const { patientState } = usePatientServiceContext(); const scope = useCareTeamReadScope(patientState?.id); const openings = useRef(0); const [opened, setOpened] = useState<{ id: number; scope: string; team: CareTeam } | null>(null); const [openedScope, setOpenedScope] = useState(scope); if (openedScope !== scope) { setOpenedScope(scope); setOpened(null); } const current = opened && opened.scope === scope ? opened : null; const selectedCareTeam = current?.team ?? null; const showDisplayModal = current !== null; const openingId = current?.id; const setShowDisplayModal = (open: boolean) => { if (!open) setOpened(null); }; useFhirCareTeamBroadcast(); useFhirCareTeamTargetedBroadcast({ careTeam: selectedCareTeam || undefined, isOpen: showDisplayModal, onUpdate: (updatedCareTeam) => { setOpened((prev) => (prev && prev.id === openingId ? { ...prev, team: updatedCareTeam } : prev)); }, onDelete: () => { setOpened((prev) => (prev && prev.id === openingId ? null : prev)); }, }); const viewCareTeam = (careTeam: CareTeam) => { setOpened({ id: ++openings.current, scope, team: careTeam }); }; const editCareTeam = (event: React.MouseEvent, careTeam: CareTeam) => { event.stopPropagation(); navigate(careTeam.id as string, { relative: "path" }); }; const addCareTeam = () => { navigate("new", { relative: "path" }); }; const isAuthorizedToEdit = () => { return userRole && [USER_ROLES.PRACTITIONER].includes(userRole as string); }; /** * WHO IS READING THIS SCREEN, because it is reachable by BOTH and the copy assumed one of them. * * Found in the practitioner walk, 2026-08-22: a clinician opening a patient's chart at * Care Provision Care Teams was told *"You don't have Care team yet. Your care team will add them * here when they are created."* **Patient copy on a staff surface** - it addresses the clinician as * the patient, and then tells them to wait for themselves. * * The component ALREADY knew: `isAuthorizedToEdit` reads the same role a line above, to decide * whether to show **Add**. The reader was identified and the sentences did not use it. * * A patient never has `USER_ROLES.PRACTITIONER`, so this defaults to the patient voice - the * original behaviour for the original reader. */ /* * Was `userRole === PRACTITIONER`, which is the wrong half to enumerate. A receptionist, an admin or a * platform manager reading this chart is just as much "not the patient", and every one of them got the * patient voice - told to wait for a care team they are part of. Listing the staff roles means each new * staff role silently defaults to the wrong sentence, which is how this spread to the sibling screens. * * The patient side is a closed pair, so asking that question instead cannot rot as roles are added. */ const staffIsViewing = !viewerIsPatient; const getParticipantCount = (careTeam: CareTeam): number => { return careTeam.participant?.length || 0; }; return (

Care Team

{/* ๐Ÿ”ป The patient line also said "your care team shared by your care team" โ€” the same noun twice, which was already wrong before anyone asked who was reading it. */} {staffIsViewing ? "The practitioners and organizations caring for this patient." : "The practitioners and organizations caring for you."}

{isAuthorizedToEdit() && ( )}
{error ? (
{" "}

Could not load the clinical care team

Try again later.

) : !loading && visibleCareTeams.length === 0 ? (

{staffIsViewing ? "No clinical care team recorded" : "No clinical care team yet"}

{/* โ›” The staff line must not tell a clinician to wait for somebody else โ€” THEY are the care team, and the Add button is right there. */} {staffIsViewing ? "No care team is recorded for this patient. Add a team to record who is involved in their care." : "Your practice will add the people involved in your care here."}

) : loading ? (
{[...Array(4)].map((_, index) => (
))}
) : ( visibleCareTeams.length !== 0 && (
{visibleCareTeams.map((careTeam: CareTeam) => { const participantCount = getParticipantCount(careTeam); // - the row IS the control, so it must be reachable without a pointer. // Enter and Space both, because role="button" promises both. return (
viewCareTeam(careTeam)} onKeyDown={(event: React.KeyboardEvent) => { if (event.key !== 'Enter' && event.key !== ' ') return; event.preventDefault(); viewCareTeam(careTeam); }} >

{careTeam?.name || "Team name not available"}{" "} {careTeam.status ? careTeam.status : "Status unknown"}

{/* {category && Category: {category}} */}
{careTeam?.meta?.lastUpdated && ( {" "} {formatDateForDisplay(careTeam.meta.lastUpdated)} )}{" "} ยท {careTeam?.resourceType}
{participantCount > 0 && (
Participant - {participantCount} {participantCount !== 1 ? "s" : ""}
)}
{isAuthorizedToEdit() && (
)}
); })}
) )} {selectedCareTeam && ( { if (!open) setShowDisplayModal(false); }} > {selectedCareTeam && ( setShowDisplayModal(false)} /> )} )}
); }; export default CareTeams; // import { useNavigate } from 'react-router-dom'; // import { CareTeam } from 'fhir/r4'; // import { AppSpinner, FhirCareTeamDisplay, ScrollableTab } from '../../../../components'; // import { formatFhirCodeableConcept } from '../../../../utils/fhirCodeableConcept.tsx'; // import { useFhirCareTeamBroadcast, useFhirCareTeams, useFhirCareTeamTargetedBroadcast } from '../../../../hooks'; // import { useAuthServiceContext, useCareTeamServiceContext } from '../../../../services'; // const CareTeams = () => { // const navigate = useNavigate(); // const { userRole, USER_ROLES } = useAuthServiceContext(); // const { getCareTeamDisplay } = useCareTeamServiceContext(); // const { loading, error, clearError, careTeamsList } = useFhirCareTeams(); // const [isGuideOpen, setIsGuideOpen] = useState(false); // const [selectedCareTeam, setSelectedCareTeam] = useState(null); // const [showDisplayModal, setShowDisplayModal] = useState(false); // const spacerMargin = '24px'; // useFhirCareTeamBroadcast(); // useFhirCareTeamTargetedBroadcast({ // careTeam: selectedCareTeam || undefined, // isOpen: showDisplayModal, // onUpdate: (updatedCareTeam) => { // setSelectedCareTeam(updatedCareTeam); // }, // onDelete: () => { // setShowDisplayModal(false); // setSelectedCareTeam(null); // } // }); // const viewCareTeam = (careTeam: CareTeam) => { // setSelectedCareTeam(careTeam); // setShowDisplayModal(true); // }; // const editCareTeam = (event: React.MouseEvent, careTeam: CareTeam) => { // event.stopPropagation(); // navigate(careTeam.id as string, { relative: 'path' }); // }; // const addCareTeam = () => { // navigate('new', { relative: 'path' }); // }; // const isAuthorizedToEdit = () => { // return userRole && [USER_ROLES.PRACTITIONER].includes(userRole as string); // }; // const getStatusDisplay = (careTeam: CareTeam): { text: string, color?: string } => { // if (!careTeam) return { text: 'Unknown' }; // switch (careTeam.status) { // case 'active': // return { text: 'Active', color: '#00a32a' }; // case 'suspended': // return { text: 'Suspended', color: '#e39700' }; // case 'inactive': // return { text: 'Inactive', color: '#cc1818' }; // case 'entered-in-error': // return { text: 'Error', color: '#cc1818' }; // case 'proposed': // return { text: 'Proposed', color: '#757575' }; // default: // return { text: careTeam.status?.charAt(0).toUpperCase() + careTeam.status?.slice(1) || 'Unknown' }; // } // }; // const getParticipantCount = (careTeam: CareTeam): number => { // return careTeam.participant?.length || 0; // }; // const getCategoryDisplay = (careTeam: CareTeam): string => { // if (!careTeam.category || careTeam.category.length === 0) { // return ''; // } // return careTeam.category.map(cat => formatFhirCodeableConcept(cat)).join(', '); // }; // return ( // // setIsGuideOpen(false)} // resourceType="CareTeam"/> // // // // // // // {isAuthorizedToEdit() && ( // // // // )} // // // {error && ( // <> // // {error} // // // // )} // {!loading && careTeamsList.length === 0 && ( // <> // // No care teams found. // // // // )} // <> // {loading ? ( // // ): ( // // {careTeamsList.length !== 0 && ( // // {careTeamsList.map((careTeam: CareTeam) => { // const displayTitle = getCareTeamDisplay(careTeam); // const { text: statusText, color: statusColor } = getStatusDisplay(careTeam); // const participantCount = getParticipantCount(careTeam); // const category = getCategoryDisplay(careTeam); // return ( // viewCareTeam(careTeam)}> // // // // // // // // // {displayTitle} // // {participantCount > 0 && ( // // {participantCount} participant{participantCount !== 1 ? 's': ''} // // )} // {category && ( // // Category: {category} // // )} // // {isAuthorizedToEdit() && ( // // // // )} // // // // // ); // })} // // )} // // )} // // {selectedCareTeam && ( // { // setShowDisplayModal(false); // setSelectedCareTeam(null); // }} // /> // )} // // ); // }; // export default CareTeams;