From 54a99cd0abdc6bcce9b8674ba840e0d396b042f8 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 20 Jan 2023 16:02:09 -0800 Subject: [PATCH 01/18] PatientStore: Add activity properties to taskItems --- web_patient/src/stores/PatientStore.ts | 57 +++++++++++++++++++++----- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/web_patient/src/stores/PatientStore.ts b/web_patient/src/stores/PatientStore.ts index 42cdd2d2..a9f37752 100644 --- a/web_patient/src/stores/PatientStore.ts +++ b/web_patient/src/stores/PatientStore.ts @@ -51,6 +51,7 @@ export interface IPatientStore { readonly loadValuesInventoryState: IPromiseQueryState; // Helpers + addActivityPropertiesToTaskItems: (taskItems: IScheduledActivity[]) => IScheduledActivity[]; getActivityById: (activityId: string) => IActivity | undefined; getActivitiesByLifeAreaId: (lifeAreaId: string) => IActivity[]; getActivitiesByValueId: (valueId: string) => IActivity[]; @@ -72,6 +73,7 @@ export interface IPatientStore { updateActivity: (activity: IActivity) => Promise; // Activity logs + completeScheduledActivity: (activityLog: IActivityLog) => Promise; loadActivityLogs: () => Promise; @@ -281,6 +283,20 @@ export class PatientStore implements IPatientStore { } // Helpers + @action.bound + public addActivityPropertiesToTaskItems(taskItems: IScheduledActivity[]) { + return taskItems.map((obj) => { + const activity = this.getActivityById( + this.activitySchedules.find((a) => a.activityScheduleId == obj.activityScheduleId) + ?.activityId as string, + ); + obj.activityId = activity?.activityId as string; + obj.activityName = activity?.name as string; + + return obj; + }); + } + @action.bound public getActivityById(activityId: string) { return this.activities.find((a) => a.activityId == activityId); @@ -329,7 +345,7 @@ export class PatientStore implements IPatientStore { public getActivitySchedulesByActivityId(activityId: string): IActivitySchedule[] { return this.activitySchedules.filter((as) => { return as.activityId == activityId; - }) + }); } @action.bound @@ -417,8 +433,14 @@ export class PatientStore implements IPatientStore { onArrayConflict('activity', 'activityId', () => this.activities, logger), ); - await this.loadAndLogQuery(this.patientService.getActivitySchedules, this.loadActivitySchedulesQuery); - await this.loadAndLogQuery(this.patientService.getScheduledActivities, this.loadScheduledActivitiesQuery); + await this.loadAndLogQuery( + this.patientService.getActivitySchedules, + this.loadActivitySchedulesQuery, + ); + await this.loadAndLogQuery( + this.patientService.getScheduledActivities, + this.loadScheduledActivitiesQuery, + ); } } @@ -500,15 +522,19 @@ export class PatientStore implements IPatientStore { @action.bound public async deleteActivitySchedule(activitySchedule: IActivitySchedule) { const prevActivitySchedules = this.activitySchedules.slice() || []; - const foundIdx = prevActivitySchedules.findIndex((as) => as.activityScheduleId == activitySchedule.activityScheduleId); + const foundIdx = prevActivitySchedules.findIndex( + (as) => as.activityScheduleId == activitySchedule.activityScheduleId, + ); console.assert(foundIdx >= 0, `ActivitySchedule to delete not found: ${activitySchedule.activityScheduleId}`); if (foundIdx >= 0) { - const promise = this.patientService.deleteActivitySchedule(activitySchedule).then((_deletedActivitySchedule) => { - prevActivitySchedules.splice(foundIdx, 1); - return prevActivitySchedules; - }); + const promise = this.patientService + .deleteActivitySchedule(activitySchedule) + .then((_deletedActivitySchedule) => { + prevActivitySchedules.splice(foundIdx, 1); + return prevActivitySchedules; + }); await this.loadAndLogQuery( () => promise, @@ -516,7 +542,10 @@ export class PatientStore implements IPatientStore { onArrayConflict('activitySchedule', 'activityScheduleId', () => this.activitySchedules, logger), ); - await this.loadAndLogQuery(this.patientService.getScheduledActivities, this.loadScheduledActivitiesQuery); + await this.loadAndLogQuery( + this.patientService.getScheduledActivities, + this.loadScheduledActivitiesQuery, + ); } } @@ -670,8 +699,14 @@ export class PatientStore implements IPatientStore { ); await this.loadAndLogQuery(this.patientService.getActivities, this.loadActivitiesQuery); - await this.loadAndLogQuery(this.patientService.getActivitySchedules, this.loadActivitySchedulesQuery); - await this.loadAndLogQuery(this.patientService.getScheduledActivities, this.loadScheduledActivitiesQuery); + await this.loadAndLogQuery( + this.patientService.getActivitySchedules, + this.loadActivitySchedulesQuery, + ); + await this.loadAndLogQuery( + this.patientService.getScheduledActivities, + this.loadScheduledActivitiesQuery, + ); } } From f50624b8c59573f9ea009b13bad9beb14462158a Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 20 Jan 2023 16:02:45 -0800 Subject: [PATCH 02/18] types: Update IScheduledActivity --- web_shared/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_shared/types.ts b/web_shared/types.ts index 43793a15..b0020ae7 100644 --- a/web_shared/types.ts +++ b/web_shared/types.ts @@ -131,7 +131,9 @@ export interface IScheduledItem { export interface IScheduledActivity extends IScheduledItem { scheduledActivityId: string; + activityScheduleId: string; + // NOTE: Check w/ James if these can go away. activityId: string; activityName: string; reminder: Date; From a84c7fa7d2ddc24adb549a070e3c91f12c6d0ba5 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 20 Jan 2023 16:03:28 -0800 Subject: [PATCH 03/18] CarePlanPage: Update selectTaskItems with activity properties --- web_patient/src/components/CarePlan/CarePlanPage.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web_patient/src/components/CarePlan/CarePlanPage.tsx b/web_patient/src/components/CarePlan/CarePlanPage.tsx index 6255a534..f3a6f97e 100644 --- a/web_patient/src/components/CarePlan/CarePlanPage.tsx +++ b/web_patient/src/components/CarePlan/CarePlanPage.tsx @@ -87,7 +87,9 @@ export const CarePlanPage: FunctionComponent = observer(() => { selectedActivitySchedule: undefined, })); - const selectedTaskItems = taskItems.filter((t) => isSameDay(t.dueDateTime, viewState.selectedDate)); + const selectedTaskItems = patientStore.addActivityPropertiesToTaskItems( + taskItems.filter((t) => isSameDay(t.dueDateTime, viewState.selectedDate)), + ); const handleDayClick = action((date: Date) => { viewState.selectedDate = date; From 5537214bc2dbba953817d17cbb03eb2bfb36a7fb Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Sun, 22 Jan 2023 17:04:20 -0800 Subject: [PATCH 04/18] HomePage: Update todayItems with activity properties --- web_patient/src/components/Home/HomePage.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/web_patient/src/components/Home/HomePage.tsx b/web_patient/src/components/Home/HomePage.tsx index e429c045..f6bdac6e 100644 --- a/web_patient/src/components/Home/HomePage.tsx +++ b/web_patient/src/components/Home/HomePage.tsx @@ -27,6 +27,9 @@ const CompactList = withTheme( export const HomePage: FunctionComponent = observer(() => { const rootStore = useStores(); + const { patientStore } = rootStore; + const todayItems = patientStore.addActivityPropertiesToTaskItems(patientStore.todayItems); + console.log(todayItems); const navigate = useNavigate(); const onTaskClick = action((item: IScheduledActivity) => () => { @@ -133,12 +136,12 @@ export const HomePage: FunctionComponent = observer(() => {
- {!!rootStore.patientStore.todayItems && rootStore.patientStore.todayItems.length > 0 ? ( + {!!todayItems && todayItems.length > 0 ? ( - {rootStore.patientStore.todayItems.map((item, idx) => ( + {todayItems.map((item, idx) => ( - {idx < rootStore.patientStore.todayItems.length - 1 && } + {idx < todayItems.length - 1 && } ))} From 18cd285d11853a044923d4cc2faecf279150d4ed Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Sun, 22 Jan 2023 17:12:49 -0800 Subject: [PATCH 05/18] Schema activity-log: Add activityId to fix http 400 errors --- .../scope/schemas/documents/activity-log.json | 181 +++++++++--------- 1 file changed, 92 insertions(+), 89 deletions(-) diff --git a/scope_shared/scope/schemas/documents/activity-log.json b/scope_shared/scope/schemas/documents/activity-log.json index cdfda49b..652365c9 100644 --- a/scope_shared/scope/schemas/documents/activity-log.json +++ b/scope_shared/scope/schemas/documents/activity-log.json @@ -1,91 +1,94 @@ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://uwscope.org/schemas/documents/activity-log", - "title": "IActivityLog", - "description": "IActivityLog Type", - "type": "object", - "properties": { - "_id": { - "type": "string" - }, - "_type": { - "const": "activityLog" - }, - "_set_id": { - "type": "string" - }, - "_rev": { - "type": "number" - }, - "activityLogId": { - "type": "string" - }, - "scheduledActivityId": { - "type": "string" - }, - "activityName": { - "type": "string" - }, - "recordedDateTime": { - "$ref": "/schemas/documents/utils/log#/properties/recordedDateTime" - }, - "comment": { - "$ref": "/schemas/documents/utils/log#/properties/comment" - }, - "completed": { - "type": "boolean" - }, - "success": { - "$ref": "/schemas/utils/enums#/properties/activitySuccessType" - }, - "alternative": { - "type": "string" - }, - "pleasure": { - "type": "number" - }, - "accomplishment": { - "type": "number" - } - }, - "additionalProperties": false, - "required": ["_type", "scheduledActivityId", "activityName", "recordedDateTime"], - "allOf": [ - { - "$ref": "#/$defs/no-success-disallows-accomplishment" - }, - { - "$ref": "#/$defs/no-success-disallows-pleasure" - } - ], - "$defs": { - "no-success-disallows-accomplishment": { - "anyOf": [ - { - "not": { "$ref": "#/$defs/no-success" } - }, - { - "not": { "required": ["accomplishment"] } - } - ] - }, - "no-success-disallows-pleasure": { - "anyOf": [ - { - "not": { "$ref": "#/$defs/no-success" } - }, - { - "not": { "required": ["pleasure"] } - } - ] - }, - "no-success": { - "properties": { - "success": { - "const": "No" - } - }, - "required": ["success"] - } - } + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://uwscope.org/schemas/documents/activity-log", + "title": "IActivityLog", + "description": "IActivityLog Type", + "type": "object", + "properties": { + "_id": { + "type": "string" + }, + "_type": { + "const": "activityLog" + }, + "_set_id": { + "type": "string" + }, + "_rev": { + "type": "number" + }, + "activityLogId": { + "type": "string" + }, + "scheduledActivityId": { + "type": "string" + }, + "activityId": { + "type": "string" + }, + "activityName": { + "type": "string" + }, + "recordedDateTime": { + "$ref": "/schemas/documents/utils/log#/properties/recordedDateTime" + }, + "comment": { + "$ref": "/schemas/documents/utils/log#/properties/comment" + }, + "completed": { + "type": "boolean" + }, + "success": { + "$ref": "/schemas/utils/enums#/properties/activitySuccessType" + }, + "alternative": { + "type": "string" + }, + "pleasure": { + "type": "number" + }, + "accomplishment": { + "type": "number" + } + }, + "additionalProperties": false, + "required": ["_type", "scheduledActivityId", "activityId", "activityName", "recordedDateTime"], + "allOf": [ + { + "$ref": "#/$defs/no-success-disallows-accomplishment" + }, + { + "$ref": "#/$defs/no-success-disallows-pleasure" + } + ], + "$defs": { + "no-success-disallows-accomplishment": { + "anyOf": [ + { + "not": { "$ref": "#/$defs/no-success" } + }, + { + "not": { "required": ["accomplishment"] } + } + ] + }, + "no-success-disallows-pleasure": { + "anyOf": [ + { + "not": { "$ref": "#/$defs/no-success" } + }, + { + "not": { "required": ["pleasure"] } + } + ] + }, + "no-success": { + "properties": { + "success": { + "const": "No" + } + }, + "required": ["success"] + } + } } From a2b745efe9814665f9f418a70b306f3854645748 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Tue, 24 Jan 2023 11:09:56 -0800 Subject: [PATCH 06/18] Schema activity-log: Added entire activity.json as property --- .../scope/schemas/documents/activity-log.json | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/scope_shared/scope/schemas/documents/activity-log.json b/scope_shared/scope/schemas/documents/activity-log.json index 652365c9..b38b2e8b 100644 --- a/scope_shared/scope/schemas/documents/activity-log.json +++ b/scope_shared/scope/schemas/documents/activity-log.json @@ -3,6 +3,19 @@ "$id": "https://uwscope.org/schemas/documents/activity-log", "title": "IActivityLog", "description": "IActivityLog Type", + "$comment": [ + "---------------------------------------", + "Added Entire Activity Json", + "---------------------------------------", + { + "activityId": { + "type": "string" + }, + "activityName": { + "type": "string" + } + } + ], "type": "object", "properties": { "_id": { @@ -23,11 +36,8 @@ "scheduledActivityId": { "type": "string" }, - "activityId": { - "type": "string" - }, - "activityName": { - "type": "string" + "activity": { + "$ref": "/schemas/documents/activity" }, "recordedDateTime": { "$ref": "/schemas/documents/utils/log#/properties/recordedDateTime" @@ -52,7 +62,7 @@ } }, "additionalProperties": false, - "required": ["_type", "scheduledActivityId", "activityId", "activityName", "recordedDateTime"], + "required": ["_type", "scheduledActivityId", "activity", "recordedDateTime"], "allOf": [ { "$ref": "#/$defs/no-success-disallows-accomplishment" From f820240a2937c443f9bd6d1719840509c60a9277 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Tue, 24 Jan 2023 11:18:59 -0800 Subject: [PATCH 07/18] CarePlanPage,HomePage,ScheduledListItem: Fetch activity using activityScheduleId instead of mutating scheduled items --- .../src/components/CarePlan/CarePlanPage.tsx | 7 +++---- web_patient/src/components/Home/HomePage.tsx | 6 +++--- .../src/components/common/ScheduledListItem.tsx | 7 ++++++- web_patient/src/stores/PatientStore.ts | 17 +++++------------ 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/web_patient/src/components/CarePlan/CarePlanPage.tsx b/web_patient/src/components/CarePlan/CarePlanPage.tsx index f3a6f97e..57aee22e 100644 --- a/web_patient/src/components/CarePlan/CarePlanPage.tsx +++ b/web_patient/src/components/CarePlan/CarePlanPage.tsx @@ -87,9 +87,7 @@ export const CarePlanPage: FunctionComponent = observer(() => { selectedActivitySchedule: undefined, })); - const selectedTaskItems = patientStore.addActivityPropertiesToTaskItems( - taskItems.filter((t) => isSameDay(t.dueDateTime, viewState.selectedDate)), - ); + const selectedTaskItems = taskItems.filter((t) => isSameDay(t.dueDateTime, viewState.selectedDate)); const handleDayClick = action((date: Date) => { viewState.selectedDate = date; @@ -100,9 +98,10 @@ export const CarePlanPage: FunctionComponent = observer(() => { }); const handleTaskClick = action((item: IScheduledActivity) => () => { + const activity = patientStore.getActivityByActivityScheduleId(item.activityScheduleId); navigate( getFormPath(ParameterValues.form.activityLog, { - [Parameters.activityId]: item.activityId, + [Parameters.activityId]: activity?.activityId as string, [Parameters.taskId]: item.scheduledActivityId, }), ); diff --git a/web_patient/src/components/Home/HomePage.tsx b/web_patient/src/components/Home/HomePage.tsx index f6bdac6e..46506f13 100644 --- a/web_patient/src/components/Home/HomePage.tsx +++ b/web_patient/src/components/Home/HomePage.tsx @@ -28,14 +28,14 @@ const CompactList = withTheme( export const HomePage: FunctionComponent = observer(() => { const rootStore = useStores(); const { patientStore } = rootStore; - const todayItems = patientStore.addActivityPropertiesToTaskItems(patientStore.todayItems); - console.log(todayItems); + const todayItems = patientStore.todayItems; const navigate = useNavigate(); const onTaskClick = action((item: IScheduledActivity) => () => { + const activity = patientStore.getActivityByActivityScheduleId(item.activityScheduleId); navigate( getFormPath(ParameterValues.form.activityLog, { - [Parameters.activityId]: item.activityId, + [Parameters.activityId]: activity?.activityId as string, [Parameters.taskId]: item.scheduledActivityId, }), ); diff --git a/web_patient/src/components/common/ScheduledListItem.tsx b/web_patient/src/components/common/ScheduledListItem.tsx index 3ae65b1f..17f152f5 100644 --- a/web_patient/src/components/common/ScheduledListItem.tsx +++ b/web_patient/src/components/common/ScheduledListItem.tsx @@ -4,6 +4,7 @@ import RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked'; import React, { FunctionComponent } from 'react'; import { IScheduledActivity } from 'shared/types'; import { getTaskItemDueTimeString } from 'src/utils/schedule'; +import { useStores } from 'src/stores/stores'; export interface IScheduledListItemProps { item: IScheduledActivity; @@ -12,6 +13,10 @@ export interface IScheduledListItemProps { export const ScheduledListItem: FunctionComponent = (props) => { const { item, onClick } = props; + const rootStore = useStores(); + const { patientStore } = rootStore; + + const activity = patientStore.getActivityByActivityScheduleId(item.activityScheduleId); return ( @@ -19,7 +24,7 @@ export const ScheduledListItem: FunctionComponent = (pr {item.completed ? : } {item.activityName}} + primary={{activity?.name}} secondary={getTaskItemDueTimeString(item, new Date())} /> diff --git a/web_patient/src/stores/PatientStore.ts b/web_patient/src/stores/PatientStore.ts index a9f37752..06688206 100644 --- a/web_patient/src/stores/PatientStore.ts +++ b/web_patient/src/stores/PatientStore.ts @@ -51,7 +51,7 @@ export interface IPatientStore { readonly loadValuesInventoryState: IPromiseQueryState; // Helpers - addActivityPropertiesToTaskItems: (taskItems: IScheduledActivity[]) => IScheduledActivity[]; + getActivityByActivityScheduleId: (activityScheduleId: string) => IActivity | undefined; getActivityById: (activityId: string) => IActivity | undefined; getActivitiesByLifeAreaId: (lifeAreaId: string) => IActivity[]; getActivitiesByValueId: (valueId: string) => IActivity[]; @@ -284,17 +284,10 @@ export class PatientStore implements IPatientStore { // Helpers @action.bound - public addActivityPropertiesToTaskItems(taskItems: IScheduledActivity[]) { - return taskItems.map((obj) => { - const activity = this.getActivityById( - this.activitySchedules.find((a) => a.activityScheduleId == obj.activityScheduleId) - ?.activityId as string, - ); - obj.activityId = activity?.activityId as string; - obj.activityName = activity?.name as string; - - return obj; - }); + public getActivityByActivityScheduleId(activityScheduleId: string) { + return this.getActivityById( + this.activitySchedules.find((a) => a.activityScheduleId == activityScheduleId)?.activityId as string, + ); } @action.bound From c8bdc95a4549c6f0d7a376b4da76745e46aa452e Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Tue, 24 Jan 2023 11:21:08 -0800 Subject: [PATCH 08/18] Add entire activity document to activity log --- .../components/Forms/ActivityLoggingForm.tsx | 14 +++++++------ .../Progress/ActivityTrackingHome.tsx | 21 ++++++++++++------- .../PatientDetail/ActivityProgress.tsx | 2 +- web_shared/types.ts | 10 +++++---- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/web_patient/src/components/Forms/ActivityLoggingForm.tsx b/web_patient/src/components/Forms/ActivityLoggingForm.tsx index 5531eb99..19e525c7 100644 --- a/web_patient/src/components/Forms/ActivityLoggingForm.tsx +++ b/web_patient/src/components/Forms/ActivityLoggingForm.tsx @@ -157,23 +157,25 @@ export const ActivityLoggingForm: FunctionComponent = return null; } - if (task.activityId != activityId) { - logError('ActivityForm', `Activity and task mismatch: activity=${activityId}, taskSource=${task.activityId}`); - return null; - } + // NOTE: activityId does not exist on IScheduledActivity anymore + // if (task.activityId != activityId) { + // logError('ActivityForm', `Activity and task mismatch: activity=${activityId}, taskSource=${task.activityId}`); + // return null; + // } const viewState = useLocalObservable<{ hasData: boolean }>(() => ({ hasData: false, })); const dataState = useLocalObservable(() => ({ - activityId, + //activityId, scheduledActivityId: task.scheduledActivityId, alternative: '', comment: '', pleasure: 5, accomplishment: 5, - activityName: activity.name, + //activityName: activity.name, + activity: activity, recordedDateTime: new Date(), success: '', })); diff --git a/web_patient/src/components/Progress/ActivityTrackingHome.tsx b/web_patient/src/components/Progress/ActivityTrackingHome.tsx index 821d3541..a7794003 100644 --- a/web_patient/src/components/Progress/ActivityTrackingHome.tsx +++ b/web_patient/src/components/Progress/ActivityTrackingHome.tsx @@ -64,14 +64,17 @@ export const ActivityTrackingHome: FunctionComponent = observer(() => { viewState.selectedLog = log; viewState.isOpen = true; // TODO Activity Refactor: Activity Tracking - // const activity = patientStore.getActivityById(log.activityId); - // viewState.selectedValue = activity?.value || getString('Activity_tracking_log_value_none'); - viewState.selectedValue = getString('Activity_tracking_log_value_none'); + const activity = patientStore.getActivityById(log.activity?.activityId as string); + viewState.selectedValue = + patientStore.getValueById(activity?.valueId as string)?.name || + getString('Activity_tracking_log_value_none'); + //viewState.selectedValue = getString('Activity_tracking_log_value_none'); - // TODO Activity Refactor: Activity Tracking // const lifearea = activity && rootStore.getLifeAreaContent(activity?.lifeareaId); - // viewState.selectedLifearea = lifearea?.name || getString('Activity_tracking_log_lifearea_none'); - viewState.selectedLifeArea = getString('Activity_tracking_log_lifearea_none'); + //viewState.selectedLifeArea = getString('Activity_tracking_log_lifearea_none'); + viewState.selectedLifeArea = + (rootStore.getLifeAreaContent(patientStore.getValueById(activity?.valueId as string)?.lifeAreaId as string) + ?.name as string) || getString('Activity_tracking_log_lifearea_none'); }); const handleClose = action(() => { @@ -103,7 +106,8 @@ export const ActivityTrackingHome: FunctionComponent = observer(() => { {`${format(log.recordedDateTime, 'MM/dd')}`} - {log.activityName} + {/* TODO: Remove ? from activity after database reset. */} + {log.activity?.name} {getSuccessStringShort(log.success)} ))} @@ -112,7 +116,8 @@ export const ActivityTrackingHome: FunctionComponent = observer(() => { {viewState.selectedLog && ( diff --git a/web_registry/src/components/PatientDetail/ActivityProgress.tsx b/web_registry/src/components/PatientDetail/ActivityProgress.tsx index 340126f2..71147070 100644 --- a/web_registry/src/components/PatientDetail/ActivityProgress.tsx +++ b/web_registry/src/components/PatientDetail/ActivityProgress.tsx @@ -44,7 +44,7 @@ export const ActivityProgress: FunctionComponent = observer(() => { const tableData = logs?.map((log) => { return { id: log.scheduledActivityId, - name: log.activityName, + name: log.activity?.name, dueDate: format(log.dueDateTime, 'MM/dd/yyyy'), recordedDateTime: log.completed && log.recordedDateTime ? format(log.recordedDateTime, 'MM/dd/yyyy') : '--', completed: log.completed && log.success ? getCompleted(log.success) : '--', diff --git a/web_shared/types.ts b/web_shared/types.ts index b0020ae7..02c9733e 100644 --- a/web_shared/types.ts +++ b/web_shared/types.ts @@ -134,8 +134,8 @@ export interface IScheduledActivity extends IScheduledItem { activityScheduleId: string; // NOTE: Check w/ James if these can go away. - activityId: string; - activityName: string; + //activityId: string; + //activityName: string; reminder: Date; completed: boolean; @@ -159,8 +159,10 @@ export interface IActivityLog extends ILog { activityLogId?: string; scheduledActivityId: string; - activityId: string; - activityName: string; + + activity: IActivity; + // activityId: string; + // activityName: string; completed?: boolean; success?: ActivitySuccessType; From 880118a63bc845bd0e80d534e8db41b699ec85be Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 09:49:51 -0800 Subject: [PATCH 09/18] Schema assessment-log: Replaced assessmentId with assessment --- .../schemas/documents/assessment-log.json | 110 ++++++++++-------- 1 file changed, 60 insertions(+), 50 deletions(-) diff --git a/scope_shared/scope/schemas/documents/assessment-log.json b/scope_shared/scope/schemas/documents/assessment-log.json index ad6d653b..91b63b7c 100644 --- a/scope_shared/scope/schemas/documents/assessment-log.json +++ b/scope_shared/scope/schemas/documents/assessment-log.json @@ -1,52 +1,62 @@ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://uwscope.org/schemas/documents/assessment-log", - "title": "IAssessmentLog", - "description": "IAssessmentLog Type", - "type": "object", - "$comment": "property pointValues not clear : { \"$ref\": \"\"}", - "properties": { - "_id": { - "type": "string" - }, - "_type": { - "const": "assessmentLog" - }, - "_set_id": { - "type": "string" - }, - "_rev": { - "type": "number" - }, - "assessmentLogId": { - "type": "string" - }, - "scheduledAssessmentId": { - "type": "string" - }, - "assessmentId": { - "type": "string" - }, - "recordedDateTime": { - "$ref": "/schemas/documents/utils/log#/properties/recordedDateTime" - }, - "comment": { - "$ref": "/schemas/documents/utils/log#/properties/comment" - }, - "patientSubmitted": { - "type": "boolean" - }, - "submittedByProviderId": { - "type": "string" - }, - "pointValues": { - "type": "object", - "$comment": "TODO" - }, - "totalScore": { - "type": "number" - } - }, - "additionalProperties": false, - "required": ["_type", "recordedDateTime", "scheduledAssessmentId", "assessmentId", "pointValues"] + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://uwscope.org/schemas/documents/assessment-log", + "title": "IAssessmentLog", + "description": "IAssessmentLog Type", + "$comment": [ + "---------------------------------------", + "Added Entire Assessment Json", + "---------------------------------------", + { + "assessmentId": { + "type": "string" + } + } + ], + "type": "object", + "$comment": "property pointValues not clear : { \"$ref\": \"\"}", + "properties": { + "_id": { + "type": "string" + }, + "_type": { + "const": "assessmentLog" + }, + "_set_id": { + "type": "string" + }, + "_rev": { + "type": "number" + }, + "assessmentLogId": { + "type": "string" + }, + "scheduledAssessmentId": { + "type": "string" + }, + "assessment": { + "$ref": "/schemas/documents/assessment" + }, + "recordedDateTime": { + "$ref": "/schemas/documents/utils/log#/properties/recordedDateTime" + }, + "comment": { + "$ref": "/schemas/documents/utils/log#/properties/comment" + }, + "patientSubmitted": { + "type": "boolean" + }, + "submittedByProviderId": { + "type": "string" + }, + "pointValues": { + "type": "object", + "$comment": "TODO" + }, + "totalScore": { + "type": "number" + } + }, + "additionalProperties": false, + "required": ["_type", "recordedDateTime", "scheduledAssessmentId", "assessment", "pointValues"] } From 1a295d0648d4ae08a092364daab518504acad6fc Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 09:54:53 -0800 Subject: [PATCH 10/18] AssessmentForm: Replace assessmentId with assessment --- .../src/components/Forms/AssessmentForm.tsx | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/web_patient/src/components/Forms/AssessmentForm.tsx b/web_patient/src/components/Forms/AssessmentForm.tsx index 9ee13fc6..31794a84 100644 --- a/web_patient/src/components/Forms/AssessmentForm.tsx +++ b/web_patient/src/components/Forms/AssessmentForm.tsx @@ -26,7 +26,7 @@ import { useStores } from 'src/stores/stores'; import { getAssessmentScore } from 'src/utils/assessment'; import styled from 'styled-components'; -export interface IAssessmentFormProps extends IFormProps { } +export interface IAssessmentFormProps extends IFormProps {} interface IQuestionFormProps { instruction: string; @@ -67,21 +67,19 @@ const CrisisContent: FunctionComponent = () => { prompt={'Crisis resources'} content={ - - You indicated that you are having thoughts of death or suicide. - + You indicated that you are having thoughts of death or suicide. If you need more help right away, here are some resources to try:
  • - Suicide & Crisis Lifeline - Call {' '} + Suicide & Crisis Lifeline - Call{' '} 988 - - {' '} or {' '} + {' '} + or{' '} {
  • - Lifeline Web Chat - {' '} + Lifeline Web Chat -{' '} {
  • - Crisis Text Line - {' '} + Crisis Text Line -{' '} https://www.crisistextline.org/ - - {' '} - Text {' '} + {' '} + - Text{' '} 988 - - {' '} or Text "HOME" to {' '} + {' '} + or Text "HOME" to{' '} = observer( const handleSubmit = action(async () => { const { scheduledAssessmentId, assessmentId } = scheduledAssessment; + const assessment = patientStore.getAssessmentById(assessmentId); + try { const log = { scheduledAssessmentId, - assessmentId, + //assessmentId, + assessment, patientSubmitted: true, pointValues: Object.fromEntries(dataState.pointValues.entries()), recordedDateTime: new Date(), From 4003de62cb033cc4739530e2e375c81af2c70af9 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 09:55:25 -0800 Subject: [PATCH 11/18] AssessmentHome: Replace assessmentId with assessment.assessmentId --- web_patient/src/components/Progress/AssessmentHome.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web_patient/src/components/Progress/AssessmentHome.tsx b/web_patient/src/components/Progress/AssessmentHome.tsx index 38bd9e64..d4311212 100644 --- a/web_patient/src/components/Progress/AssessmentHome.tsx +++ b/web_patient/src/components/Progress/AssessmentHome.tsx @@ -50,7 +50,8 @@ export const AssessmentHome: FunctionComponent<{ assessmentType: string }> = obs assessmentType == 'phq-9' ? 'Progress_phq_assessment_detail_title' : 'Progress_gad_assessment_detail_title'; const assessmentContent = rootStore.getAssessmentContent(assessmentType); - const logs = patientStore.assessmentLogs.filter((a) => a.assessmentId.toLowerCase() == assessmentType); + // TODO: Remove ? after a.assessment after database reset. + const logs = patientStore.assessmentLogs.filter((a) => a.assessment?.assessmentId.toLowerCase() == assessmentType); const getValueString = (pointValue: number | undefined) => { return `${assessmentContent?.options.find((o) => o.value == pointValue)?.text} (${pointValue})`; From 088cbb4faeaed5d2ddcb89e8c5b722bc8c90cd4f Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 09:55:51 -0800 Subject: [PATCH 12/18] PatientStore: Add assessments --- web_patient/src/stores/PatientStore.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/web_patient/src/stores/PatientStore.ts b/web_patient/src/stores/PatientStore.ts index 06688206..9c564096 100644 --- a/web_patient/src/stores/PatientStore.ts +++ b/web_patient/src/stores/PatientStore.ts @@ -9,6 +9,7 @@ import { IActivity, IActivityLog, IActivitySchedule, + IAssessment, IAssessmentLog, IMoodLog, IPatient, @@ -26,6 +27,7 @@ export interface IPatientStore { readonly activities: IActivity[]; readonly activityLogs: IActivityLog[]; readonly activitySchedules: IActivitySchedule[]; + readonly assessments: IAssessment[]; readonly assessmentsToComplete: IScheduledAssessment[]; readonly assessmentLogs: IAssessmentLog[]; readonly config: IPatientConfig; @@ -42,6 +44,7 @@ export interface IPatientStore { readonly loadActivitiesState: IPromiseQueryState; readonly loadActivityLogsState: IPromiseQueryState; readonly loadActivitySchedulesState: IPromiseQueryState; + readonly loadAssessmentsState: IPromiseQueryState; readonly loadAssessmentLogsState: IPromiseQueryState; readonly loadConfigState: IPromiseQueryState; readonly loadMoodLogsState: IPromiseQueryState; @@ -58,6 +61,7 @@ export interface IPatientStore { getActivitiesWithoutValueId: () => IActivity[]; getActivityScheduleById: (activityScheduleId: string) => IActivitySchedule | undefined; getActivitySchedulesByActivityId: (activityId: string) => IActivitySchedule[]; + getAssessmentById: (assessmentId: string) => IAssessment | undefined; getScheduledAssessmentById: (scheduleId: string) => IScheduledAssessment | undefined; getTaskById: (taskId: string) => IScheduledActivity | undefined; getValueById: (valueId: string) => IValue | undefined; @@ -110,6 +114,7 @@ export class PatientStore implements IPatientStore { private readonly loadActivitiesQuery: PromiseQuery; private readonly loadActivityLogsQuery: PromiseQuery; private readonly loadActivitySchedulesQuery: PromiseQuery; + private readonly loadAssessmentsQuery: PromiseQuery; private readonly loadAssessmentLogsQuery: PromiseQuery; private readonly loadConfigQuery: PromiseQuery; private readonly loadMoodLogsQuery: PromiseQuery; @@ -137,6 +142,7 @@ export class PatientStore implements IPatientStore { this.loadActivitiesQuery = new PromiseQuery([], 'loadActivitiesQuery'); this.loadActivitySchedulesQuery = new PromiseQuery([], 'loadActivitySchedulesQuery'); this.loadActivityLogsQuery = new PromiseQuery([], 'loadActivityLogsQuery'); + this.loadAssessmentsQuery = new PromiseQuery([], 'loadAssessmentsQuery'); this.loadAssessmentLogsQuery = new PromiseQuery([], 'loadAssessmentLogsQuery'); this.loadConfigQuery = new PromiseQuery(undefined, 'loadConfigQuery'); this.loadMoodLogsQuery = new PromiseQuery([], 'loadMoodLogsQuery'); @@ -194,6 +200,10 @@ export class PatientStore implements IPatientStore { return latestAssessments; } + @computed public get assessments() { + return this.loadAssessmentsQuery.value || []; + } + @computed public get assessmentLogs() { return this.loadAssessmentLogsQuery.value || []; } @@ -254,6 +264,10 @@ export class PatientStore implements IPatientStore { return this.loadActivitySchedulesQuery; } + @computed public get loadAssessmentsState() { + return this.loadAssessmentsQuery; + } + @computed public get loadAssessmentLogsState() { return this.loadAssessmentLogsQuery; } @@ -341,6 +355,11 @@ export class PatientStore implements IPatientStore { }); } + @action.bound + public getAssessmentById(assessmentId: string) { + return this.assessments.find((a) => a.assessmentId == assessmentId); + } + @action.bound public getScheduledAssessmentById(scheduleId: string) { return this.loadScheduledAssessmentsQuery.value?.find((t) => t.scheduledAssessmentId == scheduleId); @@ -369,6 +388,7 @@ export class PatientStore implements IPatientStore { this.loadActivitiesQuery.fromPromise(Promise.resolve(patient.activities)); this.loadActivityLogsQuery.fromPromise(Promise.resolve(patient.activityLogs)); this.loadActivitySchedulesQuery.fromPromise(Promise.resolve(patient.activitySchedules)); + this.loadAssessmentsQuery.fromPromise(Promise.resolve(patient.assessments)); this.loadAssessmentLogsQuery.fromPromise(Promise.resolve(patient.assessmentLogs)); this.loadMoodLogsQuery.fromPromise(Promise.resolve(patient.moodLogs)); this.loadSafetyPlanQuery.fromPromise(Promise.resolve(patient.safetyPlan)); From 4fd98aac800141df32a7b3102b5039ade9fcd95c Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 09:57:30 -0800 Subject: [PATCH 13/18] AssessmentProgress: Replace assessmentId with assessment --- .../src/components/PatientDetail/AssessmentProgress.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_registry/src/components/PatientDetail/AssessmentProgress.tsx b/web_registry/src/components/PatientDetail/AssessmentProgress.tsx index d9211366..62da659a 100644 --- a/web_registry/src/components/PatientDetail/AssessmentProgress.tsx +++ b/web_registry/src/components/PatientDetail/AssessmentProgress.tsx @@ -95,7 +95,7 @@ export const AssessmentProgress: FunctionComponent = o totalOnly: false, totalScoreString: '', log: { - assessmentId: assessment.assessmentId, + assessment: assessment, recordedDateTime: new Date(), comment: '', pointValues: {}, @@ -112,7 +112,7 @@ export const AssessmentProgress: FunctionComponent = o logState.openEdit = true; logState.totalOnly = false; logState.log = { - assessmentId: assessment.assessmentId, + assessment: assessment, recordedDateTime: new Date(), comment: '', pointValues: {}, From 7f5e1675fbc38f7ab1f387013c634506da6f17e1 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 09:58:01 -0800 Subject: [PATCH 14/18] ProgressInformation: Replace assessmentId with assessment.assessmentId --- .../src/components/PatientDetail/ProgressInformation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_registry/src/components/PatientDetail/ProgressInformation.tsx b/web_registry/src/components/PatientDetail/ProgressInformation.tsx index 6c482f54..905a708f 100644 --- a/web_registry/src/components/PatientDetail/ProgressInformation.tsx +++ b/web_registry/src/components/PatientDetail/ProgressInformation.tsx @@ -32,7 +32,7 @@ export const ProgressInformation: FunctionComponent = observer(() => { assigned: false, } as IAssessment); - const assessmentLogs = currentPatient?.assessmentLogs.filter((l) => l.assessmentId == assessmentId); + const assessmentLogs = currentPatient?.assessmentLogs.filter((l) => l.assessment?.assessmentId == assessmentId); // if (!!assessment) { switch (assessmentId) { From 0645c50cea14af7f1db0e9314a01e6ccee3097f6 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 09:58:30 -0800 Subject: [PATCH 15/18] SessionInfo: Replace assessmentId with assessment.assessmentId --- web_registry/src/components/PatientDetail/SessionInfo.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_registry/src/components/PatientDetail/SessionInfo.tsx b/web_registry/src/components/PatientDetail/SessionInfo.tsx index fa81f757..bd4e975d 100644 --- a/web_registry/src/components/PatientDetail/SessionInfo.tsx +++ b/web_registry/src/components/PatientDetail/SessionInfo.tsx @@ -483,14 +483,14 @@ export const SessionInfo: FunctionComponent = observer(() => { .sort((a, b) => (state.dateAsc ? compareAsc(a.date, b.date) : compareDesc(a.date, b.date))); const phqScores = currentPatient.assessmentLogs - .filter((log) => log.assessmentId == 'phq-9') + .filter((log) => log.assessment?.assessmentId == 'phq-9') .map((log) => ({ date: log.recordedDateTime, score: log.totalScore || getAssessmentScoreFromPointValues(log.pointValues), })); const gadScores = currentPatient.assessmentLogs - .filter((log) => log.assessmentId == 'gad-7') + .filter((log) => log.assessment?.assessmentId == 'gad-7') .map((log) => ({ date: log.recordedDateTime, score: log.totalScore || getAssessmentScoreFromPointValues(log.pointValues), From 3c9d917270364a993b257751b2ad5e238fe54236 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 10:01:20 -0800 Subject: [PATCH 16/18] TreatmentInfo: Replace assessmentId with assessment.assessmentId --- web_registry/src/components/PatientDetail/TreatmentInfo.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_registry/src/components/PatientDetail/TreatmentInfo.tsx b/web_registry/src/components/PatientDetail/TreatmentInfo.tsx index b9951bbb..631fdfde 100644 --- a/web_registry/src/components/PatientDetail/TreatmentInfo.tsx +++ b/web_registry/src/components/PatientDetail/TreatmentInfo.tsx @@ -16,9 +16,9 @@ export const TreatmentInfo: FunctionComponent = observer(() => { .slice() .sort((a, b) => compareDesc(a.recordedDateTime, b.recordedDateTime)); - const latestPhqLog = sortedAssessmentLogs.filter((a) => a.assessmentId == 'phq-9')[0]; + const latestPhqLog = sortedAssessmentLogs.filter((a) => a.assessment?.assessmentId == 'phq-9')[0]; const latestPhqScore = getLatestScore(currentPatient?.assessmentLogs, 'phq-9'); - const latestGadLog = sortedAssessmentLogs.filter((a) => a.assessmentId == 'gad-7')[0]; + const latestGadLog = sortedAssessmentLogs.filter((a) => a.assessment?.assessmentId == 'gad-7')[0]; const latestGadScore = getLatestScore(currentPatient?.assessmentLogs, 'gad-7'); const latestSessionDate = currentPatient.latestSession?.date; From ea2bc98b733c3b9d6292f52fd7ba414252ae7f95 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 10:01:50 -0800 Subject: [PATCH 17/18] CaseLoadTable: Replace assessmentId with assessment.assessmentId --- .../src/components/caseload/CaseloadTable.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/web_registry/src/components/caseload/CaseloadTable.tsx b/web_registry/src/components/caseload/CaseloadTable.tsx index b78502a1..ce1efb3a 100644 --- a/web_registry/src/components/caseload/CaseloadTable.tsx +++ b/web_registry/src/components/caseload/CaseloadTable.tsx @@ -1,12 +1,7 @@ import FlagIcon from '@mui/icons-material/Flag'; import { Tooltip } from '@mui/material'; import withTheme from '@mui/styles/withTheme'; -import { - GridCellParams, - GridColDef, - GridColumnHeaderParams, - GridRowParams, -} from '@mui/x-data-grid'; +import { GridCellParams, GridColDef, GridColumnHeaderParams, GridRowParams } from '@mui/x-data-grid'; import { addWeeks, compareAsc, differenceInWeeks } from 'date-fns'; import React, { FunctionComponent } from 'react'; import { formatDateOnly, getFollowupWeeks } from 'shared/time'; @@ -286,11 +281,11 @@ export const CaseloadTable: FunctionComponent = (props) => const recentReviewDate = p.caseReviews?.length > 0 ? p.caseReviews[p.caseReviews.length - 1].date : null; const phq9 = p.assessmentLogs - ?.filter((a) => a.assessmentId == 'phq-9') + ?.filter((a) => a.assessment.assessmentId == 'phq-9') .slice() .sort((a, b) => compareAsc(a.recordedDateTime, b.recordedDateTime)); const gad7 = p.assessmentLogs - ?.filter((a) => a.assessmentId == 'gad-7') + ?.filter((a) => a.assessment.assessmentId == 'gad-7') .slice() .sort((a, b) => compareAsc(a.recordedDateTime, b.recordedDateTime)); From 37e791c6c848a04ab8f1433cedb6fa1c28a374f5 Mon Sep 17 00:00:00 2001 From: Anant Mittal Date: Fri, 27 Jan 2023 10:02:31 -0800 Subject: [PATCH 18/18] assessment.ts,types.ts: Replace assessmentId with assessment.assessmentId --- web_registry/src/utils/assessment.ts | 2 +- web_shared/types.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/web_registry/src/utils/assessment.ts b/web_registry/src/utils/assessment.ts index a33e851d..0d6dabbc 100644 --- a/web_registry/src/utils/assessment.ts +++ b/web_registry/src/utils/assessment.ts @@ -38,7 +38,7 @@ export const getAssessmentScoreFromPointValues = (pointValues: AssessmentData) = }; export const getLatestScore = (assessmentLogs: IAssessmentLog[], assessmentId: string) => { - const filteredAssessmentLogs = assessmentLogs.filter((a) => a.assessmentId == assessmentId); + const filteredAssessmentLogs = assessmentLogs.filter((a) => a.assessment?.assessmentId == assessmentId); if (filteredAssessmentLogs.length > 0) { const sortedAssessments = filteredAssessmentLogs .slice() diff --git a/web_shared/types.ts b/web_shared/types.ts index 02c9733e..e84a8dbb 100644 --- a/web_shared/types.ts +++ b/web_shared/types.ts @@ -175,7 +175,8 @@ export interface IAssessmentLog extends ILog { assessmentLogId?: string; scheduledAssessmentId: string; - assessmentId: string; // NEW + //assessmentId: string; // NEW + assessment: IAssessment; patientSubmitted?: boolean; // NEW submittedByProviderId?: string;