Skip to main content
Glama
AddressInput.tsx4.51 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { Group, NativeSelect, TextInput } from '@mantine/core'; import { trimTrailingEmptyElements } from '@medplum/core'; import type { Address } from '@medplum/fhirtypes'; import type { JSX } from 'react'; import { useContext, useMemo, useRef, useState } from 'react'; import { ElementsContext } from '../ElementsInput/ElementsInput.utils'; import type { ComplexTypeInputProps } from '../ResourcePropertyInput/ResourcePropertyInput.utils'; function getLine(address: Address, index: number): string { return address.line && address.line.length > index ? address.line[index] : ''; } function setLine(address: Address, index: number, str: string): Address { const line: string[] = address.line || []; while (line.length <= index) { line.push(''); } line[index] = str; return { ...address, line: trimTrailingEmptyElements(line) }; } export type AddressInputProps = ComplexTypeInputProps<Address>; export function AddressInput(props: AddressInputProps): JSX.Element { const [value, setValue] = useState<Address>(props.defaultValue || {}); const valueRef = useRef<Address>(value); valueRef.current = value; const { getExtendedProps } = useContext(ElementsContext); const [useProps, typeProps, line1Props, line2Props, cityProps, stateProps, postalCodeProps] = useMemo( () => ['use', 'type', 'line1', 'line2', 'city', 'state', 'postalCode'].map((field) => getExtendedProps(props.path + '.' + field) ), [getExtendedProps, props.path] ); // TODO{profiles} is it worth the complexity of subbing in an autocomplete input when // a binding is defined in a profile? If so, it should go in a new wrapper around TextInput // e.g. US Core Patient Profile function setValueWrapper(newValue: Address): void { setValue(newValue); if (props.onChange) { props.onChange(newValue); } } function setUse(use: 'home' | 'work' | 'temp' | 'old' | 'billing'): void { setValueWrapper({ ...valueRef.current, use }); } function setType(type: 'postal' | 'physical' | 'both'): void { setValueWrapper({ ...valueRef.current, type }); } function setLine1(line1: string): void { setValueWrapper(setLine(valueRef.current || {}, 0, line1)); } function setLine2(line2: string): void { setValueWrapper(setLine(valueRef.current || {}, 1, line2)); } function setCity(city: string): void { setValueWrapper({ ...valueRef.current, city }); } function setState(state: string): void { setValueWrapper({ ...valueRef.current, state }); } function setPostalCode(postalCode: string): void { setValueWrapper({ ...valueRef.current, postalCode }); } return ( <Group gap="xs" wrap="nowrap" grow> <NativeSelect disabled={props.disabled || useProps?.readonly} data-testid="address-use" defaultValue={value.use} onChange={(e) => setUse(e.currentTarget.value as 'home' | 'work' | 'temp' | 'old' | 'billing')} data={['', 'home', 'work', 'temp', 'old', 'billing']} /> <NativeSelect disabled={props.disabled || typeProps?.readonly} data-testid="address-type" defaultValue={value.type} onChange={(e) => setType(e.currentTarget.value as 'postal' | 'physical' | 'both')} data={['', 'postal', 'physical', 'both']} /> <TextInput disabled={props.disabled || line1Props?.readonly} placeholder="Line 1" defaultValue={getLine(value, 0)} onChange={(e) => setLine1(e.currentTarget.value)} /> <TextInput disabled={props.disabled || line2Props?.readonly} placeholder="Line 2" defaultValue={getLine(value, 1)} onChange={(e) => setLine2(e.currentTarget.value)} /> <TextInput disabled={props.disabled || cityProps?.readonly} placeholder="City" defaultValue={value.city} onChange={(e) => setCity(e.currentTarget.value)} /> <TextInput disabled={props.disabled || stateProps?.readonly} placeholder="State" defaultValue={value.state} onChange={(e) => setState(e.currentTarget.value)} /> <TextInput disabled={props.disabled || postalCodeProps?.readonly} placeholder="Postal Code" defaultValue={value.postalCode} onChange={(e) => setPostalCode(e.currentTarget.value)} /> </Group> ); }

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