@medplum/dosespot-react 5.1.5 → 5.1.6
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/dist/cjs/index.cjs.map +2 -2
- package/dist/esm/index.mjs.map +2 -2
- package/package.json +12 -12
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts", "../../../dosespot-core/src/pharmacy-utils.ts", "../../src/useDoseSpotClinicFormulary.ts", "../../src/useDoseSpotIFrame.ts", "../../src/useDoseSpotNotifications.ts", "../../src/useDoseSpotPatientPharmacy.ts", "../../src/utils.ts", "../../src/useDoseSpotPharmacySearch.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nexport * from './common';\nexport * from './useDoseSpotClinicFormulary';\nexport * from './useDoseSpotIFrame';\nexport * from './useDoseSpotNotifications';\nexport * from './useDoseSpotPatientPharmacy';\nexport * from './useDoseSpotPharmacySearch';\nexport * from './utils';\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Identifier } from '@medplum/fhirtypes';\n\n// DoseSpot-specific pharmacy preference type system\nexport const DOSESPOT_PHARMACY_PREFERENCE_TYPE_SYSTEM = 'https://dosespot.com/pharmacy-preference-type';\n\n// Re-export generic pharmacy utilities from @medplum/core\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams, PreferredPharmacy } from '@medplum/core';\n\n// Bot system\nexport const MEDPLUM_BOT_SYSTEM = 'https://www.medplum.com/bots';\n\n// DoseSpot identifier systems\nexport const DOSESPOT_PATIENT_ID_SYSTEM = 'https://dosespot.com/patient-id';\nexport const DOSESPOT_PHARMACY_ID_SYSTEM = 'https://dosespot.com/pharmacy-id';\nexport const DOSESPOT_CLINIC_FAVORITE_ID_SYSTEM = 'https://dosespot.com/clinic-favorite-medication-id';\nexport const DOSESPOT_DISPENSABLE_DRUG_ID_SYSTEM = 'https://dosespot.com/dispensable-drug-id';\n\n// Bot identifiers - Pharmacy\nexport const DOSESPOT_SEARCH_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-pharmacy-bot',\n};\n\nexport const DOSESPOT_ADD_PATIENT_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-patient-pharmacy-bot',\n};\n\n// Bot identifiers - Patient and Medications\nexport const DOSESPOT_PATIENT_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-patient-sync-bot',\n};\n\nexport const DOSESPOT_IFRAME_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-iframe-bot',\n};\n\nexport const DOSESPOT_ADD_FAVORITE_MEDICATION_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-favorite-medication-bot',\n};\n\nexport const DOSESPOT_GET_FAVORITE_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-get-favorite-medications-bot',\n};\n\nexport const DOSESPOT_SEARCH_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-medication-bot',\n};\n\nexport const DOSESPOT_MEDICATION_HISTORY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-medication-history-bot',\n};\n\nexport const DOSESPOT_PRESCRIPTIONS_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-prescriptions-sync-bot',\n};\n\nexport const DOSESPOT_NOTIFICATION_COUNTS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-notification-counts-bot',\n};\n\n// DoseSpot notification response type\nexport interface DoseSpotNotificationCountsResponse {\n PendingPrescriptionsCount: number;\n PendingRxChangeCount: number;\n RefillRequestsCount: number;\n TransactionErrorsCount: number;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { isCodeableConcept, isCoding } from '@medplum/core';\nimport type { CodeableConcept, Coding, MedicationKnowledge } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, DOSESPOT_SEARCH_MEDICATIONS_BOT } from './common';\n\nexport interface DoseSpotClinicFormularyReturn {\n state: DoseSpotClinicFormularyState;\n /**\n * Search for DoseSpot Medications and returns array of temporary MedicationKnowledge objects that are not yet saved to the FHIR server\n */\n readonly searchMedications: (searchTerm: string) => Promise<CodeableConcept[]>;\n /**\n * Set the currently selected medication. Can be set as a CodeableConcept or a Coding, but state is always stored as a CodeableConcept\n */\n readonly setSelectedMedication: (medication: CodeableConcept | Coding | undefined) => void;\n /**\n * Set the directions for the currently selected medication\n */\n readonly setSelectedMedicationDirections: (directions: string | undefined) => void;\n /**\n * Save a DoseSpot Medication to the Clinic's favorites and returns the MedicationKnowledge object that was saved\n */\n readonly saveFavoriteMedication: () => Promise<MedicationKnowledge>;\n /**\n * Clear the state\n */\n readonly clear: () => void;\n}\n\nexport interface DoseSpotClinicFormularyState {\n selectedMedication: CodeableConcept | undefined;\n directions: string | undefined;\n}\n\nexport function useDoseSpotClinicFormulary(): DoseSpotClinicFormularyReturn {\n const [directions, privateSetDirections] = useState<string | undefined>(undefined);\n const [selectedMedication, privateSetSelectedMedication] = useState<CodeableConcept | undefined>(undefined);\n const medplum = useMedplum();\n\n const state: DoseSpotClinicFormularyState = { selectedMedication, directions };\n\n const saveFavoriteMedication = useCallback(async (): Promise<MedicationKnowledge> => {\n if (!selectedMedication) {\n throw new Error('Must select a medication before adding a favorite medication');\n }\n\n //Add the directions to the medicationKnowledge object\n const medicationKnowledgeWithDirections = {\n resourceType: 'MedicationKnowledge',\n code: { ...selectedMedication },\n administrationGuidelines: [\n {\n dosage: [\n {\n dosage: [\n {\n patientInstruction: directions || '',\n },\n ],\n type: {\n coding: [\n {\n system: 'https://dosespot.com/patient-instructions',\n },\n ],\n },\n },\n ],\n },\n ],\n };\n\n return medplum.executeBot(DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, medicationKnowledgeWithDirections);\n }, [selectedMedication, directions, medplum]);\n\n const searchMedications = useCallback(\n async (searchTerm: string): Promise<CodeableConcept[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_MEDICATIONS_BOT, { name: searchTerm })) as CodeableConcept[];\n },\n [medplum]\n );\n\n const setSelectedMedicationDirections = (directions: string | undefined): void => {\n privateSetDirections(directions);\n };\n\n const setSelectedMedication = (medication: CodeableConcept | Coding | undefined): void => {\n let medicationToSet: CodeableConcept | undefined;\n if (isCodeableConcept(medication)) {\n medicationToSet = { ...medication };\n } else if (isCoding(medication)) {\n medicationToSet = {\n text: medication.display || '',\n coding: [medication],\n };\n }\n privateSetSelectedMedication(medicationToSet);\n };\n\n const clear = (): void => {\n privateSetSelectedMedication(undefined);\n privateSetDirections(undefined);\n };\n\n return {\n state,\n searchMedications,\n setSelectedMedication,\n setSelectedMedicationDirections,\n saveFavoriteMedication,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { DOSESPOT_IFRAME_BOT, DOSESPOT_PATIENT_SYNC_BOT } from './common';\n\nexport interface DoseSpotIFrameOptions {\n readonly patientId?: string;\n readonly onPatientSyncSuccess?: () => void;\n readonly onIframeSuccess?: (url: string) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nexport function useDoseSpotIFrame(options: DoseSpotIFrameOptions): string | undefined {\n const medplum = useMedplum();\n const { patientId, onPatientSyncSuccess, onIframeSuccess, onError } = options;\n const initializingRef = useRef<boolean>(false);\n const [iframeUrl, setIframeUrl] = useState<string | undefined>(undefined);\n\n const onPatientSyncSuccessRef = useRef(onPatientSyncSuccess);\n onPatientSyncSuccessRef.current = onPatientSyncSuccess;\n\n const onIframeSuccessRef = useRef(onIframeSuccess);\n onIframeSuccessRef.current = onIframeSuccess;\n\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n // Reset when inputs change so we re-fetch the iframe URL\n useEffect(() => {\n initializingRef.current = false;\n }, [patientId]);\n\n const initPage = useCallback(async () => {\n if (initializingRef.current) {\n return;\n }\n\n initializingRef.current = true;\n try {\n if (patientId) {\n await medplum.executeBot(DOSESPOT_PATIENT_SYNC_BOT, { patientId });\n onPatientSyncSuccessRef.current?.();\n }\n const result = await medplum.executeBot(DOSESPOT_IFRAME_BOT, { patientId });\n if (result.url) {\n setIframeUrl(result.url);\n onIframeSuccessRef.current?.(result.url);\n }\n } catch (err: unknown) {\n onErrorRef.current?.(err);\n }\n }, [medplum, patientId]);\n\n useEffect(() => {\n initPage().catch(console.error);\n }, [initPage]);\n\n return iframeUrl;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DoseSpotNotificationCountsResponse } from './common';\nimport { DOSESPOT_NOTIFICATION_COUNTS_BOT } from './common';\n\nexport interface DoseSpotNotificationsOptions {\n readonly refreshIntervalMilliseconds?: number;\n readonly onChange?: (count: number) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nconst DEFAULT_REFRESH_INTERVAL_MILLISECONDS = 10000;\n\nexport function useDoseSpotNotifications(options?: DoseSpotNotificationsOptions): number | undefined {\n const medplum = useMedplum();\n const { onChange, onError } = options ?? {};\n const hasDoseSpot = medplum.getProjectMembership()?.identifier?.some((i) => i.system?.includes('dosespot'));\n const refreshInterval = options?.refreshIntervalMilliseconds ?? DEFAULT_REFRESH_INTERVAL_MILLISECONDS;\n const timerRef = useRef<NodeJS.Timeout | undefined>(undefined);\n const [unreadCount, setUnreadCount] = useState<number | undefined>(undefined);\n\n const stopTimer = useCallback(() => {\n const timerId = timerRef.current;\n if (timerId) {\n clearInterval(timerId);\n }\n }, []);\n\n const updateCount = useCallback(async () => {\n try {\n const result = (await medplum.executeBot(\n DOSESPOT_NOTIFICATION_COUNTS_BOT,\n {}\n )) as DoseSpotNotificationCountsResponse;\n\n let newCount = 0;\n if (result.PendingPrescriptionsCount) {\n newCount += result.PendingPrescriptionsCount;\n }\n if (result.PendingRxChangeCount) {\n newCount += result.PendingRxChangeCount;\n }\n if (result.RefillRequestsCount) {\n newCount += result.RefillRequestsCount;\n }\n if (result.TransactionErrorsCount) {\n newCount += result.TransactionErrorsCount;\n }\n if (newCount !== unreadCount) {\n setUnreadCount(newCount);\n onChange?.(newCount);\n }\n } catch (err: unknown) {\n onError?.(err);\n stopTimer();\n }\n }, [medplum, unreadCount, onChange, onError, stopTimer]);\n\n const startTimer = useCallback(() => {\n timerRef.current = setInterval(() => {\n updateCount().catch(console.error);\n }, refreshInterval);\n }, [updateCount, refreshInterval]);\n\n useEffect(() => {\n // Start an interval timer to update the count every 5 seconds\n if (hasDoseSpot) {\n startTimer();\n }\n\n // Clear the interval timer when the component is unmounted\n return stopTimer;\n }, [hasDoseSpot, startTimer, stopTimer]);\n\n return unreadCount;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\nimport { getPharmacyIdFromOrganization } from './utils';\n\n/**\n * Search parameters for pharmacy search.\n * See DoseSpot API section 3.13.2.\n */\nexport interface PharmacySearchParams {\n /** Pharmacy's store name (min 3 chars) */\n name?: string;\n /** City (min 3 chars) */\n city?: string;\n /** State (min 3 chars) */\n state?: string;\n /** Zip code (min 3 chars) */\n zip?: string;\n /** Address (min 3 chars) */\n address?: string;\n /** Phone or fax number */\n phoneOrFax?: string;\n /** Collection of pharmacy specialties (numeric values) */\n specialty?: number[];\n /** National Council for Prescription Drug Programs Identifier */\n ncpdpID?: string;\n /** Page number of results (defaults to 1) */\n pageNumber?: number;\n}\n\n/**\n * Response from adding a pharmacy to a patient's favorites.\n */\nexport interface AddPatientPharmacyResponse {\n /** Whether the operation was successful */\n success: boolean;\n /** A message describing the result */\n message: string;\n /** The persisted Organization resource with ID */\n organization?: Organization;\n}\n\n/**\n * State managed by the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyState {\n /** The currently selected pharmacy Organization */\n selectedPharmacy: Organization | undefined;\n /** Whether to set the selected pharmacy as the patient's primary pharmacy */\n setAsPrimary: boolean;\n}\n\n/**\n * Return type for the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyReturn {\n /** Current state of the hook */\n state: DoseSpotPatientPharmacyState;\n /**\n * Search for pharmacies in DoseSpot.\n * Returns synthetic Organization resources (not persisted to DB).\n */\n readonly searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n /**\n * Set the currently selected pharmacy.\n */\n readonly setSelectedPharmacy: (pharmacy: Organization | undefined) => void;\n /**\n * Set whether to add the pharmacy as the patient's primary pharmacy.\n */\n readonly setAsPrimary: (primary: boolean) => void;\n /**\n * Add the selected pharmacy to the patient's favorites in DoseSpot.\n * @param patientId - The Medplum Patient ID\n */\n readonly addFavoritePharmacy: (patientId: string) => Promise<AddPatientPharmacyResponse>;\n /**\n * Clear the state (selected pharmacy and setAsPrimary flag).\n */\n readonly clear: () => void;\n}\n\n/**\n * React hook for searching DoseSpot pharmacies and adding them to patient favorites.\n *\n * @returns The hook return object with state and methods.\n *\n * @example\n * ```tsx\n * function PharmacySearch({ patientId }: { patientId: string }) {\n * const {\n * state,\n * searchPharmacies,\n * setSelectedPharmacy,\n * setAsPrimary,\n * addFavoritePharmacy,\n * clear\n * } = useDoseSpotPatientPharmacy();\n *\n * const handleSearch = async () => {\n * const results = await searchPharmacies({ zip: '94118' });\n * // Display results to user\n * };\n *\n * const handleAddFavorite = async () => {\n * const result = await addFavoritePharmacy(patientId);\n * if (result.success) {\n * clear();\n * }\n * };\n * }\n * ```\n */\nexport function useDoseSpotPatientPharmacy(): DoseSpotPatientPharmacyReturn {\n const [selectedPharmacy, privateSetSelectedPharmacy] = useState<Organization | undefined>(undefined);\n const [setAsPrimaryState, privateSetAsPrimary] = useState<boolean>(false);\n const medplum = useMedplum();\n\n const state: DoseSpotPatientPharmacyState = {\n selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n };\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params)) as Organization[];\n },\n [medplum]\n );\n\n const setSelectedPharmacy = (pharmacy: Organization | undefined): void => {\n privateSetSelectedPharmacy(pharmacy);\n };\n\n const setAsPrimary = (primary: boolean): void => {\n privateSetAsPrimary(primary);\n };\n\n const addFavoritePharmacy = useCallback(\n async (patientId: string): Promise<AddPatientPharmacyResponse> => {\n if (!selectedPharmacy) {\n throw new Error('Must select a pharmacy before adding it as a favorite');\n }\n\n const pharmacyId = getPharmacyIdFromOrganization(selectedPharmacy);\n if (!pharmacyId) {\n throw new Error('Selected pharmacy does not have a valid DoseSpot pharmacy ID');\n }\n\n return medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId,\n pharmacy: selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n }) as Promise<AddPatientPharmacyResponse>;\n },\n [selectedPharmacy, setAsPrimaryState, medplum]\n );\n\n const clear = (): void => {\n privateSetSelectedPharmacy(undefined);\n privateSetAsPrimary(false);\n };\n\n return {\n state,\n searchPharmacies,\n setSelectedPharmacy,\n setAsPrimary,\n addFavoritePharmacy,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { MedicationKnowledge, Organization } from '@medplum/fhirtypes';\nimport { DOSESPOT_PHARMACY_ID_SYSTEM } from './common';\n\nexport const getMedicationName = (medication: MedicationKnowledge | undefined): string => {\n return medication?.code?.text || '';\n};\n\n/**\n * Extracts the DoseSpot pharmacy ID from an Organization resource.\n * @param organization - The FHIR Organization resource representing a pharmacy.\n * @returns The DoseSpot pharmacy ID, or undefined if not found.\n */\nexport function getPharmacyIdFromOrganization(organization: Organization): number | undefined {\n const id = organization.identifier?.find((i) => i.system === DOSESPOT_PHARMACY_ID_SYSTEM)?.value;\n return id ? Number.parseInt(id, 10) : undefined;\n}\n\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { PreferredPharmacy } from '@medplum/core';\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams } from '@medplum/core';\nimport { isAddPharmacyResponse, isOrganizationArray } from '@medplum/core';\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\n\nexport interface UseDoseSpotPharmacySearchReturn {\n searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n addToFavorites: (params: AddFavoriteParams) => Promise<AddPharmacyResponse>;\n}\n\n/**\n * React hook that provides DoseSpot-specific pharmacy search and add-to-favorites functionality.\n *\n * This hook encapsulates calls to the DoseSpot pharmacy search and add patient pharmacy bots,\n * and can be composed with the generic `PharmacyDialog` component from `@medplum/react`.\n *\n * @returns An object with `searchPharmacies` and `addToFavorites` callbacks.\n */\nexport function useDoseSpotPharmacySearch(): UseDoseSpotPharmacySearchReturn {\n const medplum = useMedplum();\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n const response = await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params);\n\n if (!isOrganizationArray(response)) {\n throw new Error('Invalid response from pharmacy search');\n }\n\n return response;\n },\n [medplum]\n );\n\n const addToFavorites = useCallback(\n async (params: AddFavoriteParams): Promise<AddPharmacyResponse> => {\n const response = await medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId: params.patientId,\n pharmacy: params.pharmacy,\n setAsPrimary: params.setAsPrimary,\n });\n\n if (!isAddPharmacyResponse(response)) {\n throw new Error('Invalid response from add pharmacy bot');\n }\n\n return response;\n },\n [medplum]\n );\n\n return { searchPharmacies, addToFavorites };\n}\n"],
|
|
5
|
-
"mappings": "wpBAAA,4nECSA,gBAWO,yBAdA,IAkBM,mBAAqB,+BAGrB,2BAA6B,kCAC7B,4BAA8B,mCAC9B,mCAAqC,qDACrC,oCAAsC,2CAGtC,6BAA2C,CACtD,OAAQ,mBACR,MAAO,8BACT,EAEa,kCAAgD,CAC3D,OAAQ,mBACR,MAAO,mCACT,EAGa,0BAAwC,CACnD,OAAQ,mBACR,MAAO,2BACT,EAEa,oBAAkC,CAC7C,OAAQ,mBACR,MAAO,qBACT,EAEa,qCAAmD,CAC9D,OAAQ,mBACR,MAAO,sCACT,EAEa,sCAAoD,CAC/D,OAAQ,mBACR,MAAO,uCACT,EAEa,gCAA8C,CACzD,OAAQ,mBACR,MAAO,gCACT,EAEa,gCAA8C,CACzD,OAAQ,mBACR,MAAO,iCACT,EAEa,gCAA8C,CACzD,OAAQ,mBACR,MAAO,iCACT,EAEa,iCAA+C,CAC1D,OAAQ,mBACR,MAAO,kCACT,EChFA,IAAAA,aAA4C,yBAE5C,mBAA2B,gCAC3B,aAAsC,iBAgC/B,SAAS,4BAA4D,CAC1E,GAAM,CAAC,WAAY,oBAAoB,KAAI,uBAA6B,MAAS,EAC3E,CAAC,mBAAoB,4BAA4B,KAAI,uBAAsC,MAAS,EACpG,WAAU,+BAAW,EAErB,MAAsC,CAAE,mBAAoB,UAAW,EAEvE,0BAAyB,0BAAY,SAA0C,CACnF,GAAI,CAAC,mBACH,MAAM,IAAI,MAAM,8DAA8D,EAIhF,IAAM,kCAAoC,CACxC,aAAc,sBACd,KAAM,CAAE,GAAG,kBAAmB,EAC9B,yBAA0B,CACxB,CACE,OAAQ,CACN,CACE,OAAQ,CACN,CACE,mBAAoB,YAAc,EACpC,CACF,EACA,KAAM,CACJ,OAAQ,CACN,CACE,OAAQ,2CACV,CACF,CACF,CACF,CACF,CACF,CACF,CACF,EAEA,OAAO,QAAQ,WAAW,qCAAsC,iCAAiC,CACnG,EAAG,CAAC,mBAAoB,WAAY,OAAO,CAAC,EAEtC,qBAAoB,0BACxB,MAAO,YACG,MAAM,QAAQ,WAAW,gCAAiC,CAAE,KAAM,UAAW,CAAC,EAExF,CAAC,OAAO,CACV,EAwBA,MAAO,CACL,MACA,kBACA,sBArB6B,YAA2D,CACxF,IAAI,mBACA,gCAAkB,UAAU,EAC9B,gBAAkB,CAAE,GAAG,UAAW,KACzB,uBAAS,UAAU,IAC5B,gBAAkB,CAChB,KAAM,WAAW,SAAW,GAC5B,OAAQ,CAAC,UAAU,CACrB,GAEF,6BAA6B,eAAe,CAC9C,EAWE,gCA1BuCC,aAAyC,CAChF,qBAAqBA,WAAU,CACjC,EAyBE,uBACA,MAXY,IAAY,CACxB,6BAA6B,MAAS,EACtC,qBAAqB,MAAS,CAChC,CASA,CACF,CCjHA,IAAAC,oBAA2B,gCAC3BC,cAAyD,iBAUlD,SAAS,kBAAkB,QAAoD,CACpF,IAAM,WAAU,gCAAW,EACrB,CAAE,UAAW,qBAAsB,gBAAiB,OAAQ,EAAI,QAChE,mBAAkB,
|
|
4
|
+
"sourcesContent": ["// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nexport * from './common';\nexport * from './useDoseSpotClinicFormulary';\nexport * from './useDoseSpotIFrame';\nexport * from './useDoseSpotNotifications';\nexport * from './useDoseSpotPatientPharmacy';\nexport * from './useDoseSpotPharmacySearch';\nexport * from './utils';\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Identifier } from '@medplum/fhirtypes';\n\n// DoseSpot-specific pharmacy preference type system\nexport const DOSESPOT_PHARMACY_PREFERENCE_TYPE_SYSTEM = 'https://dosespot.com/pharmacy-preference-type';\n\n// Re-export generic pharmacy utilities from @medplum/core\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams, PreferredPharmacy } from '@medplum/core';\n\n// Bot system\nexport const MEDPLUM_BOT_SYSTEM = 'https://www.medplum.com/bots';\n\n// DoseSpot identifier systems\nexport const DOSESPOT_PATIENT_ID_SYSTEM = 'https://dosespot.com/patient-id';\nexport const DOSESPOT_PHARMACY_ID_SYSTEM = 'https://dosespot.com/pharmacy-id';\nexport const DOSESPOT_CLINIC_FAVORITE_ID_SYSTEM = 'https://dosespot.com/clinic-favorite-medication-id';\nexport const DOSESPOT_DISPENSABLE_DRUG_ID_SYSTEM = 'https://dosespot.com/dispensable-drug-id';\n\n// Bot identifiers - Pharmacy\nexport const DOSESPOT_SEARCH_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-pharmacy-bot',\n};\n\nexport const DOSESPOT_ADD_PATIENT_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-patient-pharmacy-bot',\n};\n\n// Bot identifiers - Patient and Medications\nexport const DOSESPOT_PATIENT_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-patient-sync-bot',\n};\n\nexport const DOSESPOT_IFRAME_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-iframe-bot',\n};\n\nexport const DOSESPOT_ADD_FAVORITE_MEDICATION_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-favorite-medication-bot',\n};\n\nexport const DOSESPOT_GET_FAVORITE_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-get-favorite-medications-bot',\n};\n\nexport const DOSESPOT_SEARCH_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-medication-bot',\n};\n\nexport const DOSESPOT_MEDICATION_HISTORY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-medication-history-bot',\n};\n\nexport const DOSESPOT_PRESCRIPTIONS_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-prescriptions-sync-bot',\n};\n\nexport const DOSESPOT_NOTIFICATION_COUNTS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-notification-counts-bot',\n};\n\n// DoseSpot notification response type\nexport interface DoseSpotNotificationCountsResponse {\n PendingPrescriptionsCount: number;\n PendingRxChangeCount: number;\n RefillRequestsCount: number;\n TransactionErrorsCount: number;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { isCodeableConcept, isCoding } from '@medplum/core';\nimport type { CodeableConcept, Coding, MedicationKnowledge } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, DOSESPOT_SEARCH_MEDICATIONS_BOT } from './common';\n\nexport interface DoseSpotClinicFormularyReturn {\n state: DoseSpotClinicFormularyState;\n /**\n * Search for DoseSpot Medications and returns array of temporary MedicationKnowledge objects that are not yet saved to the FHIR server\n */\n readonly searchMedications: (searchTerm: string) => Promise<CodeableConcept[]>;\n /**\n * Set the currently selected medication. Can be set as a CodeableConcept or a Coding, but state is always stored as a CodeableConcept\n */\n readonly setSelectedMedication: (medication: CodeableConcept | Coding | undefined) => void;\n /**\n * Set the directions for the currently selected medication\n */\n readonly setSelectedMedicationDirections: (directions: string | undefined) => void;\n /**\n * Save a DoseSpot Medication to the Clinic's favorites and returns the MedicationKnowledge object that was saved\n */\n readonly saveFavoriteMedication: () => Promise<MedicationKnowledge>;\n /**\n * Clear the state\n */\n readonly clear: () => void;\n}\n\nexport interface DoseSpotClinicFormularyState {\n selectedMedication: CodeableConcept | undefined;\n directions: string | undefined;\n}\n\nexport function useDoseSpotClinicFormulary(): DoseSpotClinicFormularyReturn {\n const [directions, privateSetDirections] = useState<string | undefined>(undefined);\n const [selectedMedication, privateSetSelectedMedication] = useState<CodeableConcept | undefined>(undefined);\n const medplum = useMedplum();\n\n const state: DoseSpotClinicFormularyState = { selectedMedication, directions };\n\n const saveFavoriteMedication = useCallback(async (): Promise<MedicationKnowledge> => {\n if (!selectedMedication) {\n throw new Error('Must select a medication before adding a favorite medication');\n }\n\n //Add the directions to the medicationKnowledge object\n const medicationKnowledgeWithDirections = {\n resourceType: 'MedicationKnowledge',\n code: { ...selectedMedication },\n administrationGuidelines: [\n {\n dosage: [\n {\n dosage: [\n {\n patientInstruction: directions || '',\n },\n ],\n type: {\n coding: [\n {\n system: 'https://dosespot.com/patient-instructions',\n },\n ],\n },\n },\n ],\n },\n ],\n };\n\n return medplum.executeBot(DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, medicationKnowledgeWithDirections);\n }, [selectedMedication, directions, medplum]);\n\n const searchMedications = useCallback(\n async (searchTerm: string): Promise<CodeableConcept[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_MEDICATIONS_BOT, { name: searchTerm })) as CodeableConcept[];\n },\n [medplum]\n );\n\n const setSelectedMedicationDirections = (directions: string | undefined): void => {\n privateSetDirections(directions);\n };\n\n const setSelectedMedication = (medication: CodeableConcept | Coding | undefined): void => {\n let medicationToSet: CodeableConcept | undefined;\n if (isCodeableConcept(medication)) {\n medicationToSet = { ...medication };\n } else if (isCoding(medication)) {\n medicationToSet = {\n text: medication.display || '',\n coding: [medication],\n };\n }\n privateSetSelectedMedication(medicationToSet);\n };\n\n const clear = (): void => {\n privateSetSelectedMedication(undefined);\n privateSetDirections(undefined);\n };\n\n return {\n state,\n searchMedications,\n setSelectedMedication,\n setSelectedMedicationDirections,\n saveFavoriteMedication,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { DOSESPOT_IFRAME_BOT, DOSESPOT_PATIENT_SYNC_BOT } from './common';\n\nexport interface DoseSpotIFrameOptions {\n readonly patientId?: string;\n readonly onPatientSyncSuccess?: () => void;\n readonly onIframeSuccess?: (url: string) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nexport function useDoseSpotIFrame(options: DoseSpotIFrameOptions): string | undefined {\n const medplum = useMedplum();\n const { patientId, onPatientSyncSuccess, onIframeSuccess, onError } = options;\n const initializingRef = useRef(false);\n const [iframeUrl, setIframeUrl] = useState<string | undefined>(undefined);\n\n const onPatientSyncSuccessRef = useRef(onPatientSyncSuccess);\n onPatientSyncSuccessRef.current = onPatientSyncSuccess;\n\n const onIframeSuccessRef = useRef(onIframeSuccess);\n onIframeSuccessRef.current = onIframeSuccess;\n\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n // Reset when inputs change so we re-fetch the iframe URL\n useEffect(() => {\n initializingRef.current = false;\n }, [patientId]);\n\n const initPage = useCallback(async () => {\n if (initializingRef.current) {\n return;\n }\n\n initializingRef.current = true;\n try {\n if (patientId) {\n await medplum.executeBot(DOSESPOT_PATIENT_SYNC_BOT, { patientId });\n onPatientSyncSuccessRef.current?.();\n }\n const result = await medplum.executeBot(DOSESPOT_IFRAME_BOT, { patientId });\n if (result.url) {\n setIframeUrl(result.url);\n onIframeSuccessRef.current?.(result.url);\n }\n } catch (err: unknown) {\n onErrorRef.current?.(err);\n }\n }, [medplum, patientId]);\n\n useEffect(() => {\n initPage().catch(console.error);\n }, [initPage]);\n\n return iframeUrl;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DoseSpotNotificationCountsResponse } from './common';\nimport { DOSESPOT_NOTIFICATION_COUNTS_BOT } from './common';\n\nexport interface DoseSpotNotificationsOptions {\n readonly refreshIntervalMilliseconds?: number;\n readonly onChange?: (count: number) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nconst DEFAULT_REFRESH_INTERVAL_MILLISECONDS = 10000;\n\nexport function useDoseSpotNotifications(options?: DoseSpotNotificationsOptions): number | undefined {\n const medplum = useMedplum();\n const { onChange, onError } = options ?? {};\n const hasDoseSpot = medplum.getProjectMembership()?.identifier?.some((i) => i.system?.includes('dosespot'));\n const refreshInterval = options?.refreshIntervalMilliseconds ?? DEFAULT_REFRESH_INTERVAL_MILLISECONDS;\n const timerRef = useRef<NodeJS.Timeout | undefined>(undefined);\n const [unreadCount, setUnreadCount] = useState<number | undefined>(undefined);\n\n const stopTimer = useCallback(() => {\n const timerId = timerRef.current;\n if (timerId) {\n clearInterval(timerId);\n }\n }, []);\n\n const updateCount = useCallback(async () => {\n try {\n const result = (await medplum.executeBot(\n DOSESPOT_NOTIFICATION_COUNTS_BOT,\n {}\n )) as DoseSpotNotificationCountsResponse;\n\n let newCount = 0;\n if (result.PendingPrescriptionsCount) {\n newCount += result.PendingPrescriptionsCount;\n }\n if (result.PendingRxChangeCount) {\n newCount += result.PendingRxChangeCount;\n }\n if (result.RefillRequestsCount) {\n newCount += result.RefillRequestsCount;\n }\n if (result.TransactionErrorsCount) {\n newCount += result.TransactionErrorsCount;\n }\n if (newCount !== unreadCount) {\n setUnreadCount(newCount);\n onChange?.(newCount);\n }\n } catch (err: unknown) {\n onError?.(err);\n stopTimer();\n }\n }, [medplum, unreadCount, onChange, onError, stopTimer]);\n\n const startTimer = useCallback(() => {\n timerRef.current = setInterval(() => {\n updateCount().catch(console.error);\n }, refreshInterval);\n }, [updateCount, refreshInterval]);\n\n useEffect(() => {\n // Start an interval timer to update the count every 5 seconds\n if (hasDoseSpot) {\n startTimer();\n }\n\n // Clear the interval timer when the component is unmounted\n return stopTimer;\n }, [hasDoseSpot, startTimer, stopTimer]);\n\n return unreadCount;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\nimport { getPharmacyIdFromOrganization } from './utils';\n\n/**\n * Search parameters for pharmacy search.\n * See DoseSpot API section 3.13.2.\n */\nexport interface PharmacySearchParams {\n /** Pharmacy's store name (min 3 chars) */\n name?: string;\n /** City (min 3 chars) */\n city?: string;\n /** State (min 3 chars) */\n state?: string;\n /** Zip code (min 3 chars) */\n zip?: string;\n /** Address (min 3 chars) */\n address?: string;\n /** Phone or fax number */\n phoneOrFax?: string;\n /** Collection of pharmacy specialties (numeric values) */\n specialty?: number[];\n /** National Council for Prescription Drug Programs Identifier */\n ncpdpID?: string;\n /** Page number of results (defaults to 1) */\n pageNumber?: number;\n}\n\n/**\n * Response from adding a pharmacy to a patient's favorites.\n */\nexport interface AddPatientPharmacyResponse {\n /** Whether the operation was successful */\n success: boolean;\n /** A message describing the result */\n message: string;\n /** The persisted Organization resource with ID */\n organization?: Organization;\n}\n\n/**\n * State managed by the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyState {\n /** The currently selected pharmacy Organization */\n selectedPharmacy: Organization | undefined;\n /** Whether to set the selected pharmacy as the patient's primary pharmacy */\n setAsPrimary: boolean;\n}\n\n/**\n * Return type for the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyReturn {\n /** Current state of the hook */\n state: DoseSpotPatientPharmacyState;\n /**\n * Search for pharmacies in DoseSpot.\n * Returns synthetic Organization resources (not persisted to DB).\n */\n readonly searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n /**\n * Set the currently selected pharmacy.\n */\n readonly setSelectedPharmacy: (pharmacy: Organization | undefined) => void;\n /**\n * Set whether to add the pharmacy as the patient's primary pharmacy.\n */\n readonly setAsPrimary: (primary: boolean) => void;\n /**\n * Add the selected pharmacy to the patient's favorites in DoseSpot.\n * @param patientId - The Medplum Patient ID\n */\n readonly addFavoritePharmacy: (patientId: string) => Promise<AddPatientPharmacyResponse>;\n /**\n * Clear the state (selected pharmacy and setAsPrimary flag).\n */\n readonly clear: () => void;\n}\n\n/**\n * React hook for searching DoseSpot pharmacies and adding them to patient favorites.\n *\n * @returns The hook return object with state and methods.\n *\n * @example\n * ```tsx\n * function PharmacySearch({ patientId }: { patientId: string }) {\n * const {\n * state,\n * searchPharmacies,\n * setSelectedPharmacy,\n * setAsPrimary,\n * addFavoritePharmacy,\n * clear\n * } = useDoseSpotPatientPharmacy();\n *\n * const handleSearch = async () => {\n * const results = await searchPharmacies({ zip: '94118' });\n * // Display results to user\n * };\n *\n * const handleAddFavorite = async () => {\n * const result = await addFavoritePharmacy(patientId);\n * if (result.success) {\n * clear();\n * }\n * };\n * }\n * ```\n */\nexport function useDoseSpotPatientPharmacy(): DoseSpotPatientPharmacyReturn {\n const [selectedPharmacy, privateSetSelectedPharmacy] = useState<Organization | undefined>(undefined);\n const [setAsPrimaryState, privateSetAsPrimary] = useState(false);\n const medplum = useMedplum();\n\n const state: DoseSpotPatientPharmacyState = {\n selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n };\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params)) as Organization[];\n },\n [medplum]\n );\n\n const setSelectedPharmacy = (pharmacy: Organization | undefined): void => {\n privateSetSelectedPharmacy(pharmacy);\n };\n\n const setAsPrimary = (primary: boolean): void => {\n privateSetAsPrimary(primary);\n };\n\n const addFavoritePharmacy = useCallback(\n async (patientId: string): Promise<AddPatientPharmacyResponse> => {\n if (!selectedPharmacy) {\n throw new Error('Must select a pharmacy before adding it as a favorite');\n }\n\n const pharmacyId = getPharmacyIdFromOrganization(selectedPharmacy);\n if (!pharmacyId) {\n throw new Error('Selected pharmacy does not have a valid DoseSpot pharmacy ID');\n }\n\n return medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId,\n pharmacy: selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n }) as Promise<AddPatientPharmacyResponse>;\n },\n [selectedPharmacy, setAsPrimaryState, medplum]\n );\n\n const clear = (): void => {\n privateSetSelectedPharmacy(undefined);\n privateSetAsPrimary(false);\n };\n\n return {\n state,\n searchPharmacies,\n setSelectedPharmacy,\n setAsPrimary,\n addFavoritePharmacy,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { MedicationKnowledge, Organization } from '@medplum/fhirtypes';\nimport { DOSESPOT_PHARMACY_ID_SYSTEM } from './common';\n\nexport const getMedicationName = (medication: MedicationKnowledge | undefined): string => {\n return medication?.code?.text || '';\n};\n\n/**\n * Extracts the DoseSpot pharmacy ID from an Organization resource.\n * @param organization - The FHIR Organization resource representing a pharmacy.\n * @returns The DoseSpot pharmacy ID, or undefined if not found.\n */\nexport function getPharmacyIdFromOrganization(organization: Organization): number | undefined {\n const id = organization.identifier?.find((i) => i.system === DOSESPOT_PHARMACY_ID_SYSTEM)?.value;\n return id ? Number.parseInt(id, 10) : undefined;\n}\n\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { PreferredPharmacy } from '@medplum/core';\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams } from '@medplum/core';\nimport { isAddPharmacyResponse, isOrganizationArray } from '@medplum/core';\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\n\nexport interface UseDoseSpotPharmacySearchReturn {\n searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n addToFavorites: (params: AddFavoriteParams) => Promise<AddPharmacyResponse>;\n}\n\n/**\n * React hook that provides DoseSpot-specific pharmacy search and add-to-favorites functionality.\n *\n * This hook encapsulates calls to the DoseSpot pharmacy search and add patient pharmacy bots,\n * and can be composed with the generic `PharmacyDialog` component from `@medplum/react`.\n *\n * @returns An object with `searchPharmacies` and `addToFavorites` callbacks.\n */\nexport function useDoseSpotPharmacySearch(): UseDoseSpotPharmacySearchReturn {\n const medplum = useMedplum();\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n const response = await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params);\n\n if (!isOrganizationArray(response)) {\n throw new Error('Invalid response from pharmacy search');\n }\n\n return response;\n },\n [medplum]\n );\n\n const addToFavorites = useCallback(\n async (params: AddFavoriteParams): Promise<AddPharmacyResponse> => {\n const response = await medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId: params.patientId,\n pharmacy: params.pharmacy,\n setAsPrimary: params.setAsPrimary,\n });\n\n if (!isAddPharmacyResponse(response)) {\n throw new Error('Invalid response from add pharmacy bot');\n }\n\n return response;\n },\n [medplum]\n );\n\n return { searchPharmacies, addToFavorites };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_core", "directions", "import_react_hooks", "import_react", "import_react_hooks", "import_react", "import_react_hooks", "import_react", "import_core", "import_core", "import_react_hooks", "import_react"]
|
|
7
7
|
}
|
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../dosespot-core/src/pharmacy-utils.ts", "../../src/useDoseSpotClinicFormulary.ts", "../../src/useDoseSpotIFrame.ts", "../../src/useDoseSpotNotifications.ts", "../../src/useDoseSpotPatientPharmacy.ts", "../../src/utils.ts", "../../src/useDoseSpotPharmacySearch.ts"],
|
|
4
|
-
"sourcesContent": ["// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Identifier } from '@medplum/fhirtypes';\n\n// DoseSpot-specific pharmacy preference type system\nexport const DOSESPOT_PHARMACY_PREFERENCE_TYPE_SYSTEM = 'https://dosespot.com/pharmacy-preference-type';\n\n// Re-export generic pharmacy utilities from @medplum/core\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams, PreferredPharmacy } from '@medplum/core';\n\n// Bot system\nexport const MEDPLUM_BOT_SYSTEM = 'https://www.medplum.com/bots';\n\n// DoseSpot identifier systems\nexport const DOSESPOT_PATIENT_ID_SYSTEM = 'https://dosespot.com/patient-id';\nexport const DOSESPOT_PHARMACY_ID_SYSTEM = 'https://dosespot.com/pharmacy-id';\nexport const DOSESPOT_CLINIC_FAVORITE_ID_SYSTEM = 'https://dosespot.com/clinic-favorite-medication-id';\nexport const DOSESPOT_DISPENSABLE_DRUG_ID_SYSTEM = 'https://dosespot.com/dispensable-drug-id';\n\n// Bot identifiers - Pharmacy\nexport const DOSESPOT_SEARCH_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-pharmacy-bot',\n};\n\nexport const DOSESPOT_ADD_PATIENT_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-patient-pharmacy-bot',\n};\n\n// Bot identifiers - Patient and Medications\nexport const DOSESPOT_PATIENT_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-patient-sync-bot',\n};\n\nexport const DOSESPOT_IFRAME_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-iframe-bot',\n};\n\nexport const DOSESPOT_ADD_FAVORITE_MEDICATION_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-favorite-medication-bot',\n};\n\nexport const DOSESPOT_GET_FAVORITE_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-get-favorite-medications-bot',\n};\n\nexport const DOSESPOT_SEARCH_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-medication-bot',\n};\n\nexport const DOSESPOT_MEDICATION_HISTORY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-medication-history-bot',\n};\n\nexport const DOSESPOT_PRESCRIPTIONS_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-prescriptions-sync-bot',\n};\n\nexport const DOSESPOT_NOTIFICATION_COUNTS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-notification-counts-bot',\n};\n\n// DoseSpot notification response type\nexport interface DoseSpotNotificationCountsResponse {\n PendingPrescriptionsCount: number;\n PendingRxChangeCount: number;\n RefillRequestsCount: number;\n TransactionErrorsCount: number;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { isCodeableConcept, isCoding } from '@medplum/core';\nimport type { CodeableConcept, Coding, MedicationKnowledge } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, DOSESPOT_SEARCH_MEDICATIONS_BOT } from './common';\n\nexport interface DoseSpotClinicFormularyReturn {\n state: DoseSpotClinicFormularyState;\n /**\n * Search for DoseSpot Medications and returns array of temporary MedicationKnowledge objects that are not yet saved to the FHIR server\n */\n readonly searchMedications: (searchTerm: string) => Promise<CodeableConcept[]>;\n /**\n * Set the currently selected medication. Can be set as a CodeableConcept or a Coding, but state is always stored as a CodeableConcept\n */\n readonly setSelectedMedication: (medication: CodeableConcept | Coding | undefined) => void;\n /**\n * Set the directions for the currently selected medication\n */\n readonly setSelectedMedicationDirections: (directions: string | undefined) => void;\n /**\n * Save a DoseSpot Medication to the Clinic's favorites and returns the MedicationKnowledge object that was saved\n */\n readonly saveFavoriteMedication: () => Promise<MedicationKnowledge>;\n /**\n * Clear the state\n */\n readonly clear: () => void;\n}\n\nexport interface DoseSpotClinicFormularyState {\n selectedMedication: CodeableConcept | undefined;\n directions: string | undefined;\n}\n\nexport function useDoseSpotClinicFormulary(): DoseSpotClinicFormularyReturn {\n const [directions, privateSetDirections] = useState<string | undefined>(undefined);\n const [selectedMedication, privateSetSelectedMedication] = useState<CodeableConcept | undefined>(undefined);\n const medplum = useMedplum();\n\n const state: DoseSpotClinicFormularyState = { selectedMedication, directions };\n\n const saveFavoriteMedication = useCallback(async (): Promise<MedicationKnowledge> => {\n if (!selectedMedication) {\n throw new Error('Must select a medication before adding a favorite medication');\n }\n\n //Add the directions to the medicationKnowledge object\n const medicationKnowledgeWithDirections = {\n resourceType: 'MedicationKnowledge',\n code: { ...selectedMedication },\n administrationGuidelines: [\n {\n dosage: [\n {\n dosage: [\n {\n patientInstruction: directions || '',\n },\n ],\n type: {\n coding: [\n {\n system: 'https://dosespot.com/patient-instructions',\n },\n ],\n },\n },\n ],\n },\n ],\n };\n\n return medplum.executeBot(DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, medicationKnowledgeWithDirections);\n }, [selectedMedication, directions, medplum]);\n\n const searchMedications = useCallback(\n async (searchTerm: string): Promise<CodeableConcept[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_MEDICATIONS_BOT, { name: searchTerm })) as CodeableConcept[];\n },\n [medplum]\n );\n\n const setSelectedMedicationDirections = (directions: string | undefined): void => {\n privateSetDirections(directions);\n };\n\n const setSelectedMedication = (medication: CodeableConcept | Coding | undefined): void => {\n let medicationToSet: CodeableConcept | undefined;\n if (isCodeableConcept(medication)) {\n medicationToSet = { ...medication };\n } else if (isCoding(medication)) {\n medicationToSet = {\n text: medication.display || '',\n coding: [medication],\n };\n }\n privateSetSelectedMedication(medicationToSet);\n };\n\n const clear = (): void => {\n privateSetSelectedMedication(undefined);\n privateSetDirections(undefined);\n };\n\n return {\n state,\n searchMedications,\n setSelectedMedication,\n setSelectedMedicationDirections,\n saveFavoriteMedication,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { DOSESPOT_IFRAME_BOT, DOSESPOT_PATIENT_SYNC_BOT } from './common';\n\nexport interface DoseSpotIFrameOptions {\n readonly patientId?: string;\n readonly onPatientSyncSuccess?: () => void;\n readonly onIframeSuccess?: (url: string) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nexport function useDoseSpotIFrame(options: DoseSpotIFrameOptions): string | undefined {\n const medplum = useMedplum();\n const { patientId, onPatientSyncSuccess, onIframeSuccess, onError } = options;\n const initializingRef = useRef<boolean>(false);\n const [iframeUrl, setIframeUrl] = useState<string | undefined>(undefined);\n\n const onPatientSyncSuccessRef = useRef(onPatientSyncSuccess);\n onPatientSyncSuccessRef.current = onPatientSyncSuccess;\n\n const onIframeSuccessRef = useRef(onIframeSuccess);\n onIframeSuccessRef.current = onIframeSuccess;\n\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n // Reset when inputs change so we re-fetch the iframe URL\n useEffect(() => {\n initializingRef.current = false;\n }, [patientId]);\n\n const initPage = useCallback(async () => {\n if (initializingRef.current) {\n return;\n }\n\n initializingRef.current = true;\n try {\n if (patientId) {\n await medplum.executeBot(DOSESPOT_PATIENT_SYNC_BOT, { patientId });\n onPatientSyncSuccessRef.current?.();\n }\n const result = await medplum.executeBot(DOSESPOT_IFRAME_BOT, { patientId });\n if (result.url) {\n setIframeUrl(result.url);\n onIframeSuccessRef.current?.(result.url);\n }\n } catch (err: unknown) {\n onErrorRef.current?.(err);\n }\n }, [medplum, patientId]);\n\n useEffect(() => {\n initPage().catch(console.error);\n }, [initPage]);\n\n return iframeUrl;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DoseSpotNotificationCountsResponse } from './common';\nimport { DOSESPOT_NOTIFICATION_COUNTS_BOT } from './common';\n\nexport interface DoseSpotNotificationsOptions {\n readonly refreshIntervalMilliseconds?: number;\n readonly onChange?: (count: number) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nconst DEFAULT_REFRESH_INTERVAL_MILLISECONDS = 10000;\n\nexport function useDoseSpotNotifications(options?: DoseSpotNotificationsOptions): number | undefined {\n const medplum = useMedplum();\n const { onChange, onError } = options ?? {};\n const hasDoseSpot = medplum.getProjectMembership()?.identifier?.some((i) => i.system?.includes('dosespot'));\n const refreshInterval = options?.refreshIntervalMilliseconds ?? DEFAULT_REFRESH_INTERVAL_MILLISECONDS;\n const timerRef = useRef<NodeJS.Timeout | undefined>(undefined);\n const [unreadCount, setUnreadCount] = useState<number | undefined>(undefined);\n\n const stopTimer = useCallback(() => {\n const timerId = timerRef.current;\n if (timerId) {\n clearInterval(timerId);\n }\n }, []);\n\n const updateCount = useCallback(async () => {\n try {\n const result = (await medplum.executeBot(\n DOSESPOT_NOTIFICATION_COUNTS_BOT,\n {}\n )) as DoseSpotNotificationCountsResponse;\n\n let newCount = 0;\n if (result.PendingPrescriptionsCount) {\n newCount += result.PendingPrescriptionsCount;\n }\n if (result.PendingRxChangeCount) {\n newCount += result.PendingRxChangeCount;\n }\n if (result.RefillRequestsCount) {\n newCount += result.RefillRequestsCount;\n }\n if (result.TransactionErrorsCount) {\n newCount += result.TransactionErrorsCount;\n }\n if (newCount !== unreadCount) {\n setUnreadCount(newCount);\n onChange?.(newCount);\n }\n } catch (err: unknown) {\n onError?.(err);\n stopTimer();\n }\n }, [medplum, unreadCount, onChange, onError, stopTimer]);\n\n const startTimer = useCallback(() => {\n timerRef.current = setInterval(() => {\n updateCount().catch(console.error);\n }, refreshInterval);\n }, [updateCount, refreshInterval]);\n\n useEffect(() => {\n // Start an interval timer to update the count every 5 seconds\n if (hasDoseSpot) {\n startTimer();\n }\n\n // Clear the interval timer when the component is unmounted\n return stopTimer;\n }, [hasDoseSpot, startTimer, stopTimer]);\n\n return unreadCount;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\nimport { getPharmacyIdFromOrganization } from './utils';\n\n/**\n * Search parameters for pharmacy search.\n * See DoseSpot API section 3.13.2.\n */\nexport interface PharmacySearchParams {\n /** Pharmacy's store name (min 3 chars) */\n name?: string;\n /** City (min 3 chars) */\n city?: string;\n /** State (min 3 chars) */\n state?: string;\n /** Zip code (min 3 chars) */\n zip?: string;\n /** Address (min 3 chars) */\n address?: string;\n /** Phone or fax number */\n phoneOrFax?: string;\n /** Collection of pharmacy specialties (numeric values) */\n specialty?: number[];\n /** National Council for Prescription Drug Programs Identifier */\n ncpdpID?: string;\n /** Page number of results (defaults to 1) */\n pageNumber?: number;\n}\n\n/**\n * Response from adding a pharmacy to a patient's favorites.\n */\nexport interface AddPatientPharmacyResponse {\n /** Whether the operation was successful */\n success: boolean;\n /** A message describing the result */\n message: string;\n /** The persisted Organization resource with ID */\n organization?: Organization;\n}\n\n/**\n * State managed by the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyState {\n /** The currently selected pharmacy Organization */\n selectedPharmacy: Organization | undefined;\n /** Whether to set the selected pharmacy as the patient's primary pharmacy */\n setAsPrimary: boolean;\n}\n\n/**\n * Return type for the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyReturn {\n /** Current state of the hook */\n state: DoseSpotPatientPharmacyState;\n /**\n * Search for pharmacies in DoseSpot.\n * Returns synthetic Organization resources (not persisted to DB).\n */\n readonly searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n /**\n * Set the currently selected pharmacy.\n */\n readonly setSelectedPharmacy: (pharmacy: Organization | undefined) => void;\n /**\n * Set whether to add the pharmacy as the patient's primary pharmacy.\n */\n readonly setAsPrimary: (primary: boolean) => void;\n /**\n * Add the selected pharmacy to the patient's favorites in DoseSpot.\n * @param patientId - The Medplum Patient ID\n */\n readonly addFavoritePharmacy: (patientId: string) => Promise<AddPatientPharmacyResponse>;\n /**\n * Clear the state (selected pharmacy and setAsPrimary flag).\n */\n readonly clear: () => void;\n}\n\n/**\n * React hook for searching DoseSpot pharmacies and adding them to patient favorites.\n *\n * @returns The hook return object with state and methods.\n *\n * @example\n * ```tsx\n * function PharmacySearch({ patientId }: { patientId: string }) {\n * const {\n * state,\n * searchPharmacies,\n * setSelectedPharmacy,\n * setAsPrimary,\n * addFavoritePharmacy,\n * clear\n * } = useDoseSpotPatientPharmacy();\n *\n * const handleSearch = async () => {\n * const results = await searchPharmacies({ zip: '94118' });\n * // Display results to user\n * };\n *\n * const handleAddFavorite = async () => {\n * const result = await addFavoritePharmacy(patientId);\n * if (result.success) {\n * clear();\n * }\n * };\n * }\n * ```\n */\nexport function useDoseSpotPatientPharmacy(): DoseSpotPatientPharmacyReturn {\n const [selectedPharmacy, privateSetSelectedPharmacy] = useState<Organization | undefined>(undefined);\n const [setAsPrimaryState, privateSetAsPrimary] = useState<boolean>(false);\n const medplum = useMedplum();\n\n const state: DoseSpotPatientPharmacyState = {\n selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n };\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params)) as Organization[];\n },\n [medplum]\n );\n\n const setSelectedPharmacy = (pharmacy: Organization | undefined): void => {\n privateSetSelectedPharmacy(pharmacy);\n };\n\n const setAsPrimary = (primary: boolean): void => {\n privateSetAsPrimary(primary);\n };\n\n const addFavoritePharmacy = useCallback(\n async (patientId: string): Promise<AddPatientPharmacyResponse> => {\n if (!selectedPharmacy) {\n throw new Error('Must select a pharmacy before adding it as a favorite');\n }\n\n const pharmacyId = getPharmacyIdFromOrganization(selectedPharmacy);\n if (!pharmacyId) {\n throw new Error('Selected pharmacy does not have a valid DoseSpot pharmacy ID');\n }\n\n return medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId,\n pharmacy: selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n }) as Promise<AddPatientPharmacyResponse>;\n },\n [selectedPharmacy, setAsPrimaryState, medplum]\n );\n\n const clear = (): void => {\n privateSetSelectedPharmacy(undefined);\n privateSetAsPrimary(false);\n };\n\n return {\n state,\n searchPharmacies,\n setSelectedPharmacy,\n setAsPrimary,\n addFavoritePharmacy,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { MedicationKnowledge, Organization } from '@medplum/fhirtypes';\nimport { DOSESPOT_PHARMACY_ID_SYSTEM } from './common';\n\nexport const getMedicationName = (medication: MedicationKnowledge | undefined): string => {\n return medication?.code?.text || '';\n};\n\n/**\n * Extracts the DoseSpot pharmacy ID from an Organization resource.\n * @param organization - The FHIR Organization resource representing a pharmacy.\n * @returns The DoseSpot pharmacy ID, or undefined if not found.\n */\nexport function getPharmacyIdFromOrganization(organization: Organization): number | undefined {\n const id = organization.identifier?.find((i) => i.system === DOSESPOT_PHARMACY_ID_SYSTEM)?.value;\n return id ? Number.parseInt(id, 10) : undefined;\n}\n\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { PreferredPharmacy } from '@medplum/core';\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams } from '@medplum/core';\nimport { isAddPharmacyResponse, isOrganizationArray } from '@medplum/core';\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\n\nexport interface UseDoseSpotPharmacySearchReturn {\n searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n addToFavorites: (params: AddFavoriteParams) => Promise<AddPharmacyResponse>;\n}\n\n/**\n * React hook that provides DoseSpot-specific pharmacy search and add-to-favorites functionality.\n *\n * This hook encapsulates calls to the DoseSpot pharmacy search and add patient pharmacy bots,\n * and can be composed with the generic `PharmacyDialog` component from `@medplum/react`.\n *\n * @returns An object with `searchPharmacies` and `addToFavorites` callbacks.\n */\nexport function useDoseSpotPharmacySearch(): UseDoseSpotPharmacySearchReturn {\n const medplum = useMedplum();\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n const response = await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params);\n\n if (!isOrganizationArray(response)) {\n throw new Error('Invalid response from pharmacy search');\n }\n\n return response;\n },\n [medplum]\n );\n\n const addToFavorites = useCallback(\n async (params: AddFavoriteParams): Promise<AddPharmacyResponse> => {\n const response = await medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId: params.patientId,\n pharmacy: params.pharmacy,\n setAsPrimary: params.setAsPrimary,\n });\n\n if (!isAddPharmacyResponse(response)) {\n throw new Error('Invalid response from add pharmacy bot');\n }\n\n return response;\n },\n [medplum]\n );\n\n return { searchPharmacies, addToFavorites };\n}\n"],
|
|
5
|
-
"mappings": "AASA,OACE,8BACA,iCACA,kCACA,sBACA,oBACA,+BACA,gCACA,wBACA,sBACA,uCACK,gBAdA,IAkBM,mBAAqB,+BAGrB,2BAA6B,kCAC7B,4BAA8B,mCAC9B,mCAAqC,qDACrC,oCAAsC,2CAGtC,6BAA2C,CACtD,OAAQ,mBACR,MAAO,8BACT,EAEa,kCAAgD,CAC3D,OAAQ,mBACR,MAAO,mCACT,EAGa,0BAAwC,CACnD,OAAQ,mBACR,MAAO,2BACT,EAEa,oBAAkC,CAC7C,OAAQ,mBACR,MAAO,qBACT,EAEa,qCAAmD,CAC9D,OAAQ,mBACR,MAAO,sCACT,EAEa,sCAAoD,CAC/D,OAAQ,mBACR,MAAO,uCACT,EAEa,gCAA8C,CACzD,OAAQ,mBACR,MAAO,gCACT,EAEa,gCAA8C,CACzD,OAAQ,mBACR,MAAO,iCACT,EAEa,gCAA8C,CACzD,OAAQ,mBACR,MAAO,iCACT,EAEa,iCAA+C,CAC1D,OAAQ,mBACR,MAAO,kCACT,EChFA,OAAS,kBAAmB,aAAgB,gBAE5C,OAAS,eAAkB,uBAC3B,OAAS,YAAa,aAAgB,QAgC/B,SAAS,4BAA4D,CAC1E,GAAM,CAAC,WAAY,oBAAoB,EAAI,SAA6B,MAAS,EAC3E,CAAC,mBAAoB,4BAA4B,EAAI,SAAsC,MAAS,EACpG,QAAU,WAAW,EAErB,MAAsC,CAAE,mBAAoB,UAAW,EAEvE,uBAAyB,YAAY,SAA0C,CACnF,GAAI,CAAC,mBACH,MAAM,IAAI,MAAM,8DAA8D,EAIhF,IAAM,kCAAoC,CACxC,aAAc,sBACd,KAAM,CAAE,GAAG,kBAAmB,EAC9B,yBAA0B,CACxB,CACE,OAAQ,CACN,CACE,OAAQ,CACN,CACE,mBAAoB,YAAc,EACpC,CACF,EACA,KAAM,CACJ,OAAQ,CACN,CACE,OAAQ,2CACV,CACF,CACF,CACF,CACF,CACF,CACF,CACF,EAEA,OAAO,QAAQ,WAAW,qCAAsC,iCAAiC,CACnG,EAAG,CAAC,mBAAoB,WAAY,OAAO,CAAC,EAEtC,kBAAoB,YACxB,MAAO,YACG,MAAM,QAAQ,WAAW,gCAAiC,CAAE,KAAM,UAAW,CAAC,EAExF,CAAC,OAAO,CACV,EAwBA,MAAO,CACL,MACA,kBACA,sBArB6B,YAA2D,CACxF,IAAI,gBACA,kBAAkB,UAAU,EAC9B,gBAAkB,CAAE,GAAG,UAAW,EACzB,SAAS,UAAU,IAC5B,gBAAkB,CAChB,KAAM,WAAW,SAAW,GAC5B,OAAQ,CAAC,UAAU,CACrB,GAEF,6BAA6B,eAAe,CAC9C,EAWE,gCA1BuCA,aAAyC,CAChF,qBAAqBA,WAAU,CACjC,EAyBE,uBACA,MAXY,IAAY,CACxB,6BAA6B,MAAS,EACtC,qBAAqB,MAAS,CAChC,CASA,CACF,CCjHA,OAAS,cAAAC,gBAAkB,uBAC3B,OAAS,eAAAC,aAAa,UAAW,OAAQ,YAAAC,cAAgB,QAUlD,SAAS,kBAAkB,QAAoD,CACpF,IAAM,QAAUC,YAAW,EACrB,CAAE,UAAW,qBAAsB,gBAAiB,OAAQ,EAAI,QAChE,gBAAkB,
|
|
4
|
+
"sourcesContent": ["// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Identifier } from '@medplum/fhirtypes';\n\n// DoseSpot-specific pharmacy preference type system\nexport const DOSESPOT_PHARMACY_PREFERENCE_TYPE_SYSTEM = 'https://dosespot.com/pharmacy-preference-type';\n\n// Re-export generic pharmacy utilities from @medplum/core\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams, PreferredPharmacy } from '@medplum/core';\n\n// Bot system\nexport const MEDPLUM_BOT_SYSTEM = 'https://www.medplum.com/bots';\n\n// DoseSpot identifier systems\nexport const DOSESPOT_PATIENT_ID_SYSTEM = 'https://dosespot.com/patient-id';\nexport const DOSESPOT_PHARMACY_ID_SYSTEM = 'https://dosespot.com/pharmacy-id';\nexport const DOSESPOT_CLINIC_FAVORITE_ID_SYSTEM = 'https://dosespot.com/clinic-favorite-medication-id';\nexport const DOSESPOT_DISPENSABLE_DRUG_ID_SYSTEM = 'https://dosespot.com/dispensable-drug-id';\n\n// Bot identifiers - Pharmacy\nexport const DOSESPOT_SEARCH_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-pharmacy-bot',\n};\n\nexport const DOSESPOT_ADD_PATIENT_PHARMACY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-patient-pharmacy-bot',\n};\n\n// Bot identifiers - Patient and Medications\nexport const DOSESPOT_PATIENT_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-patient-sync-bot',\n};\n\nexport const DOSESPOT_IFRAME_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-iframe-bot',\n};\n\nexport const DOSESPOT_ADD_FAVORITE_MEDICATION_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-add-favorite-medication-bot',\n};\n\nexport const DOSESPOT_GET_FAVORITE_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-get-favorite-medications-bot',\n};\n\nexport const DOSESPOT_SEARCH_MEDICATIONS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-search-medication-bot',\n};\n\nexport const DOSESPOT_MEDICATION_HISTORY_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-medication-history-bot',\n};\n\nexport const DOSESPOT_PRESCRIPTIONS_SYNC_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-prescriptions-sync-bot',\n};\n\nexport const DOSESPOT_NOTIFICATION_COUNTS_BOT: Identifier = {\n system: MEDPLUM_BOT_SYSTEM,\n value: 'dosespot-notification-counts-bot',\n};\n\n// DoseSpot notification response type\nexport interface DoseSpotNotificationCountsResponse {\n PendingPrescriptionsCount: number;\n PendingRxChangeCount: number;\n RefillRequestsCount: number;\n TransactionErrorsCount: number;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { isCodeableConcept, isCoding } from '@medplum/core';\nimport type { CodeableConcept, Coding, MedicationKnowledge } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, DOSESPOT_SEARCH_MEDICATIONS_BOT } from './common';\n\nexport interface DoseSpotClinicFormularyReturn {\n state: DoseSpotClinicFormularyState;\n /**\n * Search for DoseSpot Medications and returns array of temporary MedicationKnowledge objects that are not yet saved to the FHIR server\n */\n readonly searchMedications: (searchTerm: string) => Promise<CodeableConcept[]>;\n /**\n * Set the currently selected medication. Can be set as a CodeableConcept or a Coding, but state is always stored as a CodeableConcept\n */\n readonly setSelectedMedication: (medication: CodeableConcept | Coding | undefined) => void;\n /**\n * Set the directions for the currently selected medication\n */\n readonly setSelectedMedicationDirections: (directions: string | undefined) => void;\n /**\n * Save a DoseSpot Medication to the Clinic's favorites and returns the MedicationKnowledge object that was saved\n */\n readonly saveFavoriteMedication: () => Promise<MedicationKnowledge>;\n /**\n * Clear the state\n */\n readonly clear: () => void;\n}\n\nexport interface DoseSpotClinicFormularyState {\n selectedMedication: CodeableConcept | undefined;\n directions: string | undefined;\n}\n\nexport function useDoseSpotClinicFormulary(): DoseSpotClinicFormularyReturn {\n const [directions, privateSetDirections] = useState<string | undefined>(undefined);\n const [selectedMedication, privateSetSelectedMedication] = useState<CodeableConcept | undefined>(undefined);\n const medplum = useMedplum();\n\n const state: DoseSpotClinicFormularyState = { selectedMedication, directions };\n\n const saveFavoriteMedication = useCallback(async (): Promise<MedicationKnowledge> => {\n if (!selectedMedication) {\n throw new Error('Must select a medication before adding a favorite medication');\n }\n\n //Add the directions to the medicationKnowledge object\n const medicationKnowledgeWithDirections = {\n resourceType: 'MedicationKnowledge',\n code: { ...selectedMedication },\n administrationGuidelines: [\n {\n dosage: [\n {\n dosage: [\n {\n patientInstruction: directions || '',\n },\n ],\n type: {\n coding: [\n {\n system: 'https://dosespot.com/patient-instructions',\n },\n ],\n },\n },\n ],\n },\n ],\n };\n\n return medplum.executeBot(DOSESPOT_ADD_FAVORITE_MEDICATION_BOT, medicationKnowledgeWithDirections);\n }, [selectedMedication, directions, medplum]);\n\n const searchMedications = useCallback(\n async (searchTerm: string): Promise<CodeableConcept[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_MEDICATIONS_BOT, { name: searchTerm })) as CodeableConcept[];\n },\n [medplum]\n );\n\n const setSelectedMedicationDirections = (directions: string | undefined): void => {\n privateSetDirections(directions);\n };\n\n const setSelectedMedication = (medication: CodeableConcept | Coding | undefined): void => {\n let medicationToSet: CodeableConcept | undefined;\n if (isCodeableConcept(medication)) {\n medicationToSet = { ...medication };\n } else if (isCoding(medication)) {\n medicationToSet = {\n text: medication.display || '',\n coding: [medication],\n };\n }\n privateSetSelectedMedication(medicationToSet);\n };\n\n const clear = (): void => {\n privateSetSelectedMedication(undefined);\n privateSetDirections(undefined);\n };\n\n return {\n state,\n searchMedications,\n setSelectedMedication,\n setSelectedMedicationDirections,\n saveFavoriteMedication,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { DOSESPOT_IFRAME_BOT, DOSESPOT_PATIENT_SYNC_BOT } from './common';\n\nexport interface DoseSpotIFrameOptions {\n readonly patientId?: string;\n readonly onPatientSyncSuccess?: () => void;\n readonly onIframeSuccess?: (url: string) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nexport function useDoseSpotIFrame(options: DoseSpotIFrameOptions): string | undefined {\n const medplum = useMedplum();\n const { patientId, onPatientSyncSuccess, onIframeSuccess, onError } = options;\n const initializingRef = useRef(false);\n const [iframeUrl, setIframeUrl] = useState<string | undefined>(undefined);\n\n const onPatientSyncSuccessRef = useRef(onPatientSyncSuccess);\n onPatientSyncSuccessRef.current = onPatientSyncSuccess;\n\n const onIframeSuccessRef = useRef(onIframeSuccess);\n onIframeSuccessRef.current = onIframeSuccess;\n\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n // Reset when inputs change so we re-fetch the iframe URL\n useEffect(() => {\n initializingRef.current = false;\n }, [patientId]);\n\n const initPage = useCallback(async () => {\n if (initializingRef.current) {\n return;\n }\n\n initializingRef.current = true;\n try {\n if (patientId) {\n await medplum.executeBot(DOSESPOT_PATIENT_SYNC_BOT, { patientId });\n onPatientSyncSuccessRef.current?.();\n }\n const result = await medplum.executeBot(DOSESPOT_IFRAME_BOT, { patientId });\n if (result.url) {\n setIframeUrl(result.url);\n onIframeSuccessRef.current?.(result.url);\n }\n } catch (err: unknown) {\n onErrorRef.current?.(err);\n }\n }, [medplum, patientId]);\n\n useEffect(() => {\n initPage().catch(console.error);\n }, [initPage]);\n\n return iframeUrl;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DoseSpotNotificationCountsResponse } from './common';\nimport { DOSESPOT_NOTIFICATION_COUNTS_BOT } from './common';\n\nexport interface DoseSpotNotificationsOptions {\n readonly refreshIntervalMilliseconds?: number;\n readonly onChange?: (count: number) => void;\n readonly onError?: (err: unknown) => void;\n}\n\nconst DEFAULT_REFRESH_INTERVAL_MILLISECONDS = 10000;\n\nexport function useDoseSpotNotifications(options?: DoseSpotNotificationsOptions): number | undefined {\n const medplum = useMedplum();\n const { onChange, onError } = options ?? {};\n const hasDoseSpot = medplum.getProjectMembership()?.identifier?.some((i) => i.system?.includes('dosespot'));\n const refreshInterval = options?.refreshIntervalMilliseconds ?? DEFAULT_REFRESH_INTERVAL_MILLISECONDS;\n const timerRef = useRef<NodeJS.Timeout | undefined>(undefined);\n const [unreadCount, setUnreadCount] = useState<number | undefined>(undefined);\n\n const stopTimer = useCallback(() => {\n const timerId = timerRef.current;\n if (timerId) {\n clearInterval(timerId);\n }\n }, []);\n\n const updateCount = useCallback(async () => {\n try {\n const result = (await medplum.executeBot(\n DOSESPOT_NOTIFICATION_COUNTS_BOT,\n {}\n )) as DoseSpotNotificationCountsResponse;\n\n let newCount = 0;\n if (result.PendingPrescriptionsCount) {\n newCount += result.PendingPrescriptionsCount;\n }\n if (result.PendingRxChangeCount) {\n newCount += result.PendingRxChangeCount;\n }\n if (result.RefillRequestsCount) {\n newCount += result.RefillRequestsCount;\n }\n if (result.TransactionErrorsCount) {\n newCount += result.TransactionErrorsCount;\n }\n if (newCount !== unreadCount) {\n setUnreadCount(newCount);\n onChange?.(newCount);\n }\n } catch (err: unknown) {\n onError?.(err);\n stopTimer();\n }\n }, [medplum, unreadCount, onChange, onError, stopTimer]);\n\n const startTimer = useCallback(() => {\n timerRef.current = setInterval(() => {\n updateCount().catch(console.error);\n }, refreshInterval);\n }, [updateCount, refreshInterval]);\n\n useEffect(() => {\n // Start an interval timer to update the count every 5 seconds\n if (hasDoseSpot) {\n startTimer();\n }\n\n // Clear the interval timer when the component is unmounted\n return stopTimer;\n }, [hasDoseSpot, startTimer, stopTimer]);\n\n return unreadCount;\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback, useState } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\nimport { getPharmacyIdFromOrganization } from './utils';\n\n/**\n * Search parameters for pharmacy search.\n * See DoseSpot API section 3.13.2.\n */\nexport interface PharmacySearchParams {\n /** Pharmacy's store name (min 3 chars) */\n name?: string;\n /** City (min 3 chars) */\n city?: string;\n /** State (min 3 chars) */\n state?: string;\n /** Zip code (min 3 chars) */\n zip?: string;\n /** Address (min 3 chars) */\n address?: string;\n /** Phone or fax number */\n phoneOrFax?: string;\n /** Collection of pharmacy specialties (numeric values) */\n specialty?: number[];\n /** National Council for Prescription Drug Programs Identifier */\n ncpdpID?: string;\n /** Page number of results (defaults to 1) */\n pageNumber?: number;\n}\n\n/**\n * Response from adding a pharmacy to a patient's favorites.\n */\nexport interface AddPatientPharmacyResponse {\n /** Whether the operation was successful */\n success: boolean;\n /** A message describing the result */\n message: string;\n /** The persisted Organization resource with ID */\n organization?: Organization;\n}\n\n/**\n * State managed by the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyState {\n /** The currently selected pharmacy Organization */\n selectedPharmacy: Organization | undefined;\n /** Whether to set the selected pharmacy as the patient's primary pharmacy */\n setAsPrimary: boolean;\n}\n\n/**\n * Return type for the useDoseSpotPatientPharmacy hook.\n */\nexport interface DoseSpotPatientPharmacyReturn {\n /** Current state of the hook */\n state: DoseSpotPatientPharmacyState;\n /**\n * Search for pharmacies in DoseSpot.\n * Returns synthetic Organization resources (not persisted to DB).\n */\n readonly searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n /**\n * Set the currently selected pharmacy.\n */\n readonly setSelectedPharmacy: (pharmacy: Organization | undefined) => void;\n /**\n * Set whether to add the pharmacy as the patient's primary pharmacy.\n */\n readonly setAsPrimary: (primary: boolean) => void;\n /**\n * Add the selected pharmacy to the patient's favorites in DoseSpot.\n * @param patientId - The Medplum Patient ID\n */\n readonly addFavoritePharmacy: (patientId: string) => Promise<AddPatientPharmacyResponse>;\n /**\n * Clear the state (selected pharmacy and setAsPrimary flag).\n */\n readonly clear: () => void;\n}\n\n/**\n * React hook for searching DoseSpot pharmacies and adding them to patient favorites.\n *\n * @returns The hook return object with state and methods.\n *\n * @example\n * ```tsx\n * function PharmacySearch({ patientId }: { patientId: string }) {\n * const {\n * state,\n * searchPharmacies,\n * setSelectedPharmacy,\n * setAsPrimary,\n * addFavoritePharmacy,\n * clear\n * } = useDoseSpotPatientPharmacy();\n *\n * const handleSearch = async () => {\n * const results = await searchPharmacies({ zip: '94118' });\n * // Display results to user\n * };\n *\n * const handleAddFavorite = async () => {\n * const result = await addFavoritePharmacy(patientId);\n * if (result.success) {\n * clear();\n * }\n * };\n * }\n * ```\n */\nexport function useDoseSpotPatientPharmacy(): DoseSpotPatientPharmacyReturn {\n const [selectedPharmacy, privateSetSelectedPharmacy] = useState<Organization | undefined>(undefined);\n const [setAsPrimaryState, privateSetAsPrimary] = useState(false);\n const medplum = useMedplum();\n\n const state: DoseSpotPatientPharmacyState = {\n selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n };\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n return (await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params)) as Organization[];\n },\n [medplum]\n );\n\n const setSelectedPharmacy = (pharmacy: Organization | undefined): void => {\n privateSetSelectedPharmacy(pharmacy);\n };\n\n const setAsPrimary = (primary: boolean): void => {\n privateSetAsPrimary(primary);\n };\n\n const addFavoritePharmacy = useCallback(\n async (patientId: string): Promise<AddPatientPharmacyResponse> => {\n if (!selectedPharmacy) {\n throw new Error('Must select a pharmacy before adding it as a favorite');\n }\n\n const pharmacyId = getPharmacyIdFromOrganization(selectedPharmacy);\n if (!pharmacyId) {\n throw new Error('Selected pharmacy does not have a valid DoseSpot pharmacy ID');\n }\n\n return medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId,\n pharmacy: selectedPharmacy,\n setAsPrimary: setAsPrimaryState,\n }) as Promise<AddPatientPharmacyResponse>;\n },\n [selectedPharmacy, setAsPrimaryState, medplum]\n );\n\n const clear = (): void => {\n privateSetSelectedPharmacy(undefined);\n privateSetAsPrimary(false);\n };\n\n return {\n state,\n searchPharmacies,\n setSelectedPharmacy,\n setAsPrimary,\n addFavoritePharmacy,\n clear,\n };\n}\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\nimport type { MedicationKnowledge, Organization } from '@medplum/fhirtypes';\nimport { DOSESPOT_PHARMACY_ID_SYSTEM } from './common';\n\nexport const getMedicationName = (medication: MedicationKnowledge | undefined): string => {\n return medication?.code?.text || '';\n};\n\n/**\n * Extracts the DoseSpot pharmacy ID from an Organization resource.\n * @param organization - The FHIR Organization resource representing a pharmacy.\n * @returns The DoseSpot pharmacy ID, or undefined if not found.\n */\nexport function getPharmacyIdFromOrganization(organization: Organization): number | undefined {\n const id = organization.identifier?.find((i) => i.system === DOSESPOT_PHARMACY_ID_SYSTEM)?.value;\n return id ? Number.parseInt(id, 10) : undefined;\n}\n\nexport {\n addPreferredPharmacyToPatient,\n createPreferredPharmacyExtension,\n getPreferredPharmaciesFromPatient,\n isAddPharmacyResponse,\n isOrganizationArray,\n PATIENT_PREFERRED_PHARMACY_URL,\n PHARMACY_PREFERENCE_TYPE_SYSTEM,\n PHARMACY_TYPE_PREFERRED,\n PHARMACY_TYPE_PRIMARY,\n removePreferredPharmacyFromPatient,\n} from '@medplum/core';\nexport type { PreferredPharmacy } from '@medplum/core';\n", "// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { AddFavoriteParams, AddPharmacyResponse, PharmacySearchParams } from '@medplum/core';\nimport { isAddPharmacyResponse, isOrganizationArray } from '@medplum/core';\nimport type { Organization } from '@medplum/fhirtypes';\nimport { useMedplum } from '@medplum/react-hooks';\nimport { useCallback } from 'react';\nimport { DOSESPOT_ADD_PATIENT_PHARMACY_BOT, DOSESPOT_SEARCH_PHARMACY_BOT } from './common';\n\nexport interface UseDoseSpotPharmacySearchReturn {\n searchPharmacies: (params: PharmacySearchParams) => Promise<Organization[]>;\n addToFavorites: (params: AddFavoriteParams) => Promise<AddPharmacyResponse>;\n}\n\n/**\n * React hook that provides DoseSpot-specific pharmacy search and add-to-favorites functionality.\n *\n * This hook encapsulates calls to the DoseSpot pharmacy search and add patient pharmacy bots,\n * and can be composed with the generic `PharmacyDialog` component from `@medplum/react`.\n *\n * @returns An object with `searchPharmacies` and `addToFavorites` callbacks.\n */\nexport function useDoseSpotPharmacySearch(): UseDoseSpotPharmacySearchReturn {\n const medplum = useMedplum();\n\n const searchPharmacies = useCallback(\n async (params: PharmacySearchParams): Promise<Organization[]> => {\n const response = await medplum.executeBot(DOSESPOT_SEARCH_PHARMACY_BOT, params);\n\n if (!isOrganizationArray(response)) {\n throw new Error('Invalid response from pharmacy search');\n }\n\n return response;\n },\n [medplum]\n );\n\n const addToFavorites = useCallback(\n async (params: AddFavoriteParams): Promise<AddPharmacyResponse> => {\n const response = await medplum.executeBot(DOSESPOT_ADD_PATIENT_PHARMACY_BOT, {\n patientId: params.patientId,\n pharmacy: params.pharmacy,\n setAsPrimary: params.setAsPrimary,\n });\n\n if (!isAddPharmacyResponse(response)) {\n throw new Error('Invalid response from add pharmacy bot');\n }\n\n return response;\n },\n [medplum]\n );\n\n return { searchPharmacies, addToFavorites };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["directions", "useMedplum", "useCallback", "useState", "useMedplum", "useState", "useCallback", "useMedplum", "useCallback", "useEffect", "useRef", "useState", "useMedplum", "useRef", "useState", "useCallback", "useEffect", "useMedplum", "useCallback", "useState", "addPreferredPharmacyToPatient", "createPreferredPharmacyExtension", "getPreferredPharmaciesFromPatient", "isAddPharmacyResponse", "isOrganizationArray", "PATIENT_PREFERRED_PHARMACY_URL", "PHARMACY_PREFERENCE_TYPE_SYSTEM", "PHARMACY_TYPE_PREFERRED", "PHARMACY_TYPE_PRIMARY", "removePreferredPharmacyFromPatient", "useState", "useMedplum", "useCallback", "isAddPharmacyResponse", "isOrganizationArray", "useMedplum", "useCallback", "useMedplum", "useCallback", "isOrganizationArray", "isAddPharmacyResponse"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@medplum/dosespot-react",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.6",
|
|
4
4
|
"description": "Medplum DoseSpot React SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"medplum",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"scripts": {
|
|
53
53
|
"api-documenter": "api-documenter markdown --input-folder ./dist/api/ --output-folder ./dist/docs/",
|
|
54
54
|
"api-extractor": "api-extractor run --local && shx cp dist/types.d.ts dist/cjs/index.d.ts && shx cp dist/types.d.ts dist/esm/index.d.ts",
|
|
55
|
-
"build": "npm run clean && tsc
|
|
55
|
+
"build": "npm run clean && tsc && node esbuild.mjs && npm run api-extractor",
|
|
56
56
|
"clean": "rimraf dist",
|
|
57
57
|
"lint": "eslint src/",
|
|
58
58
|
"lint:fix": "eslint src/ --fix",
|
|
@@ -60,11 +60,11 @@
|
|
|
60
60
|
"test:watch": "vitest watch"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@medplum/core": "5.1.
|
|
64
|
-
"@medplum/dosespot-core": "5.1.
|
|
65
|
-
"@medplum/fhirtypes": "5.1.
|
|
66
|
-
"@medplum/mock": "5.1.
|
|
67
|
-
"@medplum/react-hooks": "5.1.
|
|
63
|
+
"@medplum/core": "5.1.6",
|
|
64
|
+
"@medplum/dosespot-core": "5.1.6",
|
|
65
|
+
"@medplum/fhirtypes": "5.1.6",
|
|
66
|
+
"@medplum/mock": "5.1.6",
|
|
67
|
+
"@medplum/react-hooks": "5.1.6",
|
|
68
68
|
"@testing-library/jest-dom": "6.9.1",
|
|
69
69
|
"@testing-library/react": "16.3.2",
|
|
70
70
|
"@types/node": "22.19.15",
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
"jsdom": "29.0.1",
|
|
75
75
|
"react": "19.2.4",
|
|
76
76
|
"react-dom": "19.2.4",
|
|
77
|
-
"vitest": "4.1.
|
|
77
|
+
"vitest": "4.1.2"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
|
-
"@medplum/core": "5.1.
|
|
81
|
-
"@medplum/dosespot-core": "5.1.
|
|
82
|
-
"@medplum/fhirtypes": "5.1.
|
|
83
|
-
"@medplum/react-hooks": "5.1.
|
|
80
|
+
"@medplum/core": "5.1.6",
|
|
81
|
+
"@medplum/dosespot-core": "5.1.6",
|
|
82
|
+
"@medplum/fhirtypes": "5.1.6",
|
|
83
|
+
"@medplum/react-hooks": "5.1.6",
|
|
84
84
|
"react": "^18.0.0 || ^19.0.0"
|
|
85
85
|
},
|
|
86
86
|
"engines": {
|