import React, { useState, useEffect } from 'react'; import { TextareaControl } from "../ui/textarea-control"; import { Card, CardHeader, CardBody, CardDivider } from '../ui/wp-card'; import { Elevation } from '../ui/elevation'; import { InputControl } from '../ui/input-control'; import { Divider } from '../ui/divider'; import { DismissibleAlert } from '../ui/dismissible-alert'; import { Heading } from '../ui/heading'; import { Flex, FlexItem } from '../ui/flex'; import { Spacer } from '../ui/spacer'; import { TabPanel } from '../ui/tab-panel'; import { useFormContext, Controller, useFieldArray } from 'react-hook-form'; import { IValueSet, useAuthServiceContext, useValueSetServiceContext } from '../../services'; import { FhirCode, FhirCodeableConcept, FhirReference, FhirReferenceCollection } from '../../components'; import { useFhirAdverseEventBroadcast, useFhirAdverseEvents, useFhirAllergyIntolerances, useFhirConditions, useFhirDevices, useFhirEncounters, useFhirFamilyMemberHistories, useFhirImmunizations, useFhirLocations, useFhirMedicationAdministrations, useFhirMedicationStatements, useFhirObservations, useFhirPractitioners, useFhirProcedures } from '../../hooks'; import FhirValueSetSearch from '../FhirValueSetSearch/FhirValueSetSearch.tsx'; import { PlusCircle, Trash2 } from 'lucide-react'; import { FhirResource } from 'fhir/r4'; interface FhirImmunizationEvaluationProps { elevated?: boolean; disabled?: boolean; enableInlineActions?: boolean; } const SuspectEntityInstanceReferences: React.FC<{ index: number; disabled: boolean; enableInlineActions: boolean }> = ({ index, disabled, enableInlineActions = true }) => { const { control } = useFormContext(); const itemReferenceFieldArray = useFieldArray({ control, name: `suspectEntity.${index}.instance` }); const { devicesList } = useFhirDevices(); const { immunizationsList } = useFhirImmunizations(); const { proceduresList } = useFhirProcedures(); const { medicationAdministrationsList } = useFhirMedicationAdministrations(); const { medicationStatementsList } = useFhirMedicationStatements(); return ( { switch (referenceType) { case 'Immunization': return immunizationsList; case 'Procedure': return proceduresList; case 'MedicationAdministration': return medicationAdministrationsList; case 'MedicationStatement': return medicationStatementsList; case 'Device': return devicesList; default: return []; } }} required={false} disabled={disabled} multiple={false} enableInlineActions={enableInlineActions}/> ); }; export const FhirAdverseEvent: React.FC = ({ elevated = true, disabled = false, enableInlineActions = true }) => { const { control, watch, setValue, getValues } = useFormContext(); const { fetchValueSet, valueSetUrls } = useValueSetServiceContext(); const { userRole, USER_ROLES } = useAuthServiceContext(); const isPatientRole = [USER_ROLES.PATIENT, USER_ROLES.RELATED_PERSON].includes(userRole as string); const [loading, setLoading] = useState(false); // value sets const [adverseEventActuality, setAdverseEventActuality] = useState([]); const [adverseEventCategory, setAdverseEventCategory] = useState([]); const [adverseEventSeriousness, setAdverseEventSeriousness] = useState([]); const [adverseEventSeverity, setAdverseEventSeverity] = useState([]); const [adverseEventOutcome, setAdverseEventOutcome] = useState([]); const [adverseEventCausalityAssess, setAdverseEventCausalityAssess] = useState([]); const [adverseEventCausalityMethod, setAdverseEventCausalityMethod] = useState([]); const spacerMargin = '24px'; useFhirAdverseEvents(); useFhirAdverseEventBroadcast(); const { practitionersList } = useFhirPractitioners(); const { locationsList } = useFhirLocations(); const { encountersList } = useFhirEncounters(); const { conditionsList } = useFhirConditions(); const { devicesList } = useFhirDevices(); const { immunizationsList } = useFhirImmunizations(); const { proceduresList } = useFhirProcedures(); const { observationsList } = useFhirObservations(); const { allergyIntolerancesList } = useFhirAllergyIntolerances(); const { familyMemberHistoriesList } = useFhirFamilyMemberHistories(); const contributorFieldArray = useFieldArray({ control, name: 'contributor' }); const suspectEntityFieldArray = useFieldArray({ control, name: 'suspectEntity' }); const subjectMedicalHistoryFieldArray = useFieldArray({ control, name: 'subjectMedicalHistory' }); watch('suspectEntity'); useEffect(() => { const loadValueSets = async () => { setLoading(true); try { const [ adverseEventActualityValueSet, adverseEventCategoryValueSet, adverseEventSeriousnessValueSet, adverseEventSeverityValueSet, adverseEventOutcomeValueSet, adverseEventCausalityAssessValueSet, adverseEventCausalityMethodValueSet ] = await Promise.all([ fetchValueSet(valueSetUrls.adverseEventActuality), fetchValueSet(valueSetUrls.adverseEventCategory), fetchValueSet(valueSetUrls.adverseEventSeriousness), fetchValueSet(valueSetUrls.adverseEventSeverity), fetchValueSet(valueSetUrls.adverseEventOutcome), fetchValueSet(valueSetUrls.adverseEventCausalityAssess), fetchValueSet(valueSetUrls.adverseEventCausalityMethod) ]); setAdverseEventActuality(adverseEventActualityValueSet); setAdverseEventCategory(adverseEventCategoryValueSet); setAdverseEventSeriousness(adverseEventSeriousnessValueSet); setAdverseEventSeverity(adverseEventSeverityValueSet); setAdverseEventOutcome(adverseEventOutcomeValueSet); setAdverseEventCausalityAssess(adverseEventCausalityAssessValueSet); setAdverseEventCausalityMethod(adverseEventCausalityMethodValueSet); } catch (err) { console.error('Error loading value sets:', err); } finally { setLoading(false); } }; loadValueSets(); }, [fetchValueSet, valueSetUrls]); const addSuspectEntity = () => { suspectEntityFieldArray.append({ instance: null, causality: [] }); }; const removeSuspectEntity = (index: number) => { suspectEntityFieldArray.remove(index); }; const addCausality = (entityIndex: number) => { const path = `suspectEntity.${entityIndex}.causality`; const causality = getValues(path) || []; setValue(path, [...causality, { assessment: null, productRelatedness: '', author: null, method: null }]); }; const removeCausality = (entityIndex: number, causalityIndex: number) => { const path = `suspectEntity.${entityIndex}.causality`; const causality = getValues(path) || []; causality.splice(causalityIndex, 1); setValue(path, causality); }; return ( {elevated && } Details {/* event */} {/* category */} {/* actuality */} {/* encounter */} {!isPatientRole && <> } {/* location */} {/* resultingCondition */} {(tab) => { // details if (tab.name === 'details') { return (
{/* date */} ( )}/> {/* detected */} ( )}/> {/* recordedDate */} ( )}/> {/* seriousness */} {/* severity */} {/* outcome */}
); } // entities if (tab.name === 'entities') { return (
{suspectEntityFieldArray.fields.length === 0 && ( <> No suspect entities added yet. )} {suspectEntityFieldArray.fields.map((field, index) => (

Suspect Entity {index + 1}

Specific entity that caused the adverse event Information on the possible cause of the event {(getValues(`suspectEntity.${index}.causality`) || []).length === 0 && ( <> No causality assessments added yet. )} {(getValues(`suspectEntity.${index}.causality`) || []).map((_causality, causalityIndex) => (

Causality Assessment {causalityIndex + 1}

{/* assessment */} {/* productRelatedness */} ( )}/> {/* method */}
))} {(getValues(`suspectEntity.${index}.causality`) || []).length > 0 && ( )}
))} {suspectEntityFieldArray.fields.length > 0 && ( )}
); } // contributors if (tab.name === 'contributors') { return (
{/* contributor */} { switch (referenceType) { case 'Practitioner': return practitionersList.map(p => p.practitioner); case 'Device': return devicesList; default: return []; } }} required={false} disabled={disabled} multiple={true} enableInlineActions={enableInlineActions}/>
); } // medicalHistory if (tab.name === 'medicalHistory') { return (
{/* subjectMedicalHistory */} { switch (referenceType) { case 'Condition': return conditionsList; case 'Observation': return observationsList; case 'AllergyIntolerance': return allergyIntolerancesList; case 'FamilyMemberHistory': return familyMemberHistoriesList; case 'Immunization': return immunizationsList; case 'Procedure': return proceduresList; default: return []; } }} required={false} disabled={disabled} multiple={true} enableInlineActions={enableInlineActions}/>
); } }}
); }; export default FhirAdverseEvent;