@tellescope/react-components 1.238.0 → 1.239.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/Forms/forms.d.ts.map +1 -1
- package/lib/cjs/Forms/forms.js +29 -27
- package/lib/cjs/Forms/forms.js.map +1 -1
- package/lib/cjs/Forms/forms.v2.d.ts.map +1 -1
- package/lib/cjs/Forms/forms.v2.js +29 -27
- package/lib/cjs/Forms/forms.v2.js.map +1 -1
- package/lib/cjs/Forms/hooks.d.ts +25 -1
- package/lib/cjs/Forms/hooks.d.ts.map +1 -1
- package/lib/cjs/Forms/hooks.js +40 -2
- package/lib/cjs/Forms/hooks.js.map +1 -1
- package/lib/cjs/Forms/inputs.d.ts +6 -2
- package/lib/cjs/Forms/inputs.d.ts.map +1 -1
- package/lib/cjs/Forms/inputs.js +109 -11
- package/lib/cjs/Forms/inputs.js.map +1 -1
- package/lib/cjs/Forms/inputs.v2.d.ts +2 -1
- package/lib/cjs/Forms/inputs.v2.d.ts.map +1 -1
- package/lib/cjs/Forms/inputs.v2.js +26 -9
- package/lib/cjs/Forms/inputs.v2.js.map +1 -1
- package/lib/cjs/Forms/localization.d.ts.map +1 -1
- package/lib/cjs/Forms/localization.js +7 -0
- package/lib/cjs/Forms/localization.js.map +1 -1
- package/lib/cjs/inputs_shared.d.ts +6 -2
- package/lib/cjs/inputs_shared.d.ts.map +1 -1
- package/lib/cjs/inputs_shared.js +4 -3
- package/lib/cjs/inputs_shared.js.map +1 -1
- package/lib/esm/Forms/forms.d.ts.map +1 -1
- package/lib/esm/Forms/forms.js +30 -28
- package/lib/esm/Forms/forms.js.map +1 -1
- package/lib/esm/Forms/forms.v2.d.ts.map +1 -1
- package/lib/esm/Forms/forms.v2.js +30 -28
- package/lib/esm/Forms/forms.v2.js.map +1 -1
- package/lib/esm/Forms/hooks.d.ts +25 -1
- package/lib/esm/Forms/hooks.d.ts.map +1 -1
- package/lib/esm/Forms/hooks.js +38 -1
- package/lib/esm/Forms/hooks.js.map +1 -1
- package/lib/esm/Forms/inputs.d.ts +6 -2
- package/lib/esm/Forms/inputs.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.js +107 -10
- package/lib/esm/Forms/inputs.js.map +1 -1
- package/lib/esm/Forms/inputs.v2.d.ts +2 -1
- package/lib/esm/Forms/inputs.v2.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.v2.js +25 -9
- package/lib/esm/Forms/inputs.v2.js.map +1 -1
- package/lib/esm/Forms/localization.d.ts.map +1 -1
- package/lib/esm/Forms/localization.js +7 -0
- package/lib/esm/Forms/localization.js.map +1 -1
- package/lib/esm/inputs_shared.d.ts +6 -2
- package/lib/esm/inputs_shared.d.ts.map +1 -1
- package/lib/esm/inputs_shared.js +4 -3
- package/lib/esm/inputs_shared.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/Forms/forms.tsx +9 -2
- package/src/Forms/forms.v2.tsx +9 -2
- package/src/Forms/hooks.tsx +57 -2
- package/src/Forms/inputs.tsx +223 -9
- package/src/Forms/inputs.v2.tsx +29 -11
- package/src/Forms/localization.ts +8 -0
- package/src/inputs_shared.tsx +6 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellescope/react-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.239.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"@reduxjs/toolkit": "1.9.0",
|
|
48
48
|
"@stripe/react-stripe-js": "2.9.0",
|
|
49
49
|
"@stripe/stripe-js": "1.52.1",
|
|
50
|
-
"@tellescope/constants": "1.
|
|
51
|
-
"@tellescope/sdk": "1.
|
|
52
|
-
"@tellescope/types-client": "1.
|
|
53
|
-
"@tellescope/types-models": "1.
|
|
54
|
-
"@tellescope/types-utilities": "1.
|
|
55
|
-
"@tellescope/utilities": "1.
|
|
56
|
-
"@tellescope/validation": "1.
|
|
50
|
+
"@tellescope/constants": "1.239.1",
|
|
51
|
+
"@tellescope/sdk": "1.239.1",
|
|
52
|
+
"@tellescope/types-client": "1.239.1",
|
|
53
|
+
"@tellescope/types-models": "1.239.1",
|
|
54
|
+
"@tellescope/types-utilities": "1.239.1",
|
|
55
|
+
"@tellescope/utilities": "1.239.1",
|
|
56
|
+
"@tellescope/validation": "1.239.1",
|
|
57
57
|
"@typescript-eslint/eslint-plugin": "4.33.0",
|
|
58
58
|
"@typescript-eslint/parser": "4.33.0",
|
|
59
59
|
"css-to-react-native": "3.0.0",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
84
84
|
"react-native": "^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.71.0"
|
|
85
85
|
},
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "917ce97bdcb5e162c56bc8cc8eb41eb347d1f0a3",
|
|
87
87
|
"publishConfig": {
|
|
88
88
|
"access": "public"
|
|
89
89
|
}
|
package/src/Forms/forms.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
|
|
2
2
|
import { Button, CircularProgress, FileBlob, FileUploadHandler, Flex, LinearProgress, LoadingButton, Modal, Paper, Styled, Typography, form_display_text_for_language, useFileUpload, useFormResponses, useSession } from "../index"
|
|
3
3
|
import { useListForFormFields, useOrganizationTheme, useTellescopeForm, WithOrganizationTheme, Response, FileResponse, NextFieldLogicOptions } from "./hooks"
|
|
4
4
|
import { ChangeHandler, FormInputs } from "./types"
|
|
5
|
-
import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInput, BelugaPatientPreferenceInput, BridgeEligibilityInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, TimezoneInput, defaultButtonStyles } from "./inputs"
|
|
5
|
+
import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInput, BelugaPatientPreferenceInput, BridgeEligibilityInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PharmacySearchInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, TimezoneInput, defaultButtonStyles } from "./inputs"
|
|
6
6
|
import { PRIMARY_HEX } from "@tellescope/constants"
|
|
7
7
|
import { FormResponse, FormField, Form, Enduser } from "@tellescope/types-client"
|
|
8
8
|
import { FormResponseAnswerFileValue, OrganizationTheme } from "@tellescope/types-models"
|
|
@@ -192,6 +192,7 @@ export const QuestionForField = ({
|
|
|
192
192
|
const Conditions = customInputs?.['Conditions'] ?? ConditionsInput
|
|
193
193
|
const RichText = customInputs?.['Rich Text'] ?? RichTextInput
|
|
194
194
|
const BelugaPatientPreference = customInputs?.['Beluga Patient Preference'] ?? BelugaPatientPreferenceInput
|
|
195
|
+
const PharmacySearch = customInputs?.['Pharmacy Search'] ?? PharmacySearchInput
|
|
195
196
|
|
|
196
197
|
const validationMessage = validateField(field)
|
|
197
198
|
|
|
@@ -344,7 +345,7 @@ export const QuestionForField = ({
|
|
|
344
345
|
<Signature enduser={enduser} field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'signature'>} form={form}/>
|
|
345
346
|
)
|
|
346
347
|
: field.type === 'multiple_choice' ? (
|
|
347
|
-
<MultipleChoice field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'multiple_choice'>} form={form}/>
|
|
348
|
+
<MultipleChoice field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'multiple_choice'>} form={form} responses={responses} enduser={enduser}/>
|
|
348
349
|
)
|
|
349
350
|
: field.type === 'Dropdown' ? (
|
|
350
351
|
<Dropdown field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Dropdown'>} form={form}/>
|
|
@@ -378,6 +379,12 @@ export const QuestionForField = ({
|
|
|
378
379
|
onChange={onFieldChange as ChangeHandler<'Bridge Eligibility'>}
|
|
379
380
|
/>
|
|
380
381
|
)
|
|
382
|
+
: field.type === 'Pharmacy Search' ? (
|
|
383
|
+
<PharmacySearch field={field} value={value.answer.value as any} form={form}
|
|
384
|
+
enduser={enduser} responses={responses}
|
|
385
|
+
onChange={onFieldChange as ChangeHandler<'Pharmacy Search'>}
|
|
386
|
+
/>
|
|
387
|
+
)
|
|
381
388
|
: field.type === 'rating' ? (
|
|
382
389
|
<Rating field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'rating'>} form={form}/>
|
|
383
390
|
)
|
package/src/Forms/forms.v2.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
|
|
2
2
|
import { Button, CircularProgress, FileBlob, FileUploadHandler, Flex, LinearProgress, LoadingButton, Modal, Paper, Styled, Typography, WithTheme, form_display_text_for_language, useFileUpload, useFormResponses, useSession } from "../index"
|
|
3
3
|
import { useListForFormFields, useOrganizationTheme, useTellescopeForm, WithOrganizationTheme, Response, FileResponse, NextFieldLogicOptions } from "./hooks"
|
|
4
4
|
import { ChangeHandler, FormInputs } from "./types"
|
|
5
|
-
import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInput, BelugaPatientPreferenceInput, BridgeEligibilityInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, TimezoneInput, defaultButtonStyles } from "./inputs.v2"
|
|
5
|
+
import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInput, BelugaPatientPreferenceInput, BridgeEligibilityInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PharmacySearchInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, TimezoneInput, defaultButtonStyles } from "./inputs.v2"
|
|
6
6
|
import { PRIMARY_HEX } from "@tellescope/constants"
|
|
7
7
|
import { FormResponse, FormField, Form, Enduser } from "@tellescope/types-client"
|
|
8
8
|
import { FormResponseAnswerFileValue, OrganizationTheme } from "@tellescope/types-models"
|
|
@@ -185,6 +185,7 @@ export const QuestionForField = ({
|
|
|
185
185
|
const Conditions = customInputs?.['Conditions'] ?? ConditionsInput
|
|
186
186
|
const RichText = customInputs?.['Rich Text'] ?? RichTextInput
|
|
187
187
|
const BelugaPatientPreference = customInputs?.['Beluga Patient Preference'] ?? BelugaPatientPreferenceInput
|
|
188
|
+
const PharmacySearch = customInputs?.['Pharmacy Search'] ?? PharmacySearchInput
|
|
188
189
|
|
|
189
190
|
const validationMessage = validateField(field)
|
|
190
191
|
|
|
@@ -338,7 +339,7 @@ export const QuestionForField = ({
|
|
|
338
339
|
<Signature enduser={enduser} field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'signature'>} form={form}/>
|
|
339
340
|
)
|
|
340
341
|
: field.type === 'multiple_choice' ? (
|
|
341
|
-
<MultipleChoice field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'multiple_choice'>} form={form}/>
|
|
342
|
+
<MultipleChoice field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'multiple_choice'>} form={form} responses={responses} enduser={enduser}/>
|
|
342
343
|
)
|
|
343
344
|
: field.type === 'Dropdown' ? (
|
|
344
345
|
<Dropdown field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Dropdown'>} form={form}/>
|
|
@@ -372,6 +373,12 @@ export const QuestionForField = ({
|
|
|
372
373
|
onChange={onFieldChange as ChangeHandler<'Bridge Eligibility'>}
|
|
373
374
|
/>
|
|
374
375
|
)
|
|
376
|
+
: field.type === 'Pharmacy Search' ? (
|
|
377
|
+
<PharmacySearch field={field} value={value.answer.value as any} form={form}
|
|
378
|
+
enduser={enduser} responses={responses}
|
|
379
|
+
onChange={onFieldChange as ChangeHandler<'Pharmacy Search'>}
|
|
380
|
+
/>
|
|
381
|
+
)
|
|
375
382
|
: field.type === 'rating' ? (
|
|
376
383
|
<Rating field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'rating'>} form={form}/>
|
|
377
384
|
)
|
package/src/Forms/hooks.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { ChangeHandler, FormFieldNode } from "./types"
|
|
|
4
4
|
import { DatabaseRecord, Enduser, Form, FormField, FormResponse } from "@tellescope/types-client"
|
|
5
5
|
import { phoneValidator } from "@tellescope/validation"
|
|
6
6
|
import { FileBlob, Indexable } from "@tellescope/types-utilities"
|
|
7
|
-
import { CompoundFilter, EnduserRelationship, FormCustomization, FormResponseAnswerAddress, FormResponseAnswerFileValue, FormResponseValue, FormResponseValueAnswer, OrganizationTheme, PreviousFormCompoundLogic, PreviousFormFieldType, Timezone, TIMEZONES } from "@tellescope/types-models"
|
|
7
|
+
import { CompoundFilter, EnduserRelationship, FormCustomization, FormFieldOptionDetails, FormResponseAnswerAddress, FormResponseAnswerFileValue, FormResponseValue, FormResponseValueAnswer, OrganizationTheme, PreviousFormCompoundLogic, PreviousFormFieldType, Timezone, TIMEZONES } from "@tellescope/types-models"
|
|
8
8
|
import { WithTheme, contact_is_valid, useAddGTMTag, useFileUpload, useFormFields, useFormResponses, useResolvedSession, value_is_loaded } from "../index"
|
|
9
9
|
import ReactGA from "react-ga4";
|
|
10
10
|
|
|
@@ -679,7 +679,7 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
679
679
|
type: f.type,
|
|
680
680
|
value: (
|
|
681
681
|
existing_response_if_compatible(existingResponses, f) ?? (
|
|
682
|
-
(f.type === 'Insurance' || f.type === 'Address' || f.type === 'file' || f.type === 'signature' || f.type === 'multiple_choice' || f.type === 'Dropdown' || f.type === 'Table Input' || f.type === 'Database Select' || f.type === 'Medications')
|
|
682
|
+
(f.type === 'Insurance' || f.type === 'Address' || f.type === 'file' || f.type === 'signature' || f.type === 'multiple_choice' || f.type === 'Dropdown' || f.type === 'Table Input' || f.type === 'Database Select' || f.type === 'Medications' || f.type === 'Pharmacy Search')
|
|
683
683
|
? undefined
|
|
684
684
|
: f.type === 'Question Group'
|
|
685
685
|
? f.options?.subFields
|
|
@@ -1686,3 +1686,58 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1686
1686
|
isAutoAdvancing,
|
|
1687
1687
|
}
|
|
1688
1688
|
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* Hook for conditional visibility of multiple choice options.
|
|
1692
|
+
* Computes visible choices based on showCondition and provides an onChange wrapper
|
|
1693
|
+
* that auto-filters hidden choices from selections (event-driven, not useEffect).
|
|
1694
|
+
*/
|
|
1695
|
+
export const useConditionalChoices = ({
|
|
1696
|
+
choices,
|
|
1697
|
+
optionDetails,
|
|
1698
|
+
responses,
|
|
1699
|
+
enduser,
|
|
1700
|
+
form,
|
|
1701
|
+
onChange,
|
|
1702
|
+
fieldId,
|
|
1703
|
+
otherString,
|
|
1704
|
+
}: {
|
|
1705
|
+
choices?: string[]
|
|
1706
|
+
optionDetails?: FormFieldOptionDetails[]
|
|
1707
|
+
responses?: Response[]
|
|
1708
|
+
enduser?: Partial<Enduser>
|
|
1709
|
+
form?: Form
|
|
1710
|
+
onChange: (value: string[], fieldId: string) => void
|
|
1711
|
+
fieldId: string
|
|
1712
|
+
otherString: string
|
|
1713
|
+
}) => {
|
|
1714
|
+
// Compute visible choices based on showCondition
|
|
1715
|
+
const visibleChoices = useMemo(() => {
|
|
1716
|
+
if (!choices) return []
|
|
1717
|
+
return choices.filter((choice, index) => {
|
|
1718
|
+
const optionDetail = optionDetails?.find(d => d.option === choice) ?? optionDetails?.[index]
|
|
1719
|
+
if (!optionDetail?.showCondition || object_is_empty(optionDetail.showCondition)) {
|
|
1720
|
+
return true
|
|
1721
|
+
}
|
|
1722
|
+
return responses_satisfy_conditions(responses || [], optionDetail.showCondition, {
|
|
1723
|
+
dateOfBirth: enduser?.dateOfBirth,
|
|
1724
|
+
gender: enduser?.gender,
|
|
1725
|
+
state: enduser?.state,
|
|
1726
|
+
form,
|
|
1727
|
+
activeResponses: responses,
|
|
1728
|
+
})
|
|
1729
|
+
})
|
|
1730
|
+
}, [choices, optionDetails, responses, enduser, form])
|
|
1731
|
+
|
|
1732
|
+
// Wrap onChange to auto-filter hidden choices (event-driven)
|
|
1733
|
+
const handleChange = useCallback((newValue: string[], fieldId: string) => {
|
|
1734
|
+
// Filter out any hidden choices from the new value
|
|
1735
|
+
// Allow through: visible choices, the "other" string, and values not in the choices array (custom "other" text)
|
|
1736
|
+
const filteredValue = newValue.filter(v =>
|
|
1737
|
+
visibleChoices.includes(v) || v === otherString || !choices?.includes(v)
|
|
1738
|
+
)
|
|
1739
|
+
onChange(filteredValue, fieldId)
|
|
1740
|
+
}, [visibleChoices, otherString, choices, onChange])
|
|
1741
|
+
|
|
1742
|
+
return { visibleChoices, handleChange }
|
|
1743
|
+
}
|
package/src/Forms/inputs.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { FormInputProps } from "./types"
|
|
|
5
5
|
import { useDropzone } from "react-dropzone"
|
|
6
6
|
import { CANVAS_TITLE, BRIDGE_TITLE, EMOTII_TITLE, INSURANCE_RELATIONSHIPS, INSURANCE_RELATIONSHIPS_CANVAS, PRIMARY_HEX, RELATIONSHIP_TYPES, TELLESCOPE_GENDERS } from "@tellescope/constants"
|
|
7
7
|
import { MM_DD_YYYY_to_YYYY_MM_DD, capture_is_supported, downloadFile, emit_gtm_event, first_letter_capitalized, form_response_value_to_string, format_stripe_subscription_interval, getLocalTimezone, getPublicFileURL, mm_dd_yyyy, object_is_empty, replace_enduser_template_values, responses_satisfy_conditions, truncate_string, update_local_storage, user_display_name } from "@tellescope/utilities"
|
|
8
|
-
import { Address, DatabaseSelectResponse, Enduser, EnduserRelationship, FormResponseValue, InsuranceRelationship, MedicationResponse, MultipleChoiceOptions, FormFieldOptionDetails, TellescopeGender, TIMEZONES_USA } from "@tellescope/types-models"
|
|
8
|
+
import { Address, DatabaseSelectResponse, Enduser, EnduserRelationship, FormResponseValue, InsuranceRelationship, MedicationResponse, MultipleChoiceOptions, FormFieldOptionDetails, Pharmacy, TellescopeGender, TIMEZONES_USA } from "@tellescope/types-models"
|
|
9
9
|
import { VALID_STATES, emailValidator, phoneValidator } from "@tellescope/validation"
|
|
10
10
|
import Slider from '@mui/material/Slider';
|
|
11
11
|
import LinearProgress from '@mui/material/LinearProgress';
|
|
@@ -25,6 +25,7 @@ import { Elements, PaymentElement, useStripe, useElements, EmbeddedCheckout, Emb
|
|
|
25
25
|
import { loadStripe } from '@stripe/stripe-js';
|
|
26
26
|
import { CheckCircleOutline, Delete, Edit, ExpandMore } from "@mui/icons-material"
|
|
27
27
|
import { WYSIWYG } from "./wysiwyg"
|
|
28
|
+
import { useConditionalChoices, Response } from "./hooks"
|
|
28
29
|
|
|
29
30
|
// Bridge Eligibility - shared variable for storing most recent eligibility userIds
|
|
30
31
|
const bridgeEligibilityResult = {
|
|
@@ -1417,6 +1418,207 @@ export const BridgeEligibilityInput = ({ field, value, onChange, responses, endu
|
|
|
1417
1418
|
)
|
|
1418
1419
|
}
|
|
1419
1420
|
|
|
1421
|
+
export const PharmacySearchInput = ({
|
|
1422
|
+
field,
|
|
1423
|
+
value: rawValue,
|
|
1424
|
+
onChange,
|
|
1425
|
+
responses,
|
|
1426
|
+
enduser,
|
|
1427
|
+
form,
|
|
1428
|
+
...props
|
|
1429
|
+
}: Omit<FormInputProps<'string'>, 'value' | 'onChange'> & {
|
|
1430
|
+
value: Pharmacy | undefined,
|
|
1431
|
+
onChange: (v: Pharmacy | undefined, fieldId: string) => void
|
|
1432
|
+
}) => {
|
|
1433
|
+
const value = rawValue as Pharmacy | undefined
|
|
1434
|
+
const session = useResolvedSession()
|
|
1435
|
+
|
|
1436
|
+
// Get initial ZIP code from responses or enduser data
|
|
1437
|
+
const getInitialZipCode = () => {
|
|
1438
|
+
// Check Address field responses first
|
|
1439
|
+
const addressResponse = responses?.find(r =>
|
|
1440
|
+
r.answer?.type === 'Address' && (r.answer?.value as { zipCode?: string })?.zipCode
|
|
1441
|
+
)
|
|
1442
|
+
if (addressResponse?.answer?.type === 'Address') {
|
|
1443
|
+
const addressValue = addressResponse.answer.value as { zipCode?: string }
|
|
1444
|
+
if (addressValue?.zipCode) {
|
|
1445
|
+
return addressValue.zipCode
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
// Fall back to enduser.zipCode
|
|
1450
|
+
return enduser?.zipCode || ''
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
const [zipCode, setZipCode] = useState(getInitialZipCode())
|
|
1454
|
+
const [loading, setLoading] = useState(false)
|
|
1455
|
+
const [error, setError] = useState<string>()
|
|
1456
|
+
const [pharmacies, setPharmacies] = useState<Pharmacy[]>([])
|
|
1457
|
+
const [hasSearched, setHasSearched] = useState(false)
|
|
1458
|
+
|
|
1459
|
+
const searchPharmacies = useCallback(async () => {
|
|
1460
|
+
if (!zipCode || zipCode.length !== 5) {
|
|
1461
|
+
setError(form_display_text_for_language(form, 'Please enter a valid 5-digit ZIP code'))
|
|
1462
|
+
return
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
setLoading(true)
|
|
1466
|
+
setError(undefined)
|
|
1467
|
+
setHasSearched(true)
|
|
1468
|
+
|
|
1469
|
+
try {
|
|
1470
|
+
const { data } = await session.api.integrations.proxy_read({
|
|
1471
|
+
integration: 'ScriptSure',
|
|
1472
|
+
type: 'pharmacy-search',
|
|
1473
|
+
query: JSON.stringify({ zipCode }),
|
|
1474
|
+
})
|
|
1475
|
+
|
|
1476
|
+
setPharmacies(data || [])
|
|
1477
|
+
|
|
1478
|
+
if (!data?.length) {
|
|
1479
|
+
setError(form_display_text_for_language(form, 'No pharmacies found for this ZIP code'))
|
|
1480
|
+
}
|
|
1481
|
+
} catch (err: any) {
|
|
1482
|
+
setError(err?.message || form_display_text_for_language(form, 'Failed to search pharmacies'))
|
|
1483
|
+
setPharmacies([])
|
|
1484
|
+
} finally {
|
|
1485
|
+
setLoading(false)
|
|
1486
|
+
}
|
|
1487
|
+
}, [session, zipCode, form])
|
|
1488
|
+
|
|
1489
|
+
const handleSelectPharmacy = (pharmacy: Pharmacy) => {
|
|
1490
|
+
onChange({
|
|
1491
|
+
npi: pharmacy.npi,
|
|
1492
|
+
ncpdpId: pharmacy.ncpdpId,
|
|
1493
|
+
businessName: pharmacy.businessName,
|
|
1494
|
+
primaryTelephone: pharmacy.primaryTelephone || '',
|
|
1495
|
+
addressLine1: pharmacy.addressLine1,
|
|
1496
|
+
city: pharmacy.city,
|
|
1497
|
+
stateProvince: pharmacy.stateProvince,
|
|
1498
|
+
postalCode: pharmacy.postalCode,
|
|
1499
|
+
}, field.id)
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
const formatPharmacyAddress = (p: Pharmacy) => {
|
|
1503
|
+
const parts = [p.addressLine1, p.city, p.stateProvince, p.postalCode].filter(Boolean)
|
|
1504
|
+
return parts.join(', ')
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
return (
|
|
1508
|
+
<Grid container direction="column" spacing={2}>
|
|
1509
|
+
{/* ZIP Code Input */}
|
|
1510
|
+
<Grid item>
|
|
1511
|
+
<Grid container spacing={2} alignItems="flex-end">
|
|
1512
|
+
<Grid item xs={8} sm={6}>
|
|
1513
|
+
<TextField
|
|
1514
|
+
fullWidth
|
|
1515
|
+
size="small"
|
|
1516
|
+
label={form_display_text_for_language(form, "ZIP Code")}
|
|
1517
|
+
value={zipCode}
|
|
1518
|
+
onChange={(e) => setZipCode(e.target.value.replace(/\D/g, '').slice(0, 5))}
|
|
1519
|
+
InputProps={defaultInputProps}
|
|
1520
|
+
placeholder="12345"
|
|
1521
|
+
required={!field.isOptional}
|
|
1522
|
+
/>
|
|
1523
|
+
</Grid>
|
|
1524
|
+
<Grid item xs={4} sm={6}>
|
|
1525
|
+
<LoadingButton
|
|
1526
|
+
variant="contained"
|
|
1527
|
+
onClick={searchPharmacies}
|
|
1528
|
+
submitText={form_display_text_for_language(form, "Search")}
|
|
1529
|
+
submittingText={form_display_text_for_language(form, "Searching...")}
|
|
1530
|
+
submitting={loading}
|
|
1531
|
+
disabled={zipCode.length !== 5 || loading}
|
|
1532
|
+
style={{ width: '100%', marginTop: 0 }}
|
|
1533
|
+
/>
|
|
1534
|
+
</Grid>
|
|
1535
|
+
</Grid>
|
|
1536
|
+
</Grid>
|
|
1537
|
+
|
|
1538
|
+
{/* Error Message */}
|
|
1539
|
+
{error && (
|
|
1540
|
+
<Grid item>
|
|
1541
|
+
<Typography color="error" sx={{ fontSize: 14 }}>
|
|
1542
|
+
{error}
|
|
1543
|
+
</Typography>
|
|
1544
|
+
</Grid>
|
|
1545
|
+
)}
|
|
1546
|
+
|
|
1547
|
+
{/* Selected Pharmacy Display */}
|
|
1548
|
+
{value && (
|
|
1549
|
+
<Grid item>
|
|
1550
|
+
<Paper elevation={2} sx={{ p: 2, backgroundColor: '#e8f5e9' }}>
|
|
1551
|
+
<Grid container alignItems="center" justifyContent="space-between">
|
|
1552
|
+
<Grid item xs>
|
|
1553
|
+
<Typography variant="subtitle1" fontWeight="bold">
|
|
1554
|
+
<CheckCircleOutline sx={{ color: 'success.main', mr: 1, verticalAlign: 'middle' }} />
|
|
1555
|
+
{value.businessName}
|
|
1556
|
+
</Typography>
|
|
1557
|
+
<Typography variant="body2" color="text.secondary">
|
|
1558
|
+
{formatPharmacyAddress(value)}
|
|
1559
|
+
</Typography>
|
|
1560
|
+
{value.primaryTelephone && (
|
|
1561
|
+
<Typography variant="body2" color="text.secondary">
|
|
1562
|
+
{value.primaryTelephone}
|
|
1563
|
+
</Typography>
|
|
1564
|
+
)}
|
|
1565
|
+
</Grid>
|
|
1566
|
+
<Grid item>
|
|
1567
|
+
<MuiIconButton onClick={() => onChange(undefined as any, field.id)} size="small">
|
|
1568
|
+
<CancelIcon />
|
|
1569
|
+
</MuiIconButton>
|
|
1570
|
+
</Grid>
|
|
1571
|
+
</Grid>
|
|
1572
|
+
</Paper>
|
|
1573
|
+
</Grid>
|
|
1574
|
+
)}
|
|
1575
|
+
|
|
1576
|
+
{/* Search Results */}
|
|
1577
|
+
{!value && hasSearched && pharmacies.length > 0 && (
|
|
1578
|
+
<Grid item>
|
|
1579
|
+
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
|
1580
|
+
{pharmacies.length} {form_display_text_for_language(form, pharmacies.length === 1 ? 'pharmacy found' : 'pharmacies found')}
|
|
1581
|
+
</Typography>
|
|
1582
|
+
<Box sx={{ maxHeight: 300, overflow: 'auto' }}>
|
|
1583
|
+
{pharmacies.map((pharmacy, index) => (
|
|
1584
|
+
<Paper
|
|
1585
|
+
key={`${pharmacy.ncpdpId}-${index}`}
|
|
1586
|
+
elevation={1}
|
|
1587
|
+
sx={{
|
|
1588
|
+
p: 1.5,
|
|
1589
|
+
mb: 1,
|
|
1590
|
+
cursor: 'pointer',
|
|
1591
|
+
'&:hover': { backgroundColor: '#f5f5f5' },
|
|
1592
|
+
}}
|
|
1593
|
+
onClick={() => handleSelectPharmacy(pharmacy)}
|
|
1594
|
+
>
|
|
1595
|
+
<Typography variant="subtitle2" fontWeight="medium">
|
|
1596
|
+
{pharmacy.businessName}
|
|
1597
|
+
</Typography>
|
|
1598
|
+
<Typography variant="body2" color="text.secondary">
|
|
1599
|
+
{formatPharmacyAddress(pharmacy)}
|
|
1600
|
+
</Typography>
|
|
1601
|
+
{pharmacy.primaryTelephone && (
|
|
1602
|
+
<Typography variant="caption" color="text.secondary">
|
|
1603
|
+
{pharmacy.primaryTelephone}
|
|
1604
|
+
</Typography>
|
|
1605
|
+
)}
|
|
1606
|
+
</Paper>
|
|
1607
|
+
))}
|
|
1608
|
+
</Box>
|
|
1609
|
+
</Grid>
|
|
1610
|
+
)}
|
|
1611
|
+
|
|
1612
|
+
{/* Loading State */}
|
|
1613
|
+
{loading && (
|
|
1614
|
+
<Grid item>
|
|
1615
|
+
<LinearProgress />
|
|
1616
|
+
</Grid>
|
|
1617
|
+
)}
|
|
1618
|
+
</Grid>
|
|
1619
|
+
)
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1420
1622
|
const HourSelector = (props : { value: string, onChange: (v: string) => void }) => (
|
|
1421
1623
|
<StringSelector {...props}
|
|
1422
1624
|
options={Array(12).fill('').map((_, i) => (i + 1) <= 9 ? `0${i + 1}` : (i + 1).toString())}
|
|
@@ -1998,7 +2200,7 @@ const multipleChoiceItemSx: SxProps = {
|
|
|
1998
2200
|
},
|
|
1999
2201
|
}
|
|
2000
2202
|
|
|
2001
|
-
export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: FormInputProps<'multiple_choice'>) => {
|
|
2203
|
+
export const MultipleChoiceInput = ({ field, form, value: _value, onChange, responses, enduser }: FormInputProps<'multiple_choice'>) => {
|
|
2002
2204
|
const value = typeof _value === 'string' ? [_value] : _value // if loading existingResponses, allows them to be a string
|
|
2003
2205
|
const { choices, radio, other, optionDetails } = field.options as MultipleChoiceOptions
|
|
2004
2206
|
const [expandedDescriptions, setExpandedDescriptions] = useState<Record<number, boolean>>({})
|
|
@@ -2007,6 +2209,18 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
2007
2209
|
const enteringOtherStringRef = React.useRef('') // if typing otherString as prefix of a checkbox value, don't auto-select
|
|
2008
2210
|
const otherString = value?.find(v => v === enteringOtherStringRef.current || !(choices ?? [])?.find(c => c === v)) ?? ''
|
|
2009
2211
|
|
|
2212
|
+
// Conditional visibility for choices
|
|
2213
|
+
const { visibleChoices, handleChange } = useConditionalChoices({
|
|
2214
|
+
choices,
|
|
2215
|
+
optionDetails,
|
|
2216
|
+
responses: responses as Response[] | undefined,
|
|
2217
|
+
enduser,
|
|
2218
|
+
form,
|
|
2219
|
+
onChange,
|
|
2220
|
+
fieldId: field.id,
|
|
2221
|
+
otherString,
|
|
2222
|
+
})
|
|
2223
|
+
|
|
2010
2224
|
const getDescriptionForChoice = useCallback((choice: string) => {
|
|
2011
2225
|
return optionDetails?.find(detail => detail.option === choice)?.description
|
|
2012
2226
|
}, [optionDetails])
|
|
@@ -2031,7 +2245,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
2031
2245
|
defaultValue="female"
|
|
2032
2246
|
name={`radio-group-${field.id}`}
|
|
2033
2247
|
>
|
|
2034
|
-
{
|
|
2248
|
+
{visibleChoices.map((c, i) => {
|
|
2035
2249
|
const description = getDescriptionForChoice(c)
|
|
2036
2250
|
const hasDescription = !!description
|
|
2037
2251
|
const isExpanded = expandedDescriptions[i]
|
|
@@ -2043,7 +2257,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
2043
2257
|
sx={{ ...multipleChoiceItemSx, flex: 1, marginLeft: '0px' }}
|
|
2044
2258
|
checked={!!value?.includes(c) && c !== otherString}
|
|
2045
2259
|
control={
|
|
2046
|
-
<Radio onClick={() =>
|
|
2260
|
+
<Radio onClick={() => handleChange(value?.includes(c) ? [] : [c], field.id)} />
|
|
2047
2261
|
}
|
|
2048
2262
|
label={
|
|
2049
2263
|
<Box sx={{ display: 'flex', alignItems: 'center', width: '100%' }}>
|
|
@@ -2083,7 +2297,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
2083
2297
|
</RadioGroup>
|
|
2084
2298
|
</FormControl>
|
|
2085
2299
|
) : (
|
|
2086
|
-
|
|
2300
|
+
visibleChoices.map((c, i) => {
|
|
2087
2301
|
const description = getDescriptionForChoice(c)
|
|
2088
2302
|
const hasDescription = !!description
|
|
2089
2303
|
const isExpanded = expandedDescriptions[i]
|
|
@@ -2104,7 +2318,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
2104
2318
|
if ((e.target as HTMLElement).closest('.expand-button')) {
|
|
2105
2319
|
return
|
|
2106
2320
|
}
|
|
2107
|
-
|
|
2321
|
+
handleChange(
|
|
2108
2322
|
(
|
|
2109
2323
|
value?.includes(c)
|
|
2110
2324
|
? (
|
|
@@ -2174,9 +2388,9 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
2174
2388
|
// onClick={() => !otherChecked && handleOtherChecked()} // allow click to enable when disabled
|
|
2175
2389
|
onChange={e => {
|
|
2176
2390
|
enteringOtherStringRef.current = e.target.value
|
|
2177
|
-
|
|
2391
|
+
handleChange(
|
|
2178
2392
|
(
|
|
2179
|
-
radio
|
|
2393
|
+
radio
|
|
2180
2394
|
? (
|
|
2181
2395
|
e.target.value.trim()
|
|
2182
2396
|
? [e.target.value]
|
|
@@ -2186,7 +2400,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
2186
2400
|
e.target.value.trim()
|
|
2187
2401
|
// remove existing other string (if exists) and append new one
|
|
2188
2402
|
? [...(value ?? []).filter(v => v !== otherString), e.target.value]
|
|
2189
|
-
: value
|
|
2403
|
+
: (value ?? []).filter(v => v !== otherString)
|
|
2190
2404
|
)
|
|
2191
2405
|
),
|
|
2192
2406
|
field.id,
|
package/src/Forms/inputs.v2.tsx
CHANGED
|
@@ -23,6 +23,7 @@ import LanguageIcon from '@mui/icons-material/Language';
|
|
|
23
23
|
|
|
24
24
|
import { CheckCircleOutline, Delete, Edit, UploadFile } from "@mui/icons-material"
|
|
25
25
|
import { WYSIWYG } from "./wysiwyg"
|
|
26
|
+
import { useConditionalChoices, Response } from "./hooks"
|
|
26
27
|
|
|
27
28
|
export const LanguageSelect = ({ value, ...props }: { value: string, onChange: (s: string) => void}) => (
|
|
28
29
|
<Grid container alignItems="center" justifyContent={"center"} wrap="nowrap" spacing={1}>
|
|
@@ -544,8 +545,8 @@ export const NumberInput = ({ field, value, onChange, form, ...props }: FormInpu
|
|
|
544
545
|
)
|
|
545
546
|
}
|
|
546
547
|
|
|
547
|
-
// InsuranceInput, BridgeEligibilityInput, and AppointmentBookingInput logic is shared with inputs.tsx to avoid duplication
|
|
548
|
-
import { InsuranceInput as SharedInsuranceInput, BridgeEligibilityInput as SharedBridgeEligibilityInput, AppointmentBookingInput as SharedAppointmentBookingInput } from './inputs'
|
|
548
|
+
// InsuranceInput, BridgeEligibilityInput, PharmacySearchInput, and AppointmentBookingInput logic is shared with inputs.tsx to avoid duplication
|
|
549
|
+
import { InsuranceInput as SharedInsuranceInput, BridgeEligibilityInput as SharedBridgeEligibilityInput, PharmacySearchInput as SharedPharmacySearchInput, AppointmentBookingInput as SharedAppointmentBookingInput } from './inputs'
|
|
549
550
|
|
|
550
551
|
// Wrap the shared InsuranceInput component with v2-specific props
|
|
551
552
|
export const InsuranceInput = (props: FormInputProps<'Insurance'>) => {
|
|
@@ -557,6 +558,11 @@ export const BridgeEligibilityInput = (props: FormInputProps<'Bridge Eligibility
|
|
|
557
558
|
return <SharedBridgeEligibilityInput {...props} inputProps={defaultInputProps} />
|
|
558
559
|
}
|
|
559
560
|
|
|
561
|
+
// Wrap the shared PharmacySearchInput component with v2-specific props
|
|
562
|
+
export const PharmacySearchInput = (props: FormInputProps<'Pharmacy Search'>) => {
|
|
563
|
+
return <SharedPharmacySearchInput {...props} />
|
|
564
|
+
}
|
|
565
|
+
|
|
560
566
|
|
|
561
567
|
const StringSelector = ({ options, value, onChange, required, getDisplayValue, ...props } : {
|
|
562
568
|
options: string[]
|
|
@@ -1154,7 +1160,7 @@ export const FilesInput = ({ value, onChange, field, existingFileName, uploading
|
|
|
1154
1160
|
)
|
|
1155
1161
|
}
|
|
1156
1162
|
|
|
1157
|
-
export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: FormInputProps<'multiple_choice'>) => {
|
|
1163
|
+
export const MultipleChoiceInput = ({ field, form, value: _value, onChange, responses, enduser }: FormInputProps<'multiple_choice'>) => {
|
|
1158
1164
|
const value = typeof _value === 'string' ? [_value] : _value // if loading existingResponses, allows them to be a string
|
|
1159
1165
|
const { choices, radio, other, optionDetails } = field.options as MultipleChoiceOptions
|
|
1160
1166
|
|
|
@@ -1162,6 +1168,18 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1162
1168
|
const enteringOtherStringRef = React.useRef('') // if typing otherString as prefix of a checkbox value, don't auto-select
|
|
1163
1169
|
const otherString = value?.find(v => v === enteringOtherStringRef.current || !(choices ?? [])?.find(c => c === v)) ?? ''
|
|
1164
1170
|
|
|
1171
|
+
// Conditional visibility for choices
|
|
1172
|
+
const { visibleChoices, handleChange } = useConditionalChoices({
|
|
1173
|
+
choices,
|
|
1174
|
+
optionDetails,
|
|
1175
|
+
responses: responses as Response[] | undefined,
|
|
1176
|
+
enduser,
|
|
1177
|
+
form,
|
|
1178
|
+
onChange,
|
|
1179
|
+
fieldId: field.id,
|
|
1180
|
+
otherString,
|
|
1181
|
+
})
|
|
1182
|
+
|
|
1165
1183
|
// Get primary color from form customization or use default
|
|
1166
1184
|
const primaryColor = form?.customization?.primaryColor ?? '#798ED0'
|
|
1167
1185
|
|
|
@@ -1179,7 +1197,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1179
1197
|
defaultValue="female"
|
|
1180
1198
|
name={`radio-group-${field.id}`}
|
|
1181
1199
|
>
|
|
1182
|
-
{
|
|
1200
|
+
{visibleChoices.map((c, i) => {
|
|
1183
1201
|
const description = getDescriptionForChoice(c)
|
|
1184
1202
|
const hasDescription = !!description
|
|
1185
1203
|
const isSelected = !!value?.includes(c) && c !== otherString
|
|
@@ -1203,7 +1221,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1203
1221
|
backgroundColor: (theme: any) => `${theme.palette.primary.main}14`,
|
|
1204
1222
|
},
|
|
1205
1223
|
}}
|
|
1206
|
-
onClick={() =>
|
|
1224
|
+
onClick={() => handleChange(value?.includes(c) ? [] : [c], field.id)}
|
|
1207
1225
|
>
|
|
1208
1226
|
<Typography component="span" sx={{ flex: 1, color: 'primary.main', fontSize: 13, fontWeight: 600 }}>{c}</Typography>
|
|
1209
1227
|
</Box>
|
|
@@ -1216,11 +1234,11 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1216
1234
|
)}
|
|
1217
1235
|
</Box>
|
|
1218
1236
|
)
|
|
1219
|
-
})}
|
|
1237
|
+
})}
|
|
1220
1238
|
</RadioGroup>
|
|
1221
1239
|
</FormControl>
|
|
1222
1240
|
) : (
|
|
1223
|
-
|
|
1241
|
+
visibleChoices.map((c, i) => {
|
|
1224
1242
|
const description = getDescriptionForChoice(c)
|
|
1225
1243
|
const hasDescription = !!description
|
|
1226
1244
|
|
|
@@ -1236,7 +1254,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1236
1254
|
boxSizing: 'border-box'
|
|
1237
1255
|
}}
|
|
1238
1256
|
onClick={(e) => {
|
|
1239
|
-
|
|
1257
|
+
handleChange(
|
|
1240
1258
|
(
|
|
1241
1259
|
value?.includes(c)
|
|
1242
1260
|
? (
|
|
@@ -1287,9 +1305,9 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1287
1305
|
// onClick={() => !otherChecked && handleOtherChecked()} // allow click to enable when disabled
|
|
1288
1306
|
onChange={e => {
|
|
1289
1307
|
enteringOtherStringRef.current = e.target.value
|
|
1290
|
-
|
|
1308
|
+
handleChange(
|
|
1291
1309
|
(
|
|
1292
|
-
radio
|
|
1310
|
+
radio
|
|
1293
1311
|
? (
|
|
1294
1312
|
e.target.value.trim()
|
|
1295
1313
|
? [e.target.value]
|
|
@@ -1299,7 +1317,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1299
1317
|
e.target.value.trim()
|
|
1300
1318
|
// remove existing other string (if exists) and append new one
|
|
1301
1319
|
? [...(value ?? []).filter(v => v !== otherString), e.target.value]
|
|
1302
|
-
: value
|
|
1320
|
+
: (value ?? []).filter(v => v !== otherString)
|
|
1303
1321
|
)
|
|
1304
1322
|
),
|
|
1305
1323
|
field.id,
|
|
@@ -112,9 +112,17 @@ const SPANISH_TRANSLATIONS: Record<string, string> = {
|
|
|
112
112
|
|
|
113
113
|
// Medications Search
|
|
114
114
|
'Search': 'Buscar',
|
|
115
|
+
'Searching...': 'Buscando...',
|
|
115
116
|
'Drug Select': 'Seleccionar Medicamento',
|
|
116
117
|
'Other Drug': 'Otro Medicamento',
|
|
117
118
|
|
|
119
|
+
// Pharmacy Search
|
|
120
|
+
'pharmacies found': 'farmacias encontradas',
|
|
121
|
+
'pharmacy found': 'farmacia encontrada',
|
|
122
|
+
'Please enter a valid 5-digit ZIP code': 'Por favor ingrese un código postal válido de 5 dígitos',
|
|
123
|
+
'No pharmacies found for this ZIP code': 'No se encontraron farmacias para este código postal',
|
|
124
|
+
'Failed to search pharmacies': 'Error al buscar farmacias',
|
|
125
|
+
|
|
118
126
|
// Height Input
|
|
119
127
|
'Feet': 'Pies',
|
|
120
128
|
'Inches': 'Pulgadas',
|