Product EngineeringFeaturesCritical CalloutFrontend

Callout Modal

Component hierarchy, interfaces, draft restore flow, API payload structure, and validation rules for the Critical Callout modal.

๐Ÿ‘ค Sachin Sharma๐Ÿ“… Updated: Apr 29, 2026๐Ÿท๏ธ feature๐Ÿท๏ธ frontend๐Ÿท๏ธ modal

Callout Modal

The callout modal is the primary action surface. It is opened by CriticalNotificationButton from any entry point and renders inside CriticalNotificationModal, which splits the view into an action panel (left) and a history panel (right).


Component hierarchy

Key files:

FilePurpose
CriticalNotificationModal.tsxContainer โ€” fetches data, owns tab layout
CriticalCalloutModal.tsxAction panel โ€” all form sections + submit
CriticalNotificationBody.tsxTab body switcher
CriticalCalloutLogs.tsxHistory timeline
CriticalNotificationButton.tsxTrigger button (reused on all surfaces)
interfaces.tsAll TypeScript interfaces
utils.tsRestore state, validate, structure logs, flag tag
helpers.tsxAPI call helpers

CriticalCalloutModal props

interface Props {
  orgId: number;
  isLoading: boolean;
  billData: JsonObject;
  onCloseModal: Function;
  userDetails: JsonObject;
  attemptedCallout?: AttemptedCallout;        // present if a draft exists
  setIsLoader: (isLoader: boolean) => void;
  criticalReports: CriticalReportParameter[]; // reports to act on
  onSuccess?: (reportIds: number[], status: number) => void;
}

Core interfaces

File: interfaces.ts

AttemptedCallout โ€” draft restore payload from API

interface AlreadyNotified {
  phone_call: { name: string; contact: string | number };
  fax:        { name: string; fax_number: string };
}

interface CriticalCalloutMeta {
  communication_methods: string[];   // ["email", "fax", "sms", "whatsapp"]
  notify_to_others: { name: string; email: string; fax: string; contactNumber: string };
  log_message: string;
  already_notified: AlreadyNotified; // phone/fax already-notified person details
  callout_for?: number[];            // testIDs included in draft
}

interface AttemptedCallout {
  recipients: string[];
  critical_callout_comment: string;
  critical_values_meta: CriticalValuesMeta[];
  critical_callout_meta: CriticalCalloutMeta;
}

RestoredCalloutState โ€” hydrated UI state

interface RestoredCalloutState {
  comments: string;
  alreadyInformed: boolean;
  selectedMethod: number[];          // COMMUNICATION_METHOD ids
  selectedReports: number[];         // labReportIds
  selectedRecipients: number[];      // ACCOUNT | PROVIDER | PATIENT
  informedVia: InformedViaState;
  notifyOthers: CriticalCalloutNotifyOther;
}

CriticalCalloutHistoryLogs โ€” history panel entry

interface CriticalCalloutHistoryLogs {
  meta: {
    is_draft?: boolean;              // true = Attempted ยท false = Completed
    callout_for?: string;
    callout_forFormatted?: string;   // computed by structureCalloutLogs()
    method?: string;
    methodFormatted?: string;        // includes "Notified via Phone Call/Fax" if notify_other present
    recipients?: string;
    recipientsFormatted?: string;    // includes already-informed contact details
    callout_done_by?: string;
    comment: string;
    bill_id?: number[];
    lab_report_ids?: number[];
    organization?: { fax: string; name: string; email: string };
    referral?:     { fax: string; name: string; email: string };
    patient?:      { name: string; email: string; contact: string };
    other?:        { fax: string; name: string; email: string; contact: string };
    notify_other?: InformedViaState; // already-notified person: phone + fax
  };
  labUserName: string;
  activityText: string;
  activityDate: string;
}

Draft restore flow

File: utils.ts โ€” getRestoredCalloutState()

When attemptedCallout is present (a draft exists for the bill), a useEffect hydrates the modal state before the user interacts.


Communication channels and submit payload

File: utils.ts โ€” prepareCalloutPayload() / constants.ts โ€” COMMUNICATION_METHODS

Four channels: Email, Fax, SMS, WhatsApp.

// notification object built by prepareCalloutPayload()
{
  is_patient, is_referral, is_organization,
  notified_by_fax, notified_by_call,
  comment,
  other: { enable, name, email, faxNumber, contactNumber },
  sendEmail:    selectedCommunicationMethod.includes(EMAIL),
  sendFax:      selectedCommunicationMethod.includes(FAX),
  sendSms:      selectedCommunicationMethod.includes(SMS),
  sendWhatsApp: selectedCommunicationMethod.includes(WHATSAPP),
}

