diff --git a/src/cards/Card.ts b/src/cards/Card.ts index c79b9103..f269ae3d 100644 --- a/src/cards/Card.ts +++ b/src/cards/Card.ts @@ -5,12 +5,12 @@ interface Source { url: URL; icon?: URL; } -interface Action { +export interface Action { type: string; description: string; resource?: Resource | string; } -interface Suggestion { +export interface Suggestion { label: string; uuid?: string; actions: Action[]; diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index ff7588f6..2bea88c7 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -1,5 +1,13 @@ -import { MedicationRequest, Coding, FhirResource, Identifier } from 'fhir/r4'; -import Card, { Link } from '../cards/Card'; +import { + MedicationRequest, + Coding, + FhirResource, + Identifier, + Task, + Questionnaire, + Patient +} from 'fhir/r4'; +import Card, { Link, Suggestion, Action } from '../cards/Card'; import { HookPrefetch, OrderSignPrefetch, @@ -17,6 +25,16 @@ type HandleCallback = ( contextRequest: FhirResource | undefined, patient: FhirResource | undefined ) => Promise; + +interface Requirement { + name: string; + description: string; + stakeholderType: string; + createNewCase: boolean; + resourceId: string; + requiredToDispense: boolean; + appContext?: string; +} export interface CardRule { links: Link[]; summary?: string; @@ -364,6 +382,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } @@ -372,6 +393,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } else { @@ -380,6 +404,9 @@ export async function handleCardOrder( card.addLink( createSmartLink(requirement.name, requirement.appContext, contextRequest) ); + if (patient && patient.resourceType === 'Patient') { + createQuestionnaireSuggestion(card, requirement, patient); + } smartLinkCount++; } } @@ -421,14 +448,14 @@ export async function handleCard( // verify ids if ( patient?.id && - patient.id.replace('Patient/', '') !== context.patientId.replace('Patient/', '') + patient.id.replace('Patient/', '') !== context.patientId?.replace('Patient/', '') ) { res.json(buildErrorCard('Context patientId does not match prefetch Patient ID')); return; } if ( practitioner?.id && - practitioner.id.replace('Practitioner/', '') !== context.userId.replace('Practitioner/', '') + practitioner.id.replace('Practitioner/', '') !== context.userId?.replace('Practitioner/', '') ) { res.json(buildErrorCard('Context userId does not match prefetch Practitioner ID')); return; @@ -463,3 +490,67 @@ export function handleHook( res.json(buildErrorCard('Unknown Error')); } } + +export function createQuestionnaireSuggestion( + card: Card, + requirement: Requirement, + patient: Patient +) { + if (requirement.appContext && requirement.appContext.includes('=')) { + const qArr = requirement.appContext.split('='); // break up into parts + let qUrl = null; + for (let i = 0; i < qArr.length; i++) { + if (qArr[i].toLowerCase() === 'questionnaire') { + if (i + 1 < qArr.length) { + // not at end of array + qUrl = qArr[i + 1]; + } + } + } + if (qUrl) { + const action: Action = { + type: 'create', + description: `Create task for "completion of ${requirement.name} Questionnaire`, + resource: createQuestionnaireCompletionTask(requirement.name, qUrl, patient) + }; + const suggestion: Suggestion = { + label: `Add "Completion of ${requirement.name} Questionnaire" to task list`, + actions: [action] + }; + card.addSuggestion(suggestion); + } + } +} +export function createQuestionnaireCompletionTask( + questionnaireTitle: string, + questionnaireUrl: string, + patient: Patient +) { + const taskResource: Task = { + resourceType: 'Task', + status: 'ready', + intent: 'order', + code: { + coding: [ + { + system: 'http://hl7.org/fhir/uv/sdc/CodeSystem/temp', + code: 'complete-questionnaire' + } + ] + }, + description: `Complete ${questionnaireTitle} Questionnaire`, + for: { + reference: `${patient.resourceType}/${patient.id}` + }, + authoredOn: `${new Date(Date.now()).toISOString()}`, + input: [ + { + type: { + text: 'questionnaire' + }, + valueCanonical: `${questionnaireUrl}` + } + ] + }; + return taskResource; +}