Skip to main content
Glama
TaskPage.tsx4.58 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { Grid, Paper, Skeleton, Tabs, Title } from '@mantine/core'; import { formatCodeableConcept, getDisplayString, resolveId } from '@medplum/core'; import type { Patient, Task } from '@medplum/fhirtypes'; import { DefaultResourceTimeline, Document, PatientSummary, ResourceTable, useMedplum, useMedplumNavigate, } from '@medplum/react'; import { useEffect, useState } from 'react'; import type { JSX } from 'react'; import { useParams } from 'react-router'; import { TaskActions } from '../components/actions/TaskActions'; import { NotesPage } from './NotesPage'; export function TaskPage(): JSX.Element { const medplum = useMedplum(); const navigate = useMedplumNavigate(); const { id } = useParams() as { id: string }; const [task, setTask] = useState<Task | undefined>(undefined); const tabs = ['Details', 'Timeline', 'Notes']; const [patient, setPatient] = useState<Patient | undefined>(); const patientReference = task?.for; // Set the current tab to what is in the URL, otherwise default to 'Details' const tab = window.location.pathname.split('/').pop(); const currentTab = tab && tabs.map((t) => t.toLowerCase()).includes(tab) ? tab : tabs[0].toLowerCase(); useEffect(() => { // Fetch the task that is specified in the URL const fetchTask = async (): Promise<void> => { try { const taskData = await medplum.readResource('Task', id); setTask(taskData); } catch (error) { console.error(error); } }; fetchTask().catch((error) => console.error(error)); }, [medplum, id]); useEffect(() => { const fetchLinkedPatient = async (): Promise<void> => { if (patientReference) { const patientId = resolveId(patientReference); try { const patientData = patientId ? await medplum.readResource('Patient', patientId) : undefined; setPatient(patientData); } catch (error) { console.error(error); } } }; fetchLinkedPatient().catch((err) => console.error(err)); }, [medplum, patientReference]); // Update the current tab and navigate to its URL const handleTabChange = (newTab: string | null): void => { navigate(`/Task/${id}/${newTab ?? ''}`); }; const onTaskChange = (updatedTask: Task): void => { setTask(updatedTask); }; if (!task) { return <Document>No Task found</Document>; } return ( <Grid gutter="xs"> <Grid.Col span={4}> <PatientProfile patient={patient} /> </Grid.Col> <Grid.Col span={5}> <TaskDetails task={task} tabs={tabs} currentTab={currentTab} handleTabChange={handleTabChange} /> </Grid.Col> <Grid.Col span={3}> <Actions task={task} onTaskChange={onTaskChange} /> </Grid.Col> </Grid> ); } interface PatientProfileProps { readonly patient?: Patient; } function PatientProfile({ patient }: PatientProfileProps): JSX.Element { return <>{patient ? <PatientSummary patient={patient} /> : <Skeleton visible={true} height={100} />}</>; } interface TaskDetailsProps { readonly task: Task; readonly tabs: string[]; readonly currentTab: string; readonly handleTabChange: (newTab: string | null) => void; } function TaskDetails({ task, tabs, currentTab, handleTabChange }: TaskDetailsProps): JSX.Element { return ( <Paper p="md" key={task ? task.id : 'loading'}> <Title>{task.code ? formatCodeableConcept(task.code) : getDisplayString(task)}</Title> <Tabs value={currentTab.toLowerCase()} onChange={handleTabChange}> <Tabs.List style={{ whiteSpace: 'nowrap', flexWrap: 'nowrap' }}> {tabs.map((tab) => ( <Tabs.Tab key={tab} value={tab.toLowerCase()}> {tab} </Tabs.Tab> ))} </Tabs.List> <Tabs.Panel value="details"> <ResourceTable key={`Task/${task.id}`} value={task} ignoreMissingValues={true} /> </Tabs.Panel> <Tabs.Panel value="timeline"> <DefaultResourceTimeline resource={task} /> </Tabs.Panel> <Tabs.Panel value="notes"> <NotesPage task={task} /> </Tabs.Panel> </Tabs> </Paper> ); } interface ActionsProps { readonly task: Task; readonly onTaskChange: (updatedTask: Task) => void; } function Actions({ task, onTaskChange }: ActionsProps): JSX.Element { return ( <Paper p="md"> <TaskActions task={task} onChange={onTaskChange} /> </Paper> ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/medplum/medplum'

If you have feedback or need assistance with the MCP directory API, please join our Discord server