Skip to content

Commit 562c332

Browse files
committed
Use custom PatientApps component to support extra launch URI params
1 parent 0e4191f commit 562c332

3 files changed

Lines changed: 159 additions & 5 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Encounter } from 'fhir/r4b';
2+
3+
import { useService } from 'aidbox-react/lib/hooks/service';
4+
import { success } from 'aidbox-react/lib/libs/remoteData';
5+
import { extractBundleResources, getFHIRResources as getAidboxResources, WithId } from 'aidbox-react/lib/services/fhir';
6+
import { mapSuccess, service } from 'aidbox-react/lib/services/service';
7+
8+
import { Client } from '@beda.software/aidbox-types';
9+
import { matchCurrentUserRole, Role } from '@beda.software/emr/dist/utils/role';
10+
import config from '@beda.software/emr-config';
11+
12+
export function useSmartApps(encounter?: Encounter) {
13+
const [appsRemoteData] = useService(async () => {
14+
let clientType = matchCurrentUserRole<string>({
15+
[Role.Patient]: () => 'smart-on-fhir-patient',
16+
[Role.Admin]: () => 'smart-on-fhir',
17+
[Role.Practitioner]: () => 'smart-on-fhir-practitioner',
18+
[Role.Receptionist]: () => 'smart-on-fhir-practitioner',
19+
});
20+
if (encounter) {
21+
if (clientType === 'smart-on-fhir-practitioner') {
22+
clientType = 'smart-on-fhir-encounter';
23+
} else {
24+
const mockResonse: Array<WithId<Client>> = [];
25+
return success(mockResonse);
26+
}
27+
}
28+
return mapSuccess(
29+
await getAidboxResources<Client>('Client', { ['.type']: clientType }),
30+
(b) => extractBundleResources(b).Client,
31+
);
32+
});
33+
return { appsRemoteData };
34+
}
35+
36+
export interface LaunchProps {
37+
user: string;
38+
client: string;
39+
patient: string;
40+
practitioner?: string;
41+
encounter?: string;
42+
}
43+
44+
interface LaunchRPCResult {
45+
result: {
46+
uri: string;
47+
};
48+
}
49+
50+
export async function getLaunchURI({ user, client, patient, practitioner, encounter }: LaunchProps) {
51+
return await service<LaunchRPCResult>({
52+
url: '/rpc',
53+
method: 'POST',
54+
data: {
55+
method: 'aidbox.smart/get-launch-uri',
56+
params: {
57+
user,
58+
iss: encodeURIComponent(`${config.baseURL}/fhir`),
59+
client,
60+
ctx: {
61+
patient,
62+
...(practitioner ? { practitioner } : {}),
63+
...(encounter ? { encounter } : {}),
64+
},
65+
},
66+
},
67+
});
68+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { Button, Card, Typography } from 'antd';
2+
import { Encounter, Patient } from 'fhir/r4b';
3+
4+
import { RenderRemoteData } from 'aidbox-react/lib/components/RenderRemoteData';
5+
6+
import { Client } from '@beda.software/aidbox-types';
7+
import { selectCurrentUserRoleResource } from '@beda.software/emr/dist/utils/role';
8+
import { mapSuccess } from '@beda.software/remote-data';
9+
10+
import { getLaunchURI, LaunchProps, useSmartApps } from './hooks';
11+
12+
const { Text } = Typography;
13+
14+
interface PatientAppsProps {
15+
patient: Patient;
16+
encounter?: Encounter;
17+
}
18+
interface SmartAppProps {
19+
patient: Patient;
20+
app: Client;
21+
encounter?: Encounter;
22+
}
23+
24+
export function useLaunchApp({ app, patient, encounter }: SmartAppProps) {
25+
const currentUser = selectCurrentUserRoleResource();
26+
const launchApp = async () => {
27+
const launchParams: LaunchProps = {
28+
client: app.id!,
29+
user: currentUser.id,
30+
patient: patient.id!,
31+
encounter: encounter?.id,
32+
};
33+
if (currentUser.resourceType === 'Practitioner') {
34+
launchParams.practitioner = currentUser.id;
35+
}
36+
mapSuccess(await getLaunchURI(launchParams), (launchURI) => {
37+
switch (app.id) {
38+
case 'aus-cvd-risk-i':
39+
window.location.href = launchURI.result.uri + '&ctoken=2025';
40+
break;
41+
default:
42+
window.location.href = launchURI.result.uri;
43+
break;
44+
}
45+
});
46+
};
47+
return launchApp;
48+
}
49+
50+
function SmartApp(props: SmartAppProps) {
51+
const launchApp = useLaunchApp(props);
52+
return (
53+
<Card
54+
title={props.app.smart?.name ?? 'UNKNOWN'}
55+
style={{ width: 300 }}
56+
extra={
57+
<Button type="primary" onClick={launchApp}>
58+
Launch
59+
</Button>
60+
}
61+
>
62+
<Text>{props.app.smart?.description}</Text>
63+
</Card>
64+
);
65+
}
66+
67+
export function PatientApps({ patient, encounter }: PatientAppsProps) {
68+
const { appsRemoteData } = useSmartApps(encounter);
69+
return (
70+
<RenderRemoteData remoteData={appsRemoteData}>
71+
{(data) => {
72+
const apps = data ?? [];
73+
if (apps.length == 0) {
74+
return <Text>There are no registered smart apps</Text>;
75+
} else {
76+
return (
77+
<>
78+
{apps.map((app) => (
79+
<SmartApp key={app.id} app={app} patient={patient} encounter={encounter} />
80+
))}
81+
</>
82+
);
83+
}
84+
}}
85+
</RenderRemoteData>
86+
);
87+
}

src/containers/PatientDetails/index.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
import { Patient } from 'fhir/r4b';
22

33
import { PatientDashboardProvider } from '@beda.software/emr/dist/components/Dashboard/contexts';
4-
import { PatientApps } from '@beda.software/emr/dist/containers/PatientDetails/PatientApps/index';
54
import { PatientOverview } from '@beda.software/emr/dist/containers/PatientDetails/PatientOverviewDynamic/index';
65
import { DetailPage, Tab } from '@beda.software/emr/dist/uberComponents/DetailPage/index';
76
import { compileAsFirst } from '@beda.software/emr/dist/utils/index';
87
import config from '@beda.software/emr-config';
98

109
import { dashboard } from './dashboard';
1110
import { PatientEncounter } from './encounters';
11+
import { PatientApps } from './PatientApps/index';
1212
import { PatientServiceRequest } from './requests';
1313
import { ResourcesTabRoutes } from './ResourcesTabRoutes';
1414

15-
1615
const getName = compileAsFirst<Patient, string>("Patient.name.given.first() + ' ' + Patient.name.family");
1716

1817
const tabs: Array<Tab<Patient>> = [
@@ -33,20 +32,20 @@ const tabs: Array<Tab<Patient>> = [
3332
},
3433
];
3534

36-
if(config.baseURL === 'https://erequesting.aidbox.beda.software'){
35+
if (config.baseURL === 'https://erequesting.aidbox.beda.software') {
3736
tabs.push({
3837
path: 'service',
3938
label: 'Service requests',
4039
component: ({ resource }) => <PatientServiceRequest patient={resource} />,
41-
})
40+
});
4241
}
4342

4443
if (config.baseURL === 'https://smartonfhir.aidbox.beda.software') {
4544
tabs.push({
4645
path: 'smart',
4746
label: 'Smart Apps',
4847
component: ({ resource }) => <PatientApps patient={resource} />,
49-
})
48+
});
5049
}
5150

5251
export function PatientDetails() {

0 commit comments

Comments
 (0)