Skip to main content
Glama
SendFaxPage.tsx5.41 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { Button, FileInput, Stack, TextInput, Title } from '@mantine/core'; import { showNotification } from '@mantine/notifications'; import { createReference, isNotFound, normalizeErrorString, OperationOutcomeError } from '@medplum/core'; import type { Communication, Organization } from '@medplum/fhirtypes'; import { Document, useMedplum, useMedplumProfile } from '@medplum/react'; import { IconFile, IconSend } from '@tabler/icons-react'; import { useState } from 'react'; import type { JSX } from 'react'; interface SendFaxForm { recipientName: string; faxNumber: string; file: File | null; } export function SendFaxPage(): JSX.Element { const medplum = useMedplum(); const profile = useMedplumProfile(); const [formData, setFormData] = useState<SendFaxForm>({ recipientName: '', faxNumber: '', file: null, }); const [sending, setSending] = useState(false); const handleSendFax = async (): Promise<void> => { // Validation if (!formData.recipientName.trim()) { showNotification({ title: 'Error', message: 'Recipient name is required', color: 'red' }); return; } if (!formData.faxNumber.trim()) { showNotification({ title: 'Error', message: 'Fax number is required', color: 'red' }); return; } const digits = formData.faxNumber.replace(/\D/g, ''); if (digits.length < 10) { showNotification({ title: 'Error', message: 'Fax number must have at least 10 digits', color: 'red' }); return; } if (!formData.file) { showNotification({ title: 'Error', message: 'Please select a file to fax', color: 'red' }); return; } if (profile?.resourceType !== 'Practitioner') { showNotification({ title: 'Error', message: 'Invalid practitioner profile', color: 'red' }); return; } setSending(true); try { // Step 1: Upload the file as an attachment (creates Binary resource) const attachment = await medplum.createAttachment({ data: formData.file, contentType: formData.file.type, filename: formData.file.name, }); // Step 2: Create the recipient Organization const recipient = await medplum.createResource<Organization>({ resourceType: 'Organization', name: formData.recipientName, contact: [{ telecom: [{ system: 'fax', value: formData.faxNumber }] }], }); // Step 3: Create the Communication with proper references const communication = await medplum.createResource<Communication>({ resourceType: 'Communication', status: 'in-progress', category: [{ coding: [{ system: 'http://medplum.com/fhir/CodeSystem/fax-direction', code: 'outbound' }] }], medium: [ { coding: [ { system: 'http://terminology.hl7.org/CodeSystem/v3-ParticipationMode', code: 'FAXWRIT', }, ], }, ], sender: createReference(profile), recipient: [createReference(recipient)], payload: [{ contentAttachment: attachment }], }); // Step 4: Call the $send-efax operation const sendEfaxUrl = medplum.fhirUrl('Communication', '$send-efax'); try { await medplum.post(sendEfaxUrl, communication); } catch (efaxErr) { // Check if this is a 404 error for the efax operation if (efaxErr instanceof OperationOutcomeError && isNotFound(efaxErr.outcome)) { showNotification({ color: 'red', title: 'Error', message: 'Efax integration not setup contact Medplum Support', }); return; } // Re-throw if it's not a 404 throw efaxErr; } showNotification({ color: 'green', title: 'Success', message: `Fax sent successfully`, }); } catch (err) { showNotification({ color: 'red', title: 'Error', message: normalizeErrorString(err), }); } finally { setSending(false); } }; return ( <Document> <Title>Send Fax</Title> <Stack gap="lg" mt="lg"> <TextInput label="Organization Name" placeholder="Enter organization name" value={formData.recipientName} onChange={(e) => setFormData((prev) => ({ ...prev, recipientName: e.target.value }))} required /> <TextInput label="Fax Number" placeholder="+1 (555) 123-4567" value={formData.faxNumber} onChange={(e) => setFormData((prev) => ({ ...prev, faxNumber: e.target.value }))} required /> <FileInput label="Document to Fax" placeholder="Click to select file" accept=".pdf,.png,.jpg,.jpeg" leftSection={<IconFile size={16} />} value={formData.file} onChange={(file) => setFormData((prev) => ({ ...prev, file }))} required /> <Button onClick={handleSendFax} leftSection={<IconSend size={16} />} loading={sending} disabled={!formData.recipientName || !formData.faxNumber || !formData.file} > Send Fax </Button> </Stack> </Document> ); }

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