vintasend 0.4.0 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/examples/vintasend-medplum-example/.env.example +11 -0
- package/dist/examples/vintasend-medplum-example/IMPLEMENTATION_PLAN_FILE_ATTACHMENTS.md +597 -0
- package/dist/examples/vintasend-medplum-example/README.md +190 -0
- package/dist/examples/vintasend-medplum-example/TUTORIAL_EMAIL_NOTIFICATIONS.md +2596 -0
- package/dist/examples/vintasend-medplum-example/bots/handlers/send-pending-notifications-bot.ts +39 -0
- package/dist/examples/vintasend-medplum-example/bots/handlers/send-task-assignment-email.ts +41 -0
- package/dist/examples/vintasend-medplum-example/bots/handlers/task-due-soon-notification-bot.ts +86 -0
- package/dist/examples/vintasend-medplum-example/bots/index.ts +53 -0
- package/dist/examples/vintasend-medplum-example/bots/services/emails/schedule-task-due-soon-email.ts +84 -0
- package/dist/examples/vintasend-medplum-example/bots/services/emails/send-task-assignment-email.test.ts +388 -0
- package/dist/examples/vintasend-medplum-example/bots/services/emails/send-task-assignment-email.ts +113 -0
- package/dist/examples/vintasend-medplum-example/bots/shared/task-due-soon-helpers.ts +115 -0
- package/dist/examples/vintasend-medplum-example/bots/task-assignment-bot.ts +41 -0
- package/dist/examples/vintasend-medplum-example/compiled-notification-templates.json +6 -0
- package/dist/examples/vintasend-medplum-example/esbuild-script.mjs +71 -0
- package/dist/examples/vintasend-medplum-example/index.html +14 -0
- package/dist/examples/vintasend-medplum-example/lib/constants.ts +32 -0
- package/dist/examples/vintasend-medplum-example/lib/extensions.ts +1 -0
- package/dist/examples/vintasend-medplum-example/lib/file-upload.test.ts +389 -0
- package/dist/examples/vintasend-medplum-example/lib/file-upload.ts +222 -0
- package/dist/examples/vintasend-medplum-example/lib/medplum-singleton.ts +18 -0
- package/dist/examples/vintasend-medplum-example/lib/notification-service.test.ts +293 -0
- package/dist/examples/vintasend-medplum-example/lib/notification-service.ts +284 -0
- package/dist/examples/vintasend-medplum-example/lib/patients.ts +20 -0
- package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-assignment/body.html.pug +37 -0
- package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-assignment/subject.txt.pug +4 -0
- package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-due-soon/body.html.pug +34 -0
- package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-due-soon/subject.txt.pug +4 -0
- package/dist/examples/vintasend-medplum-example/package.json +75 -0
- package/dist/examples/vintasend-medplum-example/plugins/gql-plugin.mjs +31 -0
- package/dist/examples/vintasend-medplum-example/postcss.config.mjs +21 -0
- package/dist/examples/vintasend-medplum-example/public/favicon.ico +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/acuity.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/auth0.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/azure.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/calcom.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/candid.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/claude.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/datadog.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/deepseek.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/entra.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/epic.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/google.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/healthgorilla.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/healthie.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/labcorp.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/okta.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/openai.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/particle.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/quest.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/recaptcha.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/snowflake.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/stedi.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/stripe.png +0 -0
- package/dist/examples/vintasend-medplum-example/public/img/integrations/sumo.png +0 -0
- package/dist/examples/vintasend-medplum-example/scripts/README.md +162 -0
- package/dist/examples/vintasend-medplum-example/scripts/client.ts +18 -0
- package/dist/examples/vintasend-medplum-example/scripts/deploy-bots.ts +171 -0
- package/dist/examples/vintasend-medplum-example/src/App.tsx +185 -0
- package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemList.test.tsx +350 -0
- package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemList.tsx +241 -0
- package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemPanel.test.tsx +616 -0
- package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemPanel.tsx +138 -0
- package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionItem.test.tsx +92 -0
- package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionItem.tsx +47 -0
- package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionList.test.tsx +464 -0
- package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionList.tsx +186 -0
- package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionModal.test.tsx +80 -0
- package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionModal.tsx +82 -0
- package/dist/examples/vintasend-medplum-example/src/components/DoseSpotIcon.test.tsx +100 -0
- package/dist/examples/vintasend-medplum-example/src/components/DoseSpotIcon.tsx +20 -0
- package/dist/examples/vintasend-medplum-example/src/components/IntegrationCard.module.css +3 -0
- package/dist/examples/vintasend-medplum-example/src/components/IntegrationCard.tsx +62 -0
- package/dist/examples/vintasend-medplum-example/src/components/MessageWithLinks.tsx +47 -0
- package/dist/examples/vintasend-medplum-example/src/components/PerformingLabInput.test.tsx +299 -0
- package/dist/examples/vintasend-medplum-example/src/components/PerformingLabInput.tsx +52 -0
- package/dist/examples/vintasend-medplum-example/src/components/ResourceFormWithRequiredProfile.tsx +82 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/BillingTab.test.tsx +1016 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/BillingTab.tsx +298 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterChart.test.tsx +732 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterChart.tsx +282 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterHeader.test.tsx +268 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterHeader.tsx +224 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/SignAddendum.test.tsx +255 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/SignAddendum.tsx +212 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/SignLockDialog.test.tsx +120 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/SignLockDialog.tsx +57 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/VisitDetailsPanel.test.tsx +224 -0
- package/dist/examples/vintasend-medplum-example/src/components/encounter/VisitDetailsPanel.tsx +100 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/CoverageInput.test.tsx +431 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/CoverageInput.tsx +130 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabListItem.module.css +31 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabListItem.test.tsx +234 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabListItem.tsx +143 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabOrderDetails.module.css +11 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabOrderDetails.test.tsx +875 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabOrderDetails.tsx +943 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabResultDetails.test.tsx +413 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabResultDetails.tsx +203 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/LabSelectEmpty.tsx +22 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/README.md +104 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/TestMetadataCardInput.test.tsx +318 -0
- package/dist/examples/vintasend-medplum-example/src/components/labs/TestMetadataCardInput.tsx +87 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ChatList.test.tsx +126 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ChatList.tsx +38 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ChatListItem.module.css +23 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ChatListItem.test.tsx +167 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ChatListItem.tsx +53 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/NewTopicDialog.test.tsx +94 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/NewTopicDialog.tsx +165 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ParticipantFilter.module.css +8 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ParticipantFilter.test.tsx +523 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ParticipantFilter.tsx +230 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ThreadInbox.module.css +23 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ThreadInbox.test.tsx +567 -0
- package/dist/examples/vintasend-medplum-example/src/components/messages/ThreadInbox.tsx +358 -0
- package/dist/examples/vintasend-medplum-example/src/components/plandefinition/AddPlanDefinition.module.css +40 -0
- package/dist/examples/vintasend-medplum-example/src/components/plandefinition/AddPlanDefinition.tsx +257 -0
- package/dist/examples/vintasend-medplum-example/src/components/schedule/CreateVisit.module.css +7 -0
- package/dist/examples/vintasend-medplum-example/src/components/schedule/CreateVisit.test.tsx +279 -0
- package/dist/examples/vintasend-medplum-example/src/components/schedule/CreateVisit.tsx +156 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/HistoryList.module.css +45 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/HistoryList.test.tsx +90 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/HistoryList.tsx +84 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourceBox.module.css +26 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourceBox.tsx +90 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourcePanel.test.tsx +305 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourcePanel.tsx +46 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/SpacesInbox.module.css +262 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/SpacesInbox.test.tsx +622 -0
- package/dist/examples/vintasend-medplum-example/src/components/spaces/SpacesInbox.tsx +286 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/NewTaskModal.tsx +275 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskAttachmentList.tsx +132 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskBoard.module.css +45 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskBoard.test.tsx +749 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskBoard.tsx +416 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailPanel.test.tsx +278 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailPanel.tsx +133 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailsModal.module.css +16 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailsModal.test.tsx +255 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailsModal.tsx +203 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFileUpload.tsx +129 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFilterMenu.test.tsx +156 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFilterMenu.tsx +142 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFilterMenu.utils.ts +28 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskInputNote.test.tsx +134 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskInputNote.tsx +250 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskListItem.module.css +23 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskListItem.test.tsx +149 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskListItem.tsx +53 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskNoteItem.test.tsx +68 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskNoteItem.tsx +46 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskProperties.test.tsx +555 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskProperties.tsx +170 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskSelectEmpty.test.tsx +32 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskSelectEmpty.tsx +34 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/SimpleTask.test.tsx +47 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/SimpleTask.tsx +29 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskPanel.test.tsx +285 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskPanel.tsx +129 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskQuestionnaireForm.test.tsx +455 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskQuestionnaireForm.tsx +167 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskServiceRequest.test.tsx +435 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskServiceRequest.tsx +116 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskStatusPanel.module.css +38 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskStatusPanel.test.tsx +200 -0
- package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskStatusPanel.tsx +84 -0
- package/dist/examples/vintasend-medplum-example/src/components/utils.test.ts +176 -0
- package/dist/examples/vintasend-medplum-example/src/components/utils.ts +17 -0
- package/dist/examples/vintasend-medplum-example/src/config/constants.ts +3 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useDebouncedUpdateResource.test.tsx +166 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useDebouncedUpdateResource.ts +28 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useEncounter.test.tsx +94 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useEncounter.ts +11 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useEncounterChart.test.tsx +477 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useEncounterChart.ts +191 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/usePatient.test.tsx +100 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/usePatient.ts +18 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useThreadInbox.test.tsx +379 -0
- package/dist/examples/vintasend-medplum-example/src/hooks/useThreadInbox.ts +194 -0
- package/dist/examples/vintasend-medplum-example/src/index.css +8 -0
- package/dist/examples/vintasend-medplum-example/src/main.tsx +57 -0
- package/dist/examples/vintasend-medplum-example/src/pages/SearchPage.module.css +6 -0
- package/dist/examples/vintasend-medplum-example/src/pages/SearchPage.test.tsx +295 -0
- package/dist/examples/vintasend-medplum-example/src/pages/SearchPage.tsx +124 -0
- package/dist/examples/vintasend-medplum-example/src/pages/SignInPage.test.tsx +77 -0
- package/dist/examples/vintasend-medplum-example/src/pages/SignInPage.tsx +22 -0
- package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterChartPage.test.tsx +87 -0
- package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterChartPage.tsx +27 -0
- package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterModal.module.css +16 -0
- package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterModal.test.tsx +287 -0
- package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterModal.tsx +151 -0
- package/dist/examples/vintasend-medplum-example/src/pages/integrations/DoseSpotFavoritesPage.test.tsx +519 -0
- package/dist/examples/vintasend-medplum-example/src/pages/integrations/DoseSpotFavoritesPage.tsx +179 -0
- package/dist/examples/vintasend-medplum-example/src/pages/integrations/FavoriteMedicationsTable.tsx +76 -0
- package/dist/examples/vintasend-medplum-example/src/pages/integrations/IntegrationsPage.test.tsx +234 -0
- package/dist/examples/vintasend-medplum-example/src/pages/integrations/IntegrationsPage.tsx +222 -0
- package/dist/examples/vintasend-medplum-example/src/pages/labs/OrderLabsPage.test.tsx +356 -0
- package/dist/examples/vintasend-medplum-example/src/pages/labs/OrderLabsPage.tsx +275 -0
- package/dist/examples/vintasend-medplum-example/src/pages/messages/MessagesPage.module.css +8 -0
- package/dist/examples/vintasend-medplum-example/src/pages/messages/MessagesPage.test.tsx +103 -0
- package/dist/examples/vintasend-medplum-example/src/pages/messages/MessagesPage.tsx +78 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/CommunicationTab.test.tsx +84 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/CommunicationTab.tsx +82 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotAdvancedOptions.test.tsx +364 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotAdvancedOptions.tsx +149 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotTab.test.tsx +159 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotTab.tsx +37 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/EditTab.test.tsx +140 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/EditTab.tsx +72 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/ExportTab.test.tsx +57 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/ExportTab.tsx +14 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/IntakeFormPage.test.tsx +241 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/IntakeFormPage.tsx +710 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/LabsPage.module.css +37 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/LabsPage.test.tsx +428 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/LabsPage.tsx +334 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.module.css +24 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.test.tsx +154 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.tsx +115 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.utils.test.ts +223 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.utils.ts +89 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientSearchPage.test.tsx +147 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientSearchPage.tsx +79 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientTabsNavigation.tsx +35 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/TasksTab.test.tsx +185 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/TasksTab.tsx +115 -0
- package/dist/examples/vintasend-medplum-example/src/pages/patient/TimelineTab.tsx +14 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceCreatePage.test.tsx +170 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceCreatePage.tsx +117 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceDetailPage.tsx +28 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceEditPage.test.tsx +131 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceEditPage.tsx +65 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceHistoryPage.test.tsx +108 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceHistoryPage.tsx +16 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourcePage.module.css +7 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourcePage.test.tsx +37 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourcePage.tsx +44 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/useResourceType.ts +44 -0
- package/dist/examples/vintasend-medplum-example/src/pages/resource/utils.ts +9 -0
- package/dist/examples/vintasend-medplum-example/src/pages/schedule/SchedulePage.test.tsx +302 -0
- package/dist/examples/vintasend-medplum-example/src/pages/schedule/SchedulePage.tsx +416 -0
- package/dist/examples/vintasend-medplum-example/src/pages/spaces/ChatInput.tsx +91 -0
- package/dist/examples/vintasend-medplum-example/src/pages/spaces/SpacesPage.module.css +6 -0
- package/dist/examples/vintasend-medplum-example/src/pages/spaces/SpacesPage.test.tsx +102 -0
- package/dist/examples/vintasend-medplum-example/src/pages/spaces/SpacesPage.tsx +44 -0
- package/dist/examples/vintasend-medplum-example/src/pages/tasks/TasksPage.module.css +7 -0
- package/dist/examples/vintasend-medplum-example/src/pages/tasks/TasksPage.test.tsx +133 -0
- package/dist/examples/vintasend-medplum-example/src/pages/tasks/TasksPage.tsx +91 -0
- package/dist/examples/vintasend-medplum-example/src/test-utils/render.tsx +20 -0
- package/dist/examples/vintasend-medplum-example/src/test.setup.ts +49 -0
- package/dist/examples/vintasend-medplum-example/src/types/encounter.ts +8 -0
- package/dist/examples/vintasend-medplum-example/src/types/spaces.ts +10 -0
- package/dist/examples/vintasend-medplum-example/src/utils/chargeitems.test.ts +141 -0
- package/dist/examples/vintasend-medplum-example/src/utils/chargeitems.ts +59 -0
- package/dist/examples/vintasend-medplum-example/src/utils/claims.test.ts +153 -0
- package/dist/examples/vintasend-medplum-example/src/utils/claims.ts +65 -0
- package/dist/examples/vintasend-medplum-example/src/utils/communication-search.ts +47 -0
- package/dist/examples/vintasend-medplum-example/src/utils/coverage.test.ts +48 -0
- package/dist/examples/vintasend-medplum-example/src/utils/coverage.ts +33 -0
- package/dist/examples/vintasend-medplum-example/src/utils/documentReference.test.ts +102 -0
- package/dist/examples/vintasend-medplum-example/src/utils/documentReference.ts +55 -0
- package/dist/examples/vintasend-medplum-example/src/utils/encounter.test.ts +169 -0
- package/dist/examples/vintasend-medplum-example/src/utils/encounter.ts +261 -0
- package/dist/examples/vintasend-medplum-example/src/utils/intake-form.test.ts +154 -0
- package/dist/examples/vintasend-medplum-example/src/utils/intake-form.ts +272 -0
- package/dist/examples/vintasend-medplum-example/src/utils/intake-utils.test.ts +1137 -0
- package/dist/examples/vintasend-medplum-example/src/utils/intake-utils.ts +827 -0
- package/dist/examples/vintasend-medplum-example/src/utils/notifications.test.ts +27 -0
- package/dist/examples/vintasend-medplum-example/src/utils/notifications.ts +15 -0
- package/dist/examples/vintasend-medplum-example/src/utils/spaceMessaging.ts +249 -0
- package/dist/examples/vintasend-medplum-example/src/utils/spacePersistence.test.ts +450 -0
- package/dist/examples/vintasend-medplum-example/src/utils/spacePersistence.ts +147 -0
- package/dist/examples/vintasend-medplum-example/src/utils/task-search.ts +63 -0
- package/dist/examples/vintasend-medplum-example/src/vite-env.d.ts +3 -0
- package/dist/examples/vintasend-medplum-example/tsconfig.bots.json +4 -0
- package/dist/examples/vintasend-medplum-example/tsconfig.json +19 -0
- package/dist/examples/vintasend-medplum-example/vercel.json +3 -0
- package/dist/examples/vintasend-medplum-example/vite.config.ts +44 -0
- package/dist/services/notification-backends/base-notification-backend.d.ts +5 -0
- package/dist/services/notification-service.js +11 -1
- package/dist/services/notification-template-renderers/base-email-template-renderer.d.ts +5 -0
- package/package.json +1 -1
package/dist/examples/vintasend-medplum-example/src/pages/integrations/FavoriteMedicationsTable.tsx
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Table, Card, Text, LoadingOverlay } from '@mantine/core';
|
|
5
|
+
import type { MedicationKnowledge } from '@medplum/fhirtypes';
|
|
6
|
+
import { getCodeBySystem, NDC, RXNORM } from '@medplum/core';
|
|
7
|
+
import { getMedicationName } from '@medplum/dosespot-react';
|
|
8
|
+
|
|
9
|
+
interface FavoriteMedicationsTableProps {
|
|
10
|
+
clinicFavoriteMedications: MedicationKnowledge[] | undefined;
|
|
11
|
+
loadingFavorites?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This is a demo component for how you could display your favorite Medications
|
|
16
|
+
* from DoseSpot.
|
|
17
|
+
*
|
|
18
|
+
* The page is refreshed when a medication is added to the favorites list.
|
|
19
|
+
*
|
|
20
|
+
* @param props - The props for the component.
|
|
21
|
+
* @param props.clinicFavoriteMedications - The clinic favorite medications to display.
|
|
22
|
+
* @param props.loadingFavorites - Whether the table is loading.
|
|
23
|
+
* @returns A React component that displays the favorite medications.
|
|
24
|
+
*/
|
|
25
|
+
export function FavoriteMedicationsTable({
|
|
26
|
+
clinicFavoriteMedications,
|
|
27
|
+
loadingFavorites,
|
|
28
|
+
}: FavoriteMedicationsTableProps): React.JSX.Element {
|
|
29
|
+
if (loadingFavorites) {
|
|
30
|
+
return (
|
|
31
|
+
<Card withBorder p="xl">
|
|
32
|
+
<LoadingOverlay visible={true} />
|
|
33
|
+
</Card>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!clinicFavoriteMedications || clinicFavoriteMedications.length === 0) {
|
|
38
|
+
return (
|
|
39
|
+
<Text c="dimmed" ta="center" py="xl">
|
|
40
|
+
No favorite medications found
|
|
41
|
+
</Text>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Table>
|
|
47
|
+
<Table.Thead>
|
|
48
|
+
<Table.Tr>
|
|
49
|
+
<Table.Th>Medication</Table.Th>
|
|
50
|
+
<Table.Th>NDC</Table.Th>
|
|
51
|
+
<Table.Th>RxNorm</Table.Th>
|
|
52
|
+
<Table.Th>Directions</Table.Th>
|
|
53
|
+
</Table.Tr>
|
|
54
|
+
</Table.Thead>
|
|
55
|
+
<Table.Tbody>
|
|
56
|
+
{clinicFavoriteMedications.map((clinicFavoriteMedication, index) => (
|
|
57
|
+
<Table.Tr key={clinicFavoriteMedication.id || index}>
|
|
58
|
+
<Table.Td>
|
|
59
|
+
<Text fw={500}>{getMedicationName(clinicFavoriteMedication)}</Text>
|
|
60
|
+
</Table.Td>
|
|
61
|
+
<Table.Td>
|
|
62
|
+
{clinicFavoriteMedication.code ? getCodeBySystem(clinicFavoriteMedication.code, NDC) : ''}
|
|
63
|
+
</Table.Td>
|
|
64
|
+
<Table.Td>
|
|
65
|
+
{clinicFavoriteMedication.code ? getCodeBySystem(clinicFavoriteMedication.code, RXNORM) : ''}
|
|
66
|
+
</Table.Td>
|
|
67
|
+
<Table.Td>
|
|
68
|
+
{clinicFavoriteMedication.administrationGuidelines?.[0]?.dosage?.[0]?.dosage?.[0]?.patientInstruction ||
|
|
69
|
+
''}
|
|
70
|
+
</Table.Td>
|
|
71
|
+
</Table.Tr>
|
|
72
|
+
))}
|
|
73
|
+
</Table.Tbody>
|
|
74
|
+
</Table>
|
|
75
|
+
);
|
|
76
|
+
}
|
package/dist/examples/vintasend-medplum-example/src/pages/integrations/IntegrationsPage.test.tsx
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { describe, expect, test, beforeEach, afterEach, vi } from 'vitest';
|
|
4
|
+
import { IntegrationsPage } from './IntegrationsPage';
|
|
5
|
+
import { render, screen, fireEvent } from '../../test-utils/render';
|
|
6
|
+
|
|
7
|
+
describe('IntegrationsPage', () => {
|
|
8
|
+
let mockLocationHref: string;
|
|
9
|
+
const originalLocation = window.location;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
vi.clearAllMocks();
|
|
13
|
+
|
|
14
|
+
// Mock window.location.href
|
|
15
|
+
mockLocationHref = '';
|
|
16
|
+
Object.defineProperty(window, 'location', {
|
|
17
|
+
value: {
|
|
18
|
+
...originalLocation,
|
|
19
|
+
get href() {
|
|
20
|
+
return mockLocationHref;
|
|
21
|
+
},
|
|
22
|
+
set href(value: string) {
|
|
23
|
+
mockLocationHref = value;
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
writable: true,
|
|
27
|
+
configurable: true,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
Object.defineProperty(window, 'location', {
|
|
33
|
+
value: originalLocation,
|
|
34
|
+
writable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
function setup(): void {
|
|
40
|
+
render(<IntegrationsPage />);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
test('Renders all integrations', () => {
|
|
44
|
+
setup();
|
|
45
|
+
|
|
46
|
+
// Check that all integration names are rendered
|
|
47
|
+
expect(screen.getByText('Okta')).toBeInTheDocument();
|
|
48
|
+
expect(screen.getByText('Auth0')).toBeInTheDocument();
|
|
49
|
+
expect(screen.getByText('Google Authentication')).toBeInTheDocument();
|
|
50
|
+
expect(screen.getByText('Microsoft Entra SSO')).toBeInTheDocument();
|
|
51
|
+
expect(screen.getByText('Labcorp')).toBeInTheDocument();
|
|
52
|
+
expect(screen.getByText('Quest Diagnostics')).toBeInTheDocument();
|
|
53
|
+
expect(screen.getByText('Health Gorilla')).toBeInTheDocument();
|
|
54
|
+
expect(screen.getByText('Candid Health')).toBeInTheDocument();
|
|
55
|
+
expect(screen.getByText('Particle')).toBeInTheDocument();
|
|
56
|
+
expect(screen.getByText('Epic Systems')).toBeInTheDocument();
|
|
57
|
+
expect(screen.getByText('reCAPTCHA')).toBeInTheDocument();
|
|
58
|
+
expect(screen.getByText('Datadog')).toBeInTheDocument();
|
|
59
|
+
expect(screen.getByText('Sumo Logic')).toBeInTheDocument();
|
|
60
|
+
expect(screen.getByText('Snowflake')).toBeInTheDocument();
|
|
61
|
+
expect(screen.getByText('OpenAI')).toBeInTheDocument();
|
|
62
|
+
expect(screen.getByText('Stripe')).toBeInTheDocument();
|
|
63
|
+
expect(screen.getByText('Acuity Scheduling')).toBeInTheDocument();
|
|
64
|
+
expect(screen.getByText('Cal.com')).toBeInTheDocument();
|
|
65
|
+
expect(screen.getByText('Claude')).toBeInTheDocument();
|
|
66
|
+
expect(screen.getByText('DeepSeek')).toBeInTheDocument();
|
|
67
|
+
expect(screen.getByText('Azure')).toBeInTheDocument();
|
|
68
|
+
expect(screen.getByText('Healthie')).toBeInTheDocument();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('Renders integration descriptions', () => {
|
|
72
|
+
setup();
|
|
73
|
+
|
|
74
|
+
expect(
|
|
75
|
+
screen.getByText(/Implement SSO for healthcare staff with HIPAA-compliant authentication protocols/)
|
|
76
|
+
).toBeInTheDocument();
|
|
77
|
+
expect(screen.getByText(/Manage identity access for patient portals/)).toBeInTheDocument();
|
|
78
|
+
expect(
|
|
79
|
+
screen.getByText(/Place orders and receive lab results directly in your EHR from Labcorp/)
|
|
80
|
+
).toBeInTheDocument();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('Renders integration tags', () => {
|
|
84
|
+
setup();
|
|
85
|
+
|
|
86
|
+
// Check for various tags
|
|
87
|
+
expect(screen.getAllByText('Authentication').length).toBeGreaterThan(0);
|
|
88
|
+
expect(screen.getAllByText('Diagnostics').length).toBeGreaterThan(0);
|
|
89
|
+
expect(screen.getAllByText('Billing').length).toBeGreaterThan(0);
|
|
90
|
+
expect(screen.getAllByText('HIE').length).toBeGreaterThan(0);
|
|
91
|
+
expect(screen.getAllByText('EHR').length).toBeGreaterThan(0);
|
|
92
|
+
expect(screen.getAllByText('Security').length).toBeGreaterThan(0);
|
|
93
|
+
expect(screen.getAllByText('Observability').length).toBeGreaterThan(0);
|
|
94
|
+
expect(screen.getAllByText('AI').length).toBeGreaterThan(0);
|
|
95
|
+
expect(screen.getAllByText('Scheduling').length).toBeGreaterThan(0);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('Renders Request Integration buttons for all integrations', () => {
|
|
99
|
+
setup();
|
|
100
|
+
|
|
101
|
+
// There should be 22 integration cards, each with a "Request Integration" button
|
|
102
|
+
const requestButtons = screen.getAllByRole('button', { name: 'Request Integration' });
|
|
103
|
+
expect(requestButtons.length).toBe(22);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('Clicking Request Integration opens mailto link with correct subject', () => {
|
|
107
|
+
setup();
|
|
108
|
+
|
|
109
|
+
const oktaButton = screen.getAllByRole('button', { name: 'Request Integration' })[0];
|
|
110
|
+
fireEvent.click(oktaButton);
|
|
111
|
+
|
|
112
|
+
expect(mockLocationHref).toContain('mailto:hello@medplum.com');
|
|
113
|
+
expect(mockLocationHref).toContain('subject=');
|
|
114
|
+
expect(decodeURIComponent(mockLocationHref)).toContain('Integration Request: Okta');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('Clicking Request Integration opens mailto link with correct body', () => {
|
|
118
|
+
setup();
|
|
119
|
+
|
|
120
|
+
const oktaButton = screen.getAllByRole('button', { name: 'Request Integration' })[0];
|
|
121
|
+
fireEvent.click(oktaButton);
|
|
122
|
+
|
|
123
|
+
const decodedHref = decodeURIComponent(mockLocationHref);
|
|
124
|
+
expect(decodedHref).toContain('Hello Medplum team');
|
|
125
|
+
expect(decodedHref).toContain('I would like to request an integration with Okta');
|
|
126
|
+
expect(decodedHref).toContain('Name: Okta');
|
|
127
|
+
expect(decodedHref).toContain(
|
|
128
|
+
'Description: Implement SSO for healthcare staff with HIPAA-compliant authentication protocols.'
|
|
129
|
+
);
|
|
130
|
+
expect(decodedHref).toContain('URL: https://www.okta.com');
|
|
131
|
+
expect(decodedHref).toContain('Thank you!');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('Clicking different integration opens mailto with correct integration details', () => {
|
|
135
|
+
setup();
|
|
136
|
+
|
|
137
|
+
// Find Health Gorilla button (should be one of the later ones)
|
|
138
|
+
const buttons = screen.getAllByRole('button', { name: 'Request Integration' });
|
|
139
|
+
const healthGorillaButton = buttons.find((button) => {
|
|
140
|
+
const card = button.closest('[class*="Paper"]');
|
|
141
|
+
return card?.textContent?.includes('Health Gorilla');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
expect(healthGorillaButton).toBeDefined();
|
|
145
|
+
|
|
146
|
+
if (healthGorillaButton) {
|
|
147
|
+
fireEvent.click(healthGorillaButton);
|
|
148
|
+
|
|
149
|
+
const decodedHref = decodeURIComponent(mockLocationHref);
|
|
150
|
+
expect(decodedHref).toContain('Integration Request: Health Gorilla');
|
|
151
|
+
expect(decodedHref).toContain('I would like to request an integration with Health Gorilla');
|
|
152
|
+
expect(decodedHref).toContain('Name: Health Gorilla');
|
|
153
|
+
expect(decodedHref).toContain('URL: https://www.healthgorilla.com');
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('Mailto link properly encodes special characters', () => {
|
|
158
|
+
setup();
|
|
159
|
+
|
|
160
|
+
// Find an integration with special characters in description
|
|
161
|
+
const buttons = screen.getAllByRole('button', { name: 'Request Integration' });
|
|
162
|
+
const microsoftButton = buttons.find((button) => {
|
|
163
|
+
const card = button.closest('[class*="Paper"]');
|
|
164
|
+
return card?.textContent?.includes('Microsoft Entra SSO');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
expect(microsoftButton).toBeDefined();
|
|
168
|
+
|
|
169
|
+
if (microsoftButton) {
|
|
170
|
+
fireEvent.click(microsoftButton);
|
|
171
|
+
|
|
172
|
+
// The URL should be properly encoded
|
|
173
|
+
expect(mockLocationHref).toContain('mailto:hello@medplum.com');
|
|
174
|
+
expect(mockLocationHref).toContain('subject=');
|
|
175
|
+
expect(mockLocationHref).toContain('body=');
|
|
176
|
+
|
|
177
|
+
// Decoded should contain the correct content
|
|
178
|
+
const decodedHref = decodeURIComponent(mockLocationHref);
|
|
179
|
+
expect(decodedHref).toContain("Integrate Microsoft's identity platform");
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test('Renders integration display URLs', () => {
|
|
184
|
+
setup();
|
|
185
|
+
|
|
186
|
+
// Check that display URLs are rendered as links
|
|
187
|
+
expect(screen.getByText('okta.com')).toBeInTheDocument();
|
|
188
|
+
expect(screen.getByText('auth0.com')).toBeInTheDocument();
|
|
189
|
+
expect(screen.getByText('labcorp.com')).toBeInTheDocument();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test('Integration links open in new tab', () => {
|
|
193
|
+
setup();
|
|
194
|
+
|
|
195
|
+
const oktaLink = screen.getByText('okta.com').closest('a');
|
|
196
|
+
expect(oktaLink).toHaveAttribute('href', 'https://www.okta.com');
|
|
197
|
+
expect(oktaLink).toHaveAttribute('target', '_blank');
|
|
198
|
+
expect(oktaLink).toHaveAttribute('rel', 'noopener noreferrer');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('Renders correct number of integrations', () => {
|
|
202
|
+
setup();
|
|
203
|
+
|
|
204
|
+
// Count unique integration names
|
|
205
|
+
const integrationNames = [
|
|
206
|
+
'Okta',
|
|
207
|
+
'Auth0',
|
|
208
|
+
'Google Authentication',
|
|
209
|
+
'Microsoft Entra SSO',
|
|
210
|
+
'Labcorp',
|
|
211
|
+
'Quest Diagnostics',
|
|
212
|
+
'Health Gorilla',
|
|
213
|
+
'Candid Health',
|
|
214
|
+
'Particle',
|
|
215
|
+
'Epic Systems',
|
|
216
|
+
'reCAPTCHA',
|
|
217
|
+
'Datadog',
|
|
218
|
+
'Sumo Logic',
|
|
219
|
+
'Snowflake',
|
|
220
|
+
'OpenAI',
|
|
221
|
+
'Stripe',
|
|
222
|
+
'Acuity Scheduling',
|
|
223
|
+
'Cal.com',
|
|
224
|
+
'Claude',
|
|
225
|
+
'DeepSeek',
|
|
226
|
+
'Azure',
|
|
227
|
+
'Healthie',
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
integrationNames.forEach((name) => {
|
|
231
|
+
expect(screen.getByText(name)).toBeInTheDocument();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
});
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Flex } from '@mantine/core';
|
|
4
|
+
import type { JSX } from 'react';
|
|
5
|
+
import { IntegrationCard } from '../../components/IntegrationCard';
|
|
6
|
+
|
|
7
|
+
interface Integration {
|
|
8
|
+
name: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
description: string;
|
|
11
|
+
displayUrl: string;
|
|
12
|
+
url: string;
|
|
13
|
+
imageUrl: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const integrations = [
|
|
17
|
+
{
|
|
18
|
+
name: 'Okta',
|
|
19
|
+
tags: ['Authentication'],
|
|
20
|
+
description: 'Implement SSO for healthcare staff with HIPAA-compliant authentication protocols.',
|
|
21
|
+
displayUrl: 'okta.com',
|
|
22
|
+
url: 'https://www.okta.com',
|
|
23
|
+
imageUrl: 'okta.png',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'Auth0',
|
|
27
|
+
tags: ['Authentication'],
|
|
28
|
+
description: 'Manage identity access for patient portals and provider applications across multiple platforms.',
|
|
29
|
+
displayUrl: 'auth0.com',
|
|
30
|
+
url: 'https://auth0.com',
|
|
31
|
+
imageUrl: 'auth0.png',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'Google Authentication',
|
|
35
|
+
tags: ['Authentication'],
|
|
36
|
+
description: "Add Google's authentication system to your EHR for standardized sign-in.",
|
|
37
|
+
displayUrl: 'cloud.google.com',
|
|
38
|
+
url: 'https://cloud.google.com/identity',
|
|
39
|
+
imageUrl: 'google.png',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'Microsoft Entra SSO',
|
|
43
|
+
tags: ['Authentication'],
|
|
44
|
+
description: "Integrate Microsoft's identity platform with clinical systems for centralized access management.",
|
|
45
|
+
displayUrl: 'microsoft.com',
|
|
46
|
+
url: 'https://learn.microsoft.com/en-us/entra/identity-platform',
|
|
47
|
+
imageUrl: 'entra.png',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'Labcorp',
|
|
51
|
+
tags: ['Diagnostics'],
|
|
52
|
+
description: 'Place orders and receive lab results directly in your EHR from Labcorp.',
|
|
53
|
+
displayUrl: 'labcorp.com',
|
|
54
|
+
url: 'https://www.labcorp.com',
|
|
55
|
+
imageUrl: 'labcorp.png',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'Quest Diagnostics',
|
|
59
|
+
tags: ['Diagnostics'],
|
|
60
|
+
description: 'Place orders and receive lab results directly in your EHR from Quest.',
|
|
61
|
+
displayUrl: 'questdiagnostics.com',
|
|
62
|
+
url: 'https://www.questdiagnostics.com',
|
|
63
|
+
imageUrl: 'quest.png',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'Health Gorilla',
|
|
67
|
+
tags: ['HIE', 'Diagnostics'],
|
|
68
|
+
description:
|
|
69
|
+
'Access nationwide clinical data networks for patient records diagnostic reports and ADT notifications.',
|
|
70
|
+
displayUrl: 'healthgorilla.com',
|
|
71
|
+
url: 'https://www.healthgorilla.com',
|
|
72
|
+
imageUrl: 'healthgorilla.png',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'Candid Health',
|
|
76
|
+
tags: ['Billing'],
|
|
77
|
+
description:
|
|
78
|
+
'Integrate automated eligibility verification and claims processing with your practice management system.',
|
|
79
|
+
displayUrl: 'candidhealth.com',
|
|
80
|
+
url: 'https://www.candidhealth.com',
|
|
81
|
+
imageUrl: 'candid.png',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'Particle',
|
|
85
|
+
tags: ['HIE'],
|
|
86
|
+
description: 'Import and export clinical data with other healthcare organizations through standardized models.',
|
|
87
|
+
displayUrl: 'particlehealth.com',
|
|
88
|
+
url: 'https://www.particlehealth.com',
|
|
89
|
+
imageUrl: 'particle.png',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'Epic Systems',
|
|
93
|
+
tags: ['EHR'],
|
|
94
|
+
description: 'Connect to your existing Epic EHR through FHIR APIs to exchange clinical data.',
|
|
95
|
+
displayUrl: 'epic.com',
|
|
96
|
+
url: 'https://www.epic.com',
|
|
97
|
+
imageUrl: 'epic.png',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'reCAPTCHA',
|
|
101
|
+
tags: ['Security'],
|
|
102
|
+
description: 'Implement bot protection for online patient registration forms while maintaining usability.',
|
|
103
|
+
displayUrl: 'google.com/recaptcha',
|
|
104
|
+
url: 'https://www.google.com/recaptcha',
|
|
105
|
+
imageUrl: 'recaptcha.png',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'Datadog',
|
|
109
|
+
tags: ['Observability'],
|
|
110
|
+
description: 'Monitor healthcare application performance to identify issues before they impact clinical workflows.',
|
|
111
|
+
displayUrl: 'datadog.com',
|
|
112
|
+
url: 'https://www.datadog.com',
|
|
113
|
+
imageUrl: 'datadog.png',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'Sumo Logic',
|
|
117
|
+
tags: ['Observability'],
|
|
118
|
+
description: 'Analyze system logs and user activities across healthcare IT systems for compliance verification.',
|
|
119
|
+
displayUrl: 'sumologic.com',
|
|
120
|
+
url: 'https://www.sumologic.com',
|
|
121
|
+
imageUrl: 'sumo.png',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'Snowflake',
|
|
125
|
+
tags: ['Data warehouse'],
|
|
126
|
+
description:
|
|
127
|
+
'Store clinical and operational data in a cloud database with access controls, allowing for analysis and reporting without managing physical servers.',
|
|
128
|
+
displayUrl: 'snowflake.com',
|
|
129
|
+
url: 'https://www.snowflake.com',
|
|
130
|
+
imageUrl: 'snowflake.png',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'OpenAI',
|
|
134
|
+
tags: ['AI'],
|
|
135
|
+
description: 'Implement AI-powered features for clinical documentation and workflow management.',
|
|
136
|
+
displayUrl: 'openai.com',
|
|
137
|
+
url: 'https://openai.com',
|
|
138
|
+
imageUrl: 'openai.png',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'Stripe',
|
|
142
|
+
tags: ['Billing'],
|
|
143
|
+
description:
|
|
144
|
+
'Send invoices, process payments, and automate reconciliation to complement your revenue cycle management.',
|
|
145
|
+
displayUrl: 'stripe.com',
|
|
146
|
+
url: 'https://stripe.com',
|
|
147
|
+
imageUrl: 'stripe.png',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: 'Acuity Scheduling',
|
|
151
|
+
tags: ['Scheduling'],
|
|
152
|
+
description: 'Manage your clinical availability and appointments with comprehensive scheduling tools.',
|
|
153
|
+
displayUrl: 'acuityscheduling.com',
|
|
154
|
+
url: 'https://www.acuityscheduling.com',
|
|
155
|
+
imageUrl: 'acuity.png',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'Cal.com',
|
|
159
|
+
tags: ['Scheduling'],
|
|
160
|
+
description: 'Open source scheduling platform for managing availability and appointments.',
|
|
161
|
+
displayUrl: 'cal.com',
|
|
162
|
+
url: 'https://cal.com',
|
|
163
|
+
imageUrl: 'calcom.png',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'Claude',
|
|
167
|
+
tags: ['AI'],
|
|
168
|
+
description: 'Implement AI-powered features for clinical documentation and workflow management.',
|
|
169
|
+
displayUrl: 'anthropic.com/claude',
|
|
170
|
+
url: 'https://www.anthropic.com/claude',
|
|
171
|
+
imageUrl: 'claude.png',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: 'DeepSeek',
|
|
175
|
+
tags: ['AI'],
|
|
176
|
+
description: 'Implement AI-powered features for clinical documentation and workflow management.',
|
|
177
|
+
displayUrl: 'deepseek.com',
|
|
178
|
+
url: 'https://www.deepseek.com',
|
|
179
|
+
imageUrl: 'deepseek.png',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: 'Azure',
|
|
183
|
+
tags: ['Cloud Services'],
|
|
184
|
+
description: 'Deploy HIPAA-compliant applications with specialized services for protected health information.',
|
|
185
|
+
displayUrl: 'azure.microsoft.com',
|
|
186
|
+
url: 'https://azure.microsoft.com',
|
|
187
|
+
imageUrl: 'azure.png',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
name: 'Healthie',
|
|
191
|
+
tags: ['EHR', 'Practice Management'],
|
|
192
|
+
description: 'Connect to your existing Healthie account to exchange clinical data.',
|
|
193
|
+
displayUrl: 'gethealthie.com',
|
|
194
|
+
url: 'https://gethealthie.com',
|
|
195
|
+
imageUrl: 'healthie.png',
|
|
196
|
+
},
|
|
197
|
+
];
|
|
198
|
+
|
|
199
|
+
export function IntegrationsPage(): JSX.Element {
|
|
200
|
+
function requestIntegration(integration: Integration): void {
|
|
201
|
+
const subject = `Integration Request: ${integration.name}`;
|
|
202
|
+
const body = `Hello Medplum team,\n\nI would like to request an integration with ${integration.name}.\n\nHere are the details:\n\nName: ${integration.name}\nDescription: ${integration.description}\nURL: ${integration.url}\n\nThank you!`;
|
|
203
|
+
window.location.href = `mailto:hello@medplum.com?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<Flex mih={50} gap="md" justify="center" align="flex-end" direction="row" wrap="wrap" m="xl">
|
|
208
|
+
{integrations.map((i) => (
|
|
209
|
+
<IntegrationCard
|
|
210
|
+
key={i.name}
|
|
211
|
+
name={i.name}
|
|
212
|
+
displayUrl={i.displayUrl}
|
|
213
|
+
url={i.url}
|
|
214
|
+
tags={i.tags}
|
|
215
|
+
description={i.description}
|
|
216
|
+
imageUrl={`/img/integrations/${i.imageUrl}`}
|
|
217
|
+
onClick={() => requestIntegration(i)}
|
|
218
|
+
/>
|
|
219
|
+
))}
|
|
220
|
+
</Flex>
|
|
221
|
+
);
|
|
222
|
+
}
|