import { useCallback, useEffect, useState } from 'react'; import { useCollaborationTeamServiceContext } from '../../services/CollaborationTeamService.tsx'; import { usePatientServiceContext } from '../../services/PatientService.tsx'; import { useMyProxies } from '../../hooks/useMyProxies.tsx'; import { useActAs } from '../../hooks/useActAs'; import { useFirstSignInGateStatus } from '../FirstSignInGate/firstSignInGateStatus.tsx'; import { splitTeamsByOwner, type OtherTeam } from '../../utils/collaborationTeamSides'; import { relayServerFailure } from '../../utils/fetchFailureMessage'; import './CollaborationTeamInvitationNotice.css'; // Somebody has invited you onto their collaboration team: said at the top of every screen, answered here. // Addressed to your own account, so it waits while you act as somebody else, and nothing loads behind the agreements gate. const CollaborationTeamInvitationNotice = () => { const { listTeams, memberAction } = useCollaborationTeamServiceContext(); const { patientState } = usePatientServiceContext(); const { proxies } = useMyProxies(); const { actingAs } = useActAs(); const gateClear = useFirstSignInGateStatus() === 'clear'; const [invitations, setInvitations] = useState([]); const [busyFor, setBusyFor] = useState(null); const [error, setError] = useState(null); const [outcome, setOutcome] = useState(null); // Only somebody with a link to another person can be on their team, so nobody else pays for the read. const canBeInvited = proxies.length > 0; useEffect(() => { if (actingAs || !gateClear || !patientState || !canBeInvited) return; let cancelled = false; (async () => { try { const teams = await listTeams(); if (!cancelled) setInvitations(splitTeamsByOwner(teams, patientState.id, proxies).invitations); } catch (err) { // The teams page reports a failed read; this notice has nothing true to add. console.error('Failed to check collaboration team invitations:', err); } })(); return () => { cancelled = true; }; }, [actingAs, gateClear, patientState, canBeInvited, listTeams, proxies]); const answer = useCallback(async (invitation: OtherTeam, decision: 'accept' | 'decline') => { const { team, mine, ownerName } = invitation; setBusyFor(team.teamId); setError(null); try { await memberAction(team.teamId, mine.memberRef, decision); // Removed at once, so an answered row never sits on screen with live buttons. setInvitations((current) => current.filter((item) => item.team.teamId !== team.teamId)); setOutcome(decision === 'accept' ? `You joined ${team.name}. It is under Other teams in Collaboration teams.` : `${ownerName} has been told you declined. Nothing was added to your account.`); } catch (err) { setError(relayServerFailure(err, 'That could not be completed.')); } finally { setBusyFor(null); } }, [memberAction]); if (actingAs || !gateClear) return null; if (invitations.length === 0 && !outcome) return null; return (
{invitations.map(({ team, mine, ownerName }) => (

{ownerName} invited you to their {team.name} team

You would be able to see and join that conversation, and they can remove you at any time.

))} {error &&

{error}

} {outcome &&

{outcome}

}
); }; export default CollaborationTeamInvitationNotice;