Final API payload:

{
  is_draft: boolean,        // true = Save Draft, false = Notify Done
  bill_id: number,
  lab_report_ids: number[],
  notification: NotifyPayload,
}

Validation rules

File: utils.ts

Validation runs before every submit. Save Draft only requires at least one report to be selected โ€” all other rules apply to Notify and Mark as Done.

Four dedicated validator functions, each returning FailedValidation { isValid, errorMessage }:

validateNotifyOther(notifyOthers, selectedCommunicationMethod)

Runs when the Notify Others section is enabled.

ConditionError
name is empty"Please enter the name for 'Notify Other'."
Email method selected + invalid/empty email"Please enter a valid Email Id for 'Notify Other'."
SMS or WhatsApp method selected + invalid/empty contact"Please enter a valid Contact Number for 'Notify Other'."

validateAlreadyInformed(alreadyInformed, informedVia)

Runs when the Already Informed? toggle is on.

ConditionError
Neither phone nor fax enabled"Please enter either Fax or Phone details for 'Already Informed'."
Phone enabled + name empty or invalid number"Please enter Name and valid Contact Number for 'Notified via Phone Call'."
Fax enabled + name empty or invalid fax"Please enter Name and valid Fax Number for 'Notified via Fax'."

validateFax(criticalReports, selectedReports, selectedRecipients, orgDetails, referralData)

Runs when Fax is the selected communication method.

ConditionError
Any selected report is unsigned"Cannot send Fax as few reports are not signed"
Account selected + no fax number"Account do not have a Fax Number"
Account selected + invalid fax number"Invalid Account Fax Number"
Provider selected + no fax number"Provider do not have a Fax Number"
Provider selected + invalid fax number"Invalid Provider Fax Number"

validateEmail(selectedRecipients, orgDetails, referralData, userDetails)

Runs when Email is the selected communication method.

ConditionError
Account selected + no email"Account do not have an Email Id"
Account selected + invalid email"Invalid Account Email Id"
Provider selected + no email"Provider do not have an Email Id"
Provider selected + invalid email"Invalid Provider Email Id"
Patient selected + no email"Patient do not have an Email Id"
Patient selected + invalid email"Invalid Patient Email Id"

Summary โ€” what blocks each action

RuleDraftDone
At least one report selectedโœ“โœ“
At least one communication methodโ€”โœ“
Fax validation (unsigned reports, missing fax numbers)โ€”โœ“
Email validation (missing email addresses)โ€”โœ“
Notify Others validation (name, email, contact)โ€”โœ“
Already Informed validation (fax/phone details)โ€”โœ“
mandatory_comments on + empty commentโ€”โœ“

Critical value flag

File: utils.ts โ€” getCriticalValueTag()

Used to label each parameter in the report accordion.

InputOutput
value < lowerBound"Critical Low"
value > upperBound"Critical High"
Non-numeric value"Critical"

History panel (CriticalCalloutLogs)

File: CriticalCalloutLogs.tsx ยท Processor: utils.ts โ€” structureCalloutLogs()

Renders a VerticalTimeline on the right side of the modal. Entries are sorted most-recent first. structureCalloutLogs() handles both old (regex-parsed activityText) and new (meta.*) log formats for backward compatibility.

meta.is_draftIconEntry title
false / absentfaCheckCircle greenCallout Completed
truefaCircleXmark yellowCallout Attempted

Each entry displays: timestamp, performed by, callout for (test names), method, recipient(s), comment.

Already Notified person details in history

When a callout included an Already Informed entry (someone notified directly via phone or fax, outside digital channels), the history log reflects it by enriching the methodFormatted and recipientsFormatted computed fields:

meta.notify_other = {
  fax:   { enabled, name, number }   โ† "Notified via Fax"
  phone: { enabled, name, number }   โ† "Notified via Phone Call"
}
notify_other field presentAppended to methodFormattedAppended to recipientsFormatted
fax (non-empty)"Notified via Fax""{name} ({number})"
phone (non-empty)"Notified via Phone Call""{name} ({number})"

This means the history timeline shows the full picture of who was informed โ€” digital recipients (org/referral/patient/other) alongside physically-notified contacts โ€” all in one entry.

On this page