Skip to main content
Glama
SmokingStatus.tsx4.43 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { Group, Modal, Radio, Stack, Text, UnstyledButton } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { HTTP_HL7_ORG, LOINC, SNOMED, createReference, formatCodeableConcept } from '@medplum/core'; import type { Encounter, Observation, Patient } from '@medplum/fhirtypes'; import { useMedplum } from '@medplum/react-hooks'; import type { JSX } from 'react'; import { useCallback, useState } from 'react'; import { Form } from '../Form/Form'; import { SubmitButton } from '../Form/SubmitButton'; import { CollapsibleSection } from './CollapsibleSection'; // Smoking Status widget // See: https://build.fhir.org/ig/HL7/US-Core/StructureDefinition-us-core-smokingstatus.html const smokingStatusOptions: Record<string, string> = { '266919005': 'Never smoked tobacco', '266927001': 'Tobacco smoking consumption unknown', '428041000124106': 'Occasional tobacco smoker', '428061000124105': 'Light tobacco smoker', '428071000124103': 'Heavy tobacco smoker', '449868002': 'Smokes tobacco daily', '77176002': 'Smoker', '8517006': 'Ex-smoker', }; export interface SmokingStatusProps { readonly patient: Patient; readonly encounter?: Encounter; readonly smokingStatus?: Observation; readonly onClickResource?: (resource: Observation) => void; } export function SmokingStatus(props: SmokingStatusProps): JSX.Element { const medplum = useMedplum(); const [smokingStatus, setSmokingStatus] = useState<Observation | undefined>(props.smokingStatus); const [opened, { open, close }] = useDisclosure(false); const handleSubmit = useCallback( (formData: Record<string, string>) => { medplum .createResource<Observation>({ resourceType: 'Observation', meta: { profile: [HTTP_HL7_ORG + '/fhir/us/core/StructureDefinition/us-core-smokingstatus'], }, status: 'final', category: [ { coding: [ { system: 'http://terminology.hl7.org/CodeSystem/observation-category', code: 'social-history', display: 'Social History', }, ], text: 'Social History', }, ], code: { coding: [ { system: LOINC, code: '72166-2', display: 'Tobacco smoking status', }, ], text: 'Tobacco smoking status', }, subject: createReference(props.patient), encounter: props.encounter ? createReference(props.encounter) : undefined, effectiveDateTime: new Date().toISOString(), valueCodeableConcept: { coding: [ { system: SNOMED, version: SNOMED + '/731000124108', code: formData.smokingStatus, }, ], text: smokingStatusOptions[formData.smokingStatus], }, }) .then((newSmokingStatus) => { setSmokingStatus(newSmokingStatus); close(); }) .catch(console.error); }, [medplum, props.patient, props.encounter, close] ); return ( <> <CollapsibleSection title="Smoking Status" onAdd={() => { open(); }} > {smokingStatus?.valueCodeableConcept ? ( <UnstyledButton data-testid="smoking-status-button" onClick={() => props.onClickResource?.(smokingStatus)}> <Text>{formatCodeableConcept(smokingStatus.valueCodeableConcept)}</Text> </UnstyledButton> ) : ( <Text>(none)</Text> )} </CollapsibleSection> <Modal opened={opened} onClose={close} title="Set Smoking Status"> <Form onSubmit={handleSubmit}> <Stack> <Radio.Group name="smokingStatus" label="Smoking Status" required> {Object.entries(smokingStatusOptions).map(([code, text]) => ( <Radio key={code} value={code} label={text} my="xs" /> ))} </Radio.Group> <Group justify="flex-end" gap={4} mt="md"> <SubmitButton>Save</SubmitButton> </Group> </Stack> </Form> </Modal> </> ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/medplum/medplum'

If you have feedback or need assistance with the MCP directory API, please join our Discord server