Skip to content

(feat) Display patient phone number in appointment details and Excel export#2201

Open
gabriel090 wants to merge 2 commits intoopenmrs:mainfrom
gabriel090:phone_number_appt
Open

(feat) Display patient phone number in appointment details and Excel export#2201
gabriel090 wants to merge 2 commits intoopenmrs:mainfrom
gabriel090:phone_number_appt

Conversation

@gabriel090
Copy link
Contributor

@gabriel090 gabriel090 commented Jan 16, 2026

Requirements

  • This PR has a title that briefly describes the work done including the ticket number. If there is a ticket, make sure your PR title includes a conventional commit label. See existing PR titles for inspiration.
  • My work is based on designs, which are linked or shown either in the Jira ticket or the description below.
  • My work includes tests or is validated by existing tests.

Summary

This ticket adds patient phone number display functionality to the appointments module. Phone numbers will be visible in the appointment details view and will be automatically included when downloading appointments to Excel. The implementation retrieves complete patient contact information from the FHIR2 API and handles cases where patients have multiple phone numbers by displaying them separated by commas.

phone_number

When a phone number is unavailable, the system will display a placeholder to maintain consistent formatting.

phone_2

This enhancement improves the usability of appointment management by making patient contact information readily accessible for both on-screen viewing and offline reference through Excel exports.

Screenshots

Related Issue

Other

@gabriel090
Copy link
Contributor Author

ping @ibacher @makombe

import { formatDate, formatDatetime, usePatient } from '@openmrs/esm-framework';
import { usePatientAppointmentHistory } from '../../hooks/usePatientAppointmentHistory';
import { getGender } from '../../helpers';
import { getGender, getPatientPhoneNumberByUuid, getPatientPhoneNumber } from '../../helpers';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { getGender, getPatientPhoneNumberByUuid, getPatientPhoneNumber } from '../../helpers';
import { getGender, getPatientPhoneNumberByUuid } from '../../helpers';

This is unused.

? patientInfo.telecom.map((telecomObj) => telecomObj?.value).join(', ')
: '';
const patientInfo = await fetchPatientFromFhir2(appointment.patient.uuid);
const phoneNumber = getPatientPhoneNumber(patientInfo);
Copy link
Member

@denniskigen denniskigen Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const phoneNumber = getPatientPhoneNumber(patientInfo);
const patientInfo = includePhoneNumbers ? await fetchPatientFromFhir2(appointment.patient.uuid) : null;
const phoneNumber = includePhoneNumbers ? getPatientPhoneNumber(patientInfo) : '';

The includePhoneNumberInExcelSpreadsheet config flag is read but ignored, causing phone numbers to always be exported and FHIR2 patient data to always be fetched. This is a behavior regression and privacy risk.

'Appointment type': appointment.service?.name,
Date: formatDate(new Date(appointment.startDateTime), { mode: 'wide' }),
...(includePhoneNumbers ? { 'Telephone number': phoneNumber } : {}),
'Phone number': phoneNumber || '--',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Phone number': phoneNumber || '--',
...(includePhoneNumbers ? { 'Phone number': phoneNumber || '--' } : {}),

const AppointmentDetails: React.FC<AppointmentDetailsProps> = ({ appointment }) => {
const { t } = useTranslation();
const [isEnabledQuery, setIsEnabledQuery] = useState(false);
const [phoneNumber, setPhoneNumber] = useState<string>('');
Copy link
Member

@denniskigen denniskigen Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const [phoneNumber, setPhoneNumber] = useState<string>('');

The component already has patient data via usePatient; the extra FHIR2 call is redundant and its result is never used. Additionally, telecom can include non-phone values (email, fax), which would be mislabeled as "Phone number".

Comment on lines +26 to +34
// Fetch phone number
useEffect(() => {
const fetchPhoneNumber = async () => {
const phone = await getPatientPhoneNumberByUuid(appointment.patient.uuid);
setPhoneNumber(phone);
};

fetchPhoneNumber();
}, [appointment.patient.uuid]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Fetch phone number
useEffect(() => {
const fetchPhoneNumber = async () => {
const phone = await getPatientPhoneNumberByUuid(appointment.patient.uuid);
setPhoneNumber(phone);
};
fetchPhoneNumber();
}, [appointment.patient.uuid]);
const phoneNumber = getPatientPhoneNumber(patient ?? null);

Comment on lines +64 to +67
{patient && patient?.telecom && patient.telecom.length > 0 ? (
<div className={styles.labelContainer}>
<p className={styles.labelBold}>{t('phoneNumber', 'Phone number')}: </p>
<p className={styles.label}>{patient.telecom.map((contact) => contact.value).join(', ')}</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{patient && patient?.telecom && patient.telecom.length > 0 ? (
<div className={styles.labelContainer}>
<p className={styles.labelBold}>{t('phoneNumber', 'Phone number')}: </p>
<p className={styles.label}>{patient.telecom.map((contact) => contact.value).join(', ')}</p>
{phoneNumber ? (
<div className={styles.labelContainer}>
<p className={styles.labelBold}>{t('phoneNumber', 'Phone number')}: </p>
<p className={styles.label}>{phoneNumber}</p>

Comment on lines +160 to +168
export async function getPatientPhoneNumberByUuid(patientUuid: string): Promise<string> {
try {
const patient = await fetchPatientFromFhir2(patientUuid);
return getPatientPhoneNumber(patient);
} catch (error) {
console.error('Error getting patient phone number:', error);
return '';
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export async function getPatientPhoneNumberByUuid(patientUuid: string): Promise<string> {
try {
const patient = await fetchPatientFromFhir2(patientUuid);
return getPatientPhoneNumber(patient);
} catch (error) {
console.error('Error getting patient phone number:', error);
return '';
}
}

After the suggested component change, getPatientPhoneNumberByUuid is no longer used anywhere and should be removed.

@denniskigen denniskigen changed the title Add phone number in appointment download excel using FHIR2 API (feat) Display patient phone number in appointment details and Excel export Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants