diff --git a/client/src/components/form-fields-changed-alert/form-fields-changed-alert.component.jsx b/client/src/components/form-fields-changed-alert/form-fields-changed-alert.component.jsx index 0f265d7db..3254c9f74 100644 --- a/client/src/components/form-fields-changed-alert/form-fields-changed-alert.component.jsx +++ b/client/src/components/form-fields-changed-alert/form-fields-changed-alert.component.jsx @@ -17,7 +17,7 @@ export default function FormsFieldChanged({ form, skipPrompt }) { const errors = form.getFieldsError().filter((e) => e.errors.length > 0); if (form.isFieldsTouched()) return ( - + ; -} +/** + * Formats a phone number for display purposes. If the input value is a valid phone number, it will be formatted in a + * national format (e.g., (123) 456-7890 for US/CA). If the input is not a valid phone number, it will be returned as-is. + * @param value + * @returns {*} + */ +const formatPhoneDisplayValue = (value) => { + if (!value) return value; + + try { + const parsedPhone = parsePhoneNumber(value, "CA"); + return parsedPhone?.isValid() ? parsedPhone.formatNational() : value; + } catch { + return value; + } +}; + +/** + * Generates a "tel:" URL for a phone number if it's valid. If the input value is a valid phone number, it will return a + * URL in the format "tel:+1234567890". If the input is not a valid phone number, it will attempt to trim whitespace and + * return a "tel:" URL with the raw value, or null if the trimmed value is empty. + * @param value + * @returns {string|null} + */ +const getPhoneActionHref = (value) => { + if (!value) return null; + + try { + const parsedPhone = parsePhoneNumber(value, "CA"); + if (parsedPhone?.isValid()) return `tel:${parsedPhone.number}`; + } catch { + // Fall back to the raw value below. + } + + const trimmedValue = String(value).trim(); + return trimmedValue ? `tel:${trimmedValue}` : null; +}; + +const FormItemPhone = forwardRef(function FormItemPhone( + { formatDisplayOnly = false, showPhoneAction = false, value, onBlur, onFocus, ...props }, + ref +) { + const [isFocused, setIsFocused] = useState(false); + const displayValue = useMemo(() => { + if (!formatDisplayOnly || isFocused) return value; + return formatPhoneDisplayValue(value); + }, [formatDisplayOnly, isFocused, value]); + const phoneActionHref = useMemo(() => (showPhoneAction ? getPhoneActionHref(value) : null), [showPhoneAction, value]); + + const input = ( + { + setIsFocused(true); + onFocus?.(event); + }} + onBlur={(event) => { + setIsFocused(false); + onBlur?.(event); + }} + /> + ); + + if (!showPhoneAction) return input; + + return ( + + {input} + {phoneActionHref ? ( +