@tellescope/react-components 1.230.0 → 1.230.2
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 +32 -28
- package/lib/cjs/Forms/forms.v2.js.map +1 -1
- package/lib/cjs/Forms/hooks.d.ts.map +1 -1
- package/lib/cjs/Forms/hooks.js +30 -4
- package/lib/cjs/Forms/hooks.js.map +1 -1
- package/lib/cjs/Forms/index.d.ts +1 -0
- package/lib/cjs/Forms/index.d.ts.map +1 -1
- package/lib/cjs/Forms/index.js +3 -1
- package/lib/cjs/Forms/index.js.map +1 -1
- package/lib/cjs/Forms/inputs.d.ts +1 -0
- package/lib/cjs/Forms/inputs.d.ts.map +1 -1
- package/lib/cjs/Forms/inputs.js +30 -3
- package/lib/cjs/Forms/inputs.js.map +1 -1
- package/lib/cjs/Forms/inputs.v2.d.ts +1 -0
- package/lib/cjs/Forms/inputs.v2.d.ts.map +1 -1
- package/lib/cjs/Forms/inputs.v2.js +33 -4
- package/lib/cjs/Forms/inputs.v2.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 +33 -29
- package/lib/esm/Forms/forms.v2.js.map +1 -1
- package/lib/esm/Forms/hooks.d.ts.map +1 -1
- package/lib/esm/Forms/hooks.js +31 -5
- package/lib/esm/Forms/hooks.js.map +1 -1
- package/lib/esm/Forms/index.d.ts +1 -0
- package/lib/esm/Forms/index.d.ts.map +1 -1
- package/lib/esm/Forms/index.js +1 -0
- package/lib/esm/Forms/index.js.map +1 -1
- package/lib/esm/Forms/inputs.d.ts +1 -0
- package/lib/esm/Forms/inputs.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.js +29 -3
- package/lib/esm/Forms/inputs.js.map +1 -1
- package/lib/esm/Forms/inputs.v2.d.ts +1 -0
- package/lib/esm/Forms/inputs.v2.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.v2.js +32 -4
- package/lib/esm/Forms/inputs.v2.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/Forms/forms.tsx +5 -1
- package/src/Forms/forms.v2.tsx +23 -3
- package/src/Forms/hooks.tsx +55 -8
- package/src/Forms/index.ts +2 -1
- package/src/Forms/inputs.tsx +160 -2
- package/src/Forms/inputs.v2.tsx +171 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellescope/react-components",
|
|
3
|
-
"version": "1.230.
|
|
3
|
+
"version": "1.230.2",
|
|
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.6.2",
|
|
48
48
|
"@stripe/react-stripe-js": "^2.9.0",
|
|
49
49
|
"@stripe/stripe-js": "^1.52.1",
|
|
50
|
-
"@tellescope/constants": "1.230.
|
|
51
|
-
"@tellescope/sdk": "1.230.
|
|
52
|
-
"@tellescope/types-client": "1.230.
|
|
53
|
-
"@tellescope/types-models": "1.230.
|
|
54
|
-
"@tellescope/types-utilities": "1.230.
|
|
55
|
-
"@tellescope/utilities": "1.230.
|
|
56
|
-
"@tellescope/validation": "1.230.
|
|
50
|
+
"@tellescope/constants": "1.230.2",
|
|
51
|
+
"@tellescope/sdk": "1.230.2",
|
|
52
|
+
"@tellescope/types-client": "1.230.2",
|
|
53
|
+
"@tellescope/types-models": "1.230.2",
|
|
54
|
+
"@tellescope/types-utilities": "1.230.2",
|
|
55
|
+
"@tellescope/utilities": "1.230.2",
|
|
56
|
+
"@tellescope/validation": "1.230.2",
|
|
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": "0bc1e80c698398e1c62c4f026fa76475883f2396",
|
|
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, 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, 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"
|
|
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"
|
|
@@ -190,6 +190,7 @@ export const QuestionForField = ({
|
|
|
190
190
|
const Allergies = customInputs?.['Allergies'] ?? AllergiesInput
|
|
191
191
|
const Conditions = customInputs?.['Conditions'] ?? ConditionsInput
|
|
192
192
|
const RichText = customInputs?.['Rich Text'] ?? RichTextInput
|
|
193
|
+
const BelugaPatientPreference = customInputs?.['Beluga Patient Preference'] ?? BelugaPatientPreferenceInput
|
|
193
194
|
|
|
194
195
|
const validationMessage = validateField(field)
|
|
195
196
|
|
|
@@ -357,6 +358,9 @@ export const QuestionForField = ({
|
|
|
357
358
|
: field.type === 'Medications' ? (
|
|
358
359
|
<Medications field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Medications'>} form={form}/>
|
|
359
360
|
)
|
|
361
|
+
: field.type === 'Beluga Patient Preference' ? (
|
|
362
|
+
<BelugaPatientPreference field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Beluga Patient Preference'>} form={form}/>
|
|
363
|
+
)
|
|
360
364
|
: field.type === 'Insurance' ? (
|
|
361
365
|
<Insurance field={field} value={value.answer.value as any} form={form}
|
|
362
366
|
onDatabaseSelect={handleDatabaseSelect}
|
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, 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, 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"
|
|
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"
|
|
@@ -44,8 +44,24 @@ const TellescopeFormContainerWithThemeV2: typeof TellescopeFormContainerV2 = ({
|
|
|
44
44
|
const finalBgColor = shouldUseCustomBg ? backgroundColor : '#F4F3FA'
|
|
45
45
|
|
|
46
46
|
return (
|
|
47
|
-
<Flex flex={1} column alignItems="center" style={{
|
|
48
|
-
|
|
47
|
+
<Flex flex={1} column alignItems="center" style={{
|
|
48
|
+
backgroundColor: finalBgColor,
|
|
49
|
+
overflow: 'auto',
|
|
50
|
+
paddingTop: window.innerWidth < 600 ? 20 : 40,
|
|
51
|
+
paddingBottom: window.innerWidth < 600 ? 20 : 40,
|
|
52
|
+
...style
|
|
53
|
+
}}>
|
|
54
|
+
<Flex flex={1} column style={{
|
|
55
|
+
padding: window.innerWidth < 600 ? '0 12px' : '0 20px',
|
|
56
|
+
maxWidth: maxWidth ?? 650,
|
|
57
|
+
minWidth: 250,
|
|
58
|
+
width: '100%',
|
|
59
|
+
height: '100%',
|
|
60
|
+
boxSizing: 'border-box',
|
|
61
|
+
...(window.innerWidth < 600 ? {
|
|
62
|
+
paddingBottom: '80px' // Extra bottom padding on mobile to keep button above Safari navigation
|
|
63
|
+
} : {})
|
|
64
|
+
}}>
|
|
49
65
|
{language && onChangeLanguage &&
|
|
50
66
|
<Flex style={{ marginTop: 22 }}>
|
|
51
67
|
<LanguageSelect value={language} onChange={onChangeLanguage} />
|
|
@@ -167,6 +183,7 @@ export const QuestionForField = ({
|
|
|
167
183
|
const Allergies = customInputs?.['Allergies'] ?? AllergiesInput
|
|
168
184
|
const Conditions = customInputs?.['Conditions'] ?? ConditionsInput
|
|
169
185
|
const RichText = customInputs?.['Rich Text'] ?? RichTextInput
|
|
186
|
+
const BelugaPatientPreference = customInputs?.['Beluga Patient Preference'] ?? BelugaPatientPreferenceInput
|
|
170
187
|
|
|
171
188
|
const validationMessage = validateField(field)
|
|
172
189
|
|
|
@@ -333,6 +350,9 @@ export const QuestionForField = ({
|
|
|
333
350
|
: field.type === 'Medications' ? (
|
|
334
351
|
<Medications field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Medications'>} form={form}/>
|
|
335
352
|
)
|
|
353
|
+
: field.type === 'Beluga Patient Preference' ? (
|
|
354
|
+
<BelugaPatientPreference field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Beluga Patient Preference'>} form={form}/>
|
|
355
|
+
)
|
|
336
356
|
: field.type === 'Insurance' ? (
|
|
337
357
|
<Insurance field={field} value={value.answer.value as any} form={form}
|
|
338
358
|
onDatabaseSelect={handleDatabaseSelect}
|
package/src/Forms/hooks.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react"
|
|
1
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"
|
|
2
2
|
import { Session } from "@tellescope/sdk"
|
|
3
3
|
import { ChangeHandler, FormFieldNode } from "./types"
|
|
4
4
|
import { DatabaseRecord, Enduser, Form, FormField, FormResponse } from "@tellescope/types-client"
|
|
@@ -9,7 +9,7 @@ import { WithTheme, contact_is_valid, useAddGTMTag, useFileUpload, useFormFields
|
|
|
9
9
|
import ReactGA from "react-ga4";
|
|
10
10
|
|
|
11
11
|
import isEmail from "validator/lib/isEmail"
|
|
12
|
-
import { append_current_utm_params, emit_gtm_event, field_can_autoadvance, getLocalTimezone, get_time_values, get_utm_params, is_object, object_is_empty, read_local_storage, responses_satisfy_conditions, update_local_storage } from "@tellescope/utilities"
|
|
12
|
+
import { append_current_utm_params, emit_gtm_event, field_can_autoadvance, getLocalTimezone, get_time_values, get_utm_params, is_object, object_is_empty, read_local_storage, replace_form_field_template_values, responses_satisfy_conditions, update_local_storage } from "@tellescope/utilities"
|
|
13
13
|
|
|
14
14
|
export const useFlattenedTree = (root?: FormFieldNode) => {
|
|
15
15
|
const flat: FormField[] = []
|
|
@@ -1419,6 +1419,30 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1419
1419
|
return false
|
|
1420
1420
|
}, [activeField, validateField, uploadingFiles])
|
|
1421
1421
|
|
|
1422
|
+
// Helper function to apply templating to responses
|
|
1423
|
+
// Templates field titles/descriptions with current enduser data and form response values
|
|
1424
|
+
// Can be called whenever we need to update templates (e.g., on "next" button click)
|
|
1425
|
+
const applyTemplatingToResponses = useCallback((
|
|
1426
|
+
currentResponses: Response[]
|
|
1427
|
+
): Response[] => {
|
|
1428
|
+
return currentResponses.map(response => {
|
|
1429
|
+
const originalField = fields.find(f => f.id === response.fieldId) || response.field
|
|
1430
|
+
|
|
1431
|
+
return {
|
|
1432
|
+
...response,
|
|
1433
|
+
fieldTitle: replace_form_field_template_values(originalField.title || '', { enduser, responses: currentResponses }),
|
|
1434
|
+
fieldDescription: replace_form_field_template_values(originalField.description || '', { enduser, responses: currentResponses }),
|
|
1435
|
+
fieldHtmlDescription: replace_form_field_template_values(originalField.htmlDescription || '', { enduser, responses: currentResponses }),
|
|
1436
|
+
field: {
|
|
1437
|
+
...response.field,
|
|
1438
|
+
title: replace_form_field_template_values(originalField.title || '', { enduser, responses: currentResponses }),
|
|
1439
|
+
description: replace_form_field_template_values(originalField.description || '', { enduser, responses: currentResponses }),
|
|
1440
|
+
htmlDescription: replace_form_field_template_values(originalField.htmlDescription || '', { enduser, responses: currentResponses }),
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
})
|
|
1444
|
+
}, [fields, enduser])
|
|
1445
|
+
|
|
1422
1446
|
const autoAdvanceRef = useRef(false)
|
|
1423
1447
|
// don't make option, to avoid user passing invalid data, like an onclick event
|
|
1424
1448
|
const goToNextField = useCallback((answer: FormResponseValue['answer'] | undefined) => {
|
|
@@ -1426,10 +1450,24 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1426
1450
|
if (isNextDisabled() && currentValue?.answer.type !== 'Hidden Value') return
|
|
1427
1451
|
|
|
1428
1452
|
console.log('going to next field')
|
|
1453
|
+
|
|
1454
|
+
// If an answer is provided (e.g., from Hidden Value), update responses first
|
|
1455
|
+
const responsesWithAnswer = answer
|
|
1456
|
+
? responses.map(r =>
|
|
1457
|
+
r.fieldId === currentValue.fieldId
|
|
1458
|
+
? { ...r, answer }
|
|
1459
|
+
: r
|
|
1460
|
+
)
|
|
1461
|
+
: responses
|
|
1462
|
+
|
|
1463
|
+
// Apply templating to all responses including the newly updated answer
|
|
1464
|
+
const templatedResponses = applyTemplatingToResponses(responsesWithAnswer)
|
|
1465
|
+
setResponses(templatedResponses)
|
|
1466
|
+
|
|
1429
1467
|
if (currentValue.answer.type === 'Question Group') {
|
|
1430
1468
|
const responsesToSave = (
|
|
1431
1469
|
(currentValue.field.options?.subFields || [])
|
|
1432
|
-
.map(({ id }) =>
|
|
1470
|
+
.map(({ id }) => templatedResponses.find(f => f.fieldId === id)!)
|
|
1433
1471
|
.filter(f => f && f?.answer.type !== 'file' && f?.answer.type !== 'files')
|
|
1434
1472
|
)
|
|
1435
1473
|
if (responsesToSave.length) {
|
|
@@ -1440,7 +1478,7 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1440
1478
|
})
|
|
1441
1479
|
.catch(console.error)
|
|
1442
1480
|
}
|
|
1443
|
-
}
|
|
1481
|
+
}
|
|
1444
1482
|
else if (currentValue?.answer?.type !== 'file' && currentValue?.answer?.type !== 'files' && (formResponseId || accessCode)) {
|
|
1445
1483
|
session.api.form_responses.save_field_response({
|
|
1446
1484
|
accessCode,
|
|
@@ -1455,17 +1493,26 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1455
1493
|
|
|
1456
1494
|
try { window.scrollTo({ top: 0 }) } catch(err) {} // scroll to top if needed
|
|
1457
1495
|
setActiveField(activeField => {
|
|
1458
|
-
let newField = getNextField(activeField, currentValue,
|
|
1496
|
+
let newField = getNextField(activeField, currentValue, templatedResponses, logicOptions)
|
|
1459
1497
|
|
|
1460
1498
|
// when autoadvancing, prevent adding duplicates by checking whether already on stack
|
|
1461
1499
|
if (newField !== undefined && !prevFieldStackRef.current.find(v => v.value.id === activeField?.value.id)) {
|
|
1462
1500
|
prevFieldStackRef.current.push(activeField)
|
|
1463
1501
|
setCurrentPageIndex(i => i + 1)
|
|
1464
1502
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1503
|
+
|
|
1504
|
+
const fieldToReturn = newField || activeField
|
|
1505
|
+
|
|
1506
|
+
// Apply templating to the active field by pulling from the templated responses
|
|
1507
|
+
// This ensures the UI displays templated titles/descriptions immediately
|
|
1508
|
+
const templatedResponse = templatedResponses.find(r => r.fieldId === fieldToReturn.value.id)
|
|
1509
|
+
if (templatedResponse) {
|
|
1510
|
+
fieldToReturn.value = templatedResponse.field
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
return fieldToReturn
|
|
1467
1514
|
})
|
|
1468
|
-
}, [prevFieldStackRef, currentValue, isNextDisabled, updateFormResponse, session, responses, logicOptions, accessCode, formResponseId, setActiveField, setCurrentPageIndex])
|
|
1515
|
+
}, [prevFieldStackRef, currentValue, isNextDisabled, updateFormResponse, session, responses, logicOptions, accessCode, formResponseId, setActiveField, setCurrentPageIndex, applyTemplatingToResponses])
|
|
1469
1516
|
|
|
1470
1517
|
useEffect(() => {
|
|
1471
1518
|
if (dontAutoadvance) return
|
package/src/Forms/index.ts
CHANGED
|
@@ -6,4 +6,5 @@ export * from "./types";
|
|
|
6
6
|
export * from "./localization";
|
|
7
7
|
|
|
8
8
|
// V2 Forms exports
|
|
9
|
-
export { TellescopeFormV2, TellescopeFormContainerV2, TellescopeSingleQuestionFlowV2 } from "./forms.v2";
|
|
9
|
+
export { TellescopeFormV2, TellescopeFormContainerV2, TellescopeSingleQuestionFlowV2 } from "./forms.v2";
|
|
10
|
+
export { defaultInputProps as inputPropsV2 } from "./inputs.v2";
|
package/src/Forms/inputs.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { Autocomplete, Box, Button, Checkbox, Chip, Collapse, Divider, FormContr
|
|
|
4
4
|
import { FormInputProps } from "./types"
|
|
5
5
|
import { useDropzone } from "react-dropzone"
|
|
6
6
|
import { CANVAS_TITLE, EMOTII_TITLE, INSURANCE_RELATIONSHIPS, INSURANCE_RELATIONSHIPS_CANVAS, PRIMARY_HEX, RELATIONSHIP_TYPES, TELLESCOPE_GENDERS } from "@tellescope/constants"
|
|
7
|
-
import { MM_DD_YYYY_to_YYYY_MM_DD, capture_is_supported, downloadFile, emit_gtm_event, first_letter_capitalized, form_response_value_to_string, getLocalTimezone, getPublicFileURL, mm_dd_yyyy, replace_enduser_template_values, truncate_string, update_local_storage, user_display_name } from "@tellescope/utilities"
|
|
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, replace_enduser_template_values, truncate_string, update_local_storage, user_display_name } from "@tellescope/utilities"
|
|
8
8
|
import { Address, DatabaseSelectResponse, Enduser, EnduserRelationship, FormResponseValue, InsuranceRelationship, MedicationResponse, MultipleChoiceOptions, FormFieldOptionDetails, 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';
|
|
@@ -1898,7 +1898,7 @@ export const StripeInput = ({ field, value, onChange, setCustomerId, enduserId }
|
|
|
1898
1898
|
${(priceAmount / 100).toFixed(2)} {priceCurrency.toUpperCase()}
|
|
1899
1899
|
{product.currentPrice?.isSubscription && (
|
|
1900
1900
|
<Typography component="span" variant="caption" sx={{ ml: 0.5 }}>
|
|
1901
|
-
|
|
1901
|
+
{format_stripe_subscription_interval(product.currentPrice?.interval, product.currentPrice?.interval_count)}
|
|
1902
1902
|
</Typography>
|
|
1903
1903
|
)}
|
|
1904
1904
|
</Typography>
|
|
@@ -2948,6 +2948,164 @@ export const MedicationsInput = ({ field, value, onChange, ...props }: FormInput
|
|
|
2948
2948
|
)
|
|
2949
2949
|
}
|
|
2950
2950
|
|
|
2951
|
+
export const BelugaPatientPreferenceInput = ({ field, value: _value, onChange }: FormInputProps<'Beluga Patient Preference'>) => {
|
|
2952
|
+
const value = Array.isArray(_value) ? _value : []
|
|
2953
|
+
|
|
2954
|
+
return (
|
|
2955
|
+
<Grid container direction="column" sx={{ mt: 2 }}>
|
|
2956
|
+
{value.map((v, i) => (
|
|
2957
|
+
<>
|
|
2958
|
+
<Grid item key={i}>
|
|
2959
|
+
<Grid container alignItems="center" wrap="nowrap">
|
|
2960
|
+
<Grid item sx={{ width: '100%'}}>
|
|
2961
|
+
<Grid container direction="column" spacing={1.5}>
|
|
2962
|
+
<Grid item>
|
|
2963
|
+
<TextField label="Medication Name" size="small" fullWidth required
|
|
2964
|
+
value={v.name ?? ''}
|
|
2965
|
+
onChange={e =>
|
|
2966
|
+
onChange(
|
|
2967
|
+
value.map((_v, _i) => (
|
|
2968
|
+
i === _i ? { ..._v, name: e.target.value } : _v
|
|
2969
|
+
)),
|
|
2970
|
+
field.id,
|
|
2971
|
+
)
|
|
2972
|
+
}
|
|
2973
|
+
/>
|
|
2974
|
+
</Grid>
|
|
2975
|
+
|
|
2976
|
+
<Grid item>
|
|
2977
|
+
<Grid container spacing={1}>
|
|
2978
|
+
<Grid item xs={12} md={6}>
|
|
2979
|
+
<TextField label="Strength" size="small" fullWidth required
|
|
2980
|
+
value={v.strength ?? ''}
|
|
2981
|
+
onChange={e =>
|
|
2982
|
+
onChange(
|
|
2983
|
+
value.map((_v, _i) => (
|
|
2984
|
+
i === _i ? { ..._v, strength: e.target.value } : _v
|
|
2985
|
+
)),
|
|
2986
|
+
field.id,
|
|
2987
|
+
)
|
|
2988
|
+
}
|
|
2989
|
+
/>
|
|
2990
|
+
</Grid>
|
|
2991
|
+
<Grid item xs={12} md={6}>
|
|
2992
|
+
<TextField label="Dispense Unit" size="small" fullWidth required
|
|
2993
|
+
value={v.dispenseUnit ?? ''}
|
|
2994
|
+
onChange={e =>
|
|
2995
|
+
onChange(
|
|
2996
|
+
value.map((_v, _i) => (
|
|
2997
|
+
i === _i ? { ..._v, dispenseUnit: e.target.value } : _v
|
|
2998
|
+
)),
|
|
2999
|
+
field.id,
|
|
3000
|
+
)
|
|
3001
|
+
}
|
|
3002
|
+
/>
|
|
3003
|
+
</Grid>
|
|
3004
|
+
</Grid>
|
|
3005
|
+
</Grid>
|
|
3006
|
+
|
|
3007
|
+
<Grid item>
|
|
3008
|
+
<Grid container spacing={1}>
|
|
3009
|
+
<Grid item xs={12} md={4}>
|
|
3010
|
+
<TextField label="Quantity" size="small" fullWidth required
|
|
3011
|
+
value={v.quantity ?? ''}
|
|
3012
|
+
onChange={e =>
|
|
3013
|
+
onChange(
|
|
3014
|
+
value.map((_v, _i) => (
|
|
3015
|
+
i === _i ? { ..._v, quantity: e.target.value } : _v
|
|
3016
|
+
)),
|
|
3017
|
+
field.id,
|
|
3018
|
+
)
|
|
3019
|
+
}
|
|
3020
|
+
/>
|
|
3021
|
+
</Grid>
|
|
3022
|
+
<Grid item xs={12} md={4}>
|
|
3023
|
+
<TextField label="Refills" size="small" fullWidth required
|
|
3024
|
+
value={v.refills ?? ''}
|
|
3025
|
+
onChange={e =>
|
|
3026
|
+
onChange(
|
|
3027
|
+
value.map((_v, _i) => (
|
|
3028
|
+
i === _i ? { ..._v, refills: e.target.value } : _v
|
|
3029
|
+
)),
|
|
3030
|
+
field.id,
|
|
3031
|
+
)
|
|
3032
|
+
}
|
|
3033
|
+
/>
|
|
3034
|
+
</Grid>
|
|
3035
|
+
<Grid item xs={12} md={4}>
|
|
3036
|
+
<TextField label="Days Supply" size="small" fullWidth required
|
|
3037
|
+
value={v.daysSupply ?? ''}
|
|
3038
|
+
onChange={e =>
|
|
3039
|
+
onChange(
|
|
3040
|
+
value.map((_v, _i) => (
|
|
3041
|
+
i === _i ? { ..._v, daysSupply: e.target.value } : _v
|
|
3042
|
+
)),
|
|
3043
|
+
field.id,
|
|
3044
|
+
)
|
|
3045
|
+
}
|
|
3046
|
+
/>
|
|
3047
|
+
</Grid>
|
|
3048
|
+
</Grid>
|
|
3049
|
+
</Grid>
|
|
3050
|
+
|
|
3051
|
+
<Grid item>
|
|
3052
|
+
<TextField label="Sig (Instructions)" size="small" fullWidth required multiline rows={2}
|
|
3053
|
+
value={v.sig ?? ''}
|
|
3054
|
+
onChange={e =>
|
|
3055
|
+
onChange(
|
|
3056
|
+
value.map((_v, _i) => (
|
|
3057
|
+
i === _i ? { ..._v, sig: e.target.value } : _v
|
|
3058
|
+
)),
|
|
3059
|
+
field.id,
|
|
3060
|
+
)
|
|
3061
|
+
}
|
|
3062
|
+
/>
|
|
3063
|
+
</Grid>
|
|
3064
|
+
|
|
3065
|
+
<Grid item>
|
|
3066
|
+
<TextField label="Med ID (NDC11)" size="small" fullWidth required
|
|
3067
|
+
value={v.medId ?? ''}
|
|
3068
|
+
onChange={e =>
|
|
3069
|
+
onChange(
|
|
3070
|
+
value.map((_v, _i) => (
|
|
3071
|
+
i === _i ? { ..._v, medId: e.target.value } : _v
|
|
3072
|
+
)),
|
|
3073
|
+
field.id,
|
|
3074
|
+
)
|
|
3075
|
+
}
|
|
3076
|
+
/>
|
|
3077
|
+
</Grid>
|
|
3078
|
+
|
|
3079
|
+
<Grid item>
|
|
3080
|
+
<Typography color="primary" sx={{ textDecoration: 'underline', cursor: 'pointer' }}
|
|
3081
|
+
onClick={() => onChange(value.filter((_, _i) => i !== _i), field.id)}
|
|
3082
|
+
>
|
|
3083
|
+
Remove medication
|
|
3084
|
+
</Typography>
|
|
3085
|
+
</Grid>
|
|
3086
|
+
</Grid>
|
|
3087
|
+
</Grid>
|
|
3088
|
+
</Grid>
|
|
3089
|
+
</Grid>
|
|
3090
|
+
|
|
3091
|
+
<Grid item><Divider flexItem sx={{ my: 1 }} /></Grid>
|
|
3092
|
+
</>
|
|
3093
|
+
))}
|
|
3094
|
+
|
|
3095
|
+
<Grid item>
|
|
3096
|
+
<Button color="primary" variant="outlined"
|
|
3097
|
+
onClick={() => onChange([
|
|
3098
|
+
...value,
|
|
3099
|
+
{ name: '', strength: '', quantity: '', refills: '', daysSupply: '', sig: '', dispenseUnit: '', medId: '' }
|
|
3100
|
+
], field.id)}
|
|
3101
|
+
>
|
|
3102
|
+
Add Medication
|
|
3103
|
+
</Button>
|
|
3104
|
+
</Grid>
|
|
3105
|
+
</Grid>
|
|
3106
|
+
)
|
|
3107
|
+
}
|
|
3108
|
+
|
|
2951
3109
|
export const contact_is_valid = (e: Partial<Enduser>) => {
|
|
2952
3110
|
if (e.email) {
|
|
2953
3111
|
try {
|
package/src/Forms/inputs.v2.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { Autocomplete, Box, Button, Checkbox, Chip, Collapse, Divider, FormContr
|
|
|
4
4
|
import { FormInputProps } from "./types"
|
|
5
5
|
import { useDropzone } from "react-dropzone"
|
|
6
6
|
import { CANVAS_TITLE, EMOTII_TITLE, INSURANCE_RELATIONSHIPS, INSURANCE_RELATIONSHIPS_CANVAS, PRIMARY_HEX, RELATIONSHIP_TYPES, TELLESCOPE_GENDERS } from "@tellescope/constants"
|
|
7
|
-
import { MM_DD_YYYY_to_YYYY_MM_DD, capture_is_supported, downloadFile, emit_gtm_event, first_letter_capitalized, form_response_value_to_string, getLocalTimezone, getPublicFileURL, mm_dd_yyyy, replace_enduser_template_values, truncate_string, update_local_storage, user_display_name } from "@tellescope/utilities"
|
|
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, replace_enduser_template_values, truncate_string, update_local_storage, user_display_name } from "@tellescope/utilities"
|
|
8
8
|
import { Address, DatabaseSelectResponse, Enduser, EnduserRelationship, FormResponseValue, InsuranceRelationship, MedicationResponse, MultipleChoiceOptions, FormFieldOptionDetails, 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';
|
|
@@ -1561,6 +1561,7 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1561
1561
|
marginBottom: '12px',
|
|
1562
1562
|
cursor: 'pointer',
|
|
1563
1563
|
backgroundColor: 'transparent',
|
|
1564
|
+
boxSizing: 'border-box',
|
|
1564
1565
|
'&:hover': {
|
|
1565
1566
|
backgroundColor: (theme: any) => `${theme.palette.primary.main}14`,
|
|
1566
1567
|
},
|
|
@@ -1614,7 +1615,8 @@ export const MultipleChoiceInput = ({ field, form, value: _value, onChange }: Fo
|
|
|
1614
1615
|
display: 'flex',
|
|
1615
1616
|
alignItems: 'center',
|
|
1616
1617
|
cursor: 'pointer',
|
|
1617
|
-
width: '100%'
|
|
1618
|
+
width: '100%',
|
|
1619
|
+
boxSizing: 'border-box'
|
|
1618
1620
|
}}
|
|
1619
1621
|
onClick={(e) => {
|
|
1620
1622
|
// Don't trigger selection if clicking on the expand button
|
|
@@ -1911,7 +1913,7 @@ export const StripeInput = ({ field, value, onChange, setCustomerId, enduserId }
|
|
|
1911
1913
|
${(priceAmount / 100).toFixed(2)} {priceCurrency.toUpperCase()}
|
|
1912
1914
|
{product.currentPrice?.isSubscription && (
|
|
1913
1915
|
<Typography component="span" variant="caption" sx={{ ml: 0.5 }}>
|
|
1914
|
-
|
|
1916
|
+
{format_stripe_subscription_interval(product.currentPrice?.interval, product.currentPrice?.interval_count)}
|
|
1915
1917
|
</Typography>
|
|
1916
1918
|
)}
|
|
1917
1919
|
</Typography>
|
|
@@ -2971,6 +2973,172 @@ export const MedicationsInput = ({ field, value, onChange, ...props }: FormInput
|
|
|
2971
2973
|
)
|
|
2972
2974
|
}
|
|
2973
2975
|
|
|
2976
|
+
export const BelugaPatientPreferenceInput = ({ field, value: _value, onChange }: FormInputProps<'Beluga Patient Preference'>) => {
|
|
2977
|
+
const value = Array.isArray(_value) ? _value : []
|
|
2978
|
+
|
|
2979
|
+
return (
|
|
2980
|
+
<Grid container direction="column" sx={{ mt: 2 }}>
|
|
2981
|
+
{value.map((v, i) => (
|
|
2982
|
+
<>
|
|
2983
|
+
<Grid item key={i}>
|
|
2984
|
+
<Grid container alignItems="center" wrap="nowrap">
|
|
2985
|
+
<Grid item sx={{ width: '100%'}}>
|
|
2986
|
+
<Grid container direction="column" spacing={1.5}>
|
|
2987
|
+
<Grid item>
|
|
2988
|
+
<TextField label="Medication Name" size="small" fullWidth required
|
|
2989
|
+
InputProps={defaultInputProps}
|
|
2990
|
+
value={v.name ?? ''}
|
|
2991
|
+
onChange={e =>
|
|
2992
|
+
onChange(
|
|
2993
|
+
value.map((_v, _i) => (
|
|
2994
|
+
i === _i ? { ..._v, name: e.target.value } : _v
|
|
2995
|
+
)),
|
|
2996
|
+
field.id,
|
|
2997
|
+
)
|
|
2998
|
+
}
|
|
2999
|
+
/>
|
|
3000
|
+
</Grid>
|
|
3001
|
+
|
|
3002
|
+
<Grid item>
|
|
3003
|
+
<Grid container spacing={1}>
|
|
3004
|
+
<Grid item xs={12} md={6}>
|
|
3005
|
+
<TextField label="Strength" size="small" fullWidth required
|
|
3006
|
+
InputProps={defaultInputProps}
|
|
3007
|
+
value={v.strength ?? ''}
|
|
3008
|
+
onChange={e =>
|
|
3009
|
+
onChange(
|
|
3010
|
+
value.map((_v, _i) => (
|
|
3011
|
+
i === _i ? { ..._v, strength: e.target.value } : _v
|
|
3012
|
+
)),
|
|
3013
|
+
field.id,
|
|
3014
|
+
)
|
|
3015
|
+
}
|
|
3016
|
+
/>
|
|
3017
|
+
</Grid>
|
|
3018
|
+
<Grid item xs={12} md={6}>
|
|
3019
|
+
<TextField label="Dispense Unit" size="small" fullWidth required
|
|
3020
|
+
InputProps={defaultInputProps}
|
|
3021
|
+
value={v.dispenseUnit ?? ''}
|
|
3022
|
+
onChange={e =>
|
|
3023
|
+
onChange(
|
|
3024
|
+
value.map((_v, _i) => (
|
|
3025
|
+
i === _i ? { ..._v, dispenseUnit: e.target.value } : _v
|
|
3026
|
+
)),
|
|
3027
|
+
field.id,
|
|
3028
|
+
)
|
|
3029
|
+
}
|
|
3030
|
+
/>
|
|
3031
|
+
</Grid>
|
|
3032
|
+
</Grid>
|
|
3033
|
+
</Grid>
|
|
3034
|
+
|
|
3035
|
+
<Grid item>
|
|
3036
|
+
<Grid container spacing={1}>
|
|
3037
|
+
<Grid item xs={12} md={4}>
|
|
3038
|
+
<TextField label="Quantity" size="small" fullWidth required
|
|
3039
|
+
InputProps={defaultInputProps}
|
|
3040
|
+
value={v.quantity ?? ''}
|
|
3041
|
+
onChange={e =>
|
|
3042
|
+
onChange(
|
|
3043
|
+
value.map((_v, _i) => (
|
|
3044
|
+
i === _i ? { ..._v, quantity: e.target.value } : _v
|
|
3045
|
+
)),
|
|
3046
|
+
field.id,
|
|
3047
|
+
)
|
|
3048
|
+
}
|
|
3049
|
+
/>
|
|
3050
|
+
</Grid>
|
|
3051
|
+
<Grid item xs={12} md={4}>
|
|
3052
|
+
<TextField label="Refills" size="small" fullWidth required
|
|
3053
|
+
InputProps={defaultInputProps}
|
|
3054
|
+
value={v.refills ?? ''}
|
|
3055
|
+
onChange={e =>
|
|
3056
|
+
onChange(
|
|
3057
|
+
value.map((_v, _i) => (
|
|
3058
|
+
i === _i ? { ..._v, refills: e.target.value } : _v
|
|
3059
|
+
)),
|
|
3060
|
+
field.id,
|
|
3061
|
+
)
|
|
3062
|
+
}
|
|
3063
|
+
/>
|
|
3064
|
+
</Grid>
|
|
3065
|
+
<Grid item xs={12} md={4}>
|
|
3066
|
+
<TextField label="Days Supply" size="small" fullWidth required
|
|
3067
|
+
InputProps={defaultInputProps}
|
|
3068
|
+
value={v.daysSupply ?? ''}
|
|
3069
|
+
onChange={e =>
|
|
3070
|
+
onChange(
|
|
3071
|
+
value.map((_v, _i) => (
|
|
3072
|
+
i === _i ? { ..._v, daysSupply: e.target.value } : _v
|
|
3073
|
+
)),
|
|
3074
|
+
field.id,
|
|
3075
|
+
)
|
|
3076
|
+
}
|
|
3077
|
+
/>
|
|
3078
|
+
</Grid>
|
|
3079
|
+
</Grid>
|
|
3080
|
+
</Grid>
|
|
3081
|
+
|
|
3082
|
+
<Grid item>
|
|
3083
|
+
<TextField label="Sig (Instructions)" size="small" fullWidth required multiline rows={2}
|
|
3084
|
+
InputProps={defaultInputProps}
|
|
3085
|
+
value={v.sig ?? ''}
|
|
3086
|
+
onChange={e =>
|
|
3087
|
+
onChange(
|
|
3088
|
+
value.map((_v, _i) => (
|
|
3089
|
+
i === _i ? { ..._v, sig: e.target.value } : _v
|
|
3090
|
+
)),
|
|
3091
|
+
field.id,
|
|
3092
|
+
)
|
|
3093
|
+
}
|
|
3094
|
+
/>
|
|
3095
|
+
</Grid>
|
|
3096
|
+
|
|
3097
|
+
<Grid item>
|
|
3098
|
+
<TextField label="Med ID (NDC11)" size="small" fullWidth required
|
|
3099
|
+
InputProps={defaultInputProps}
|
|
3100
|
+
value={v.medId ?? ''}
|
|
3101
|
+
onChange={e =>
|
|
3102
|
+
onChange(
|
|
3103
|
+
value.map((_v, _i) => (
|
|
3104
|
+
i === _i ? { ..._v, medId: e.target.value } : _v
|
|
3105
|
+
)),
|
|
3106
|
+
field.id,
|
|
3107
|
+
)
|
|
3108
|
+
}
|
|
3109
|
+
/>
|
|
3110
|
+
</Grid>
|
|
3111
|
+
|
|
3112
|
+
<Grid item>
|
|
3113
|
+
<Typography color="primary" sx={{ textDecoration: 'underline', cursor: 'pointer' }}
|
|
3114
|
+
onClick={() => onChange(value.filter((_, _i) => i !== _i), field.id)}
|
|
3115
|
+
>
|
|
3116
|
+
Remove medication
|
|
3117
|
+
</Typography>
|
|
3118
|
+
</Grid>
|
|
3119
|
+
</Grid>
|
|
3120
|
+
</Grid>
|
|
3121
|
+
</Grid>
|
|
3122
|
+
</Grid>
|
|
3123
|
+
|
|
3124
|
+
<Grid item><Divider flexItem sx={{ my: 1 }} /></Grid>
|
|
3125
|
+
</>
|
|
3126
|
+
))}
|
|
3127
|
+
|
|
3128
|
+
<Grid item>
|
|
3129
|
+
<Button color="primary" variant="outlined"
|
|
3130
|
+
onClick={() => onChange([
|
|
3131
|
+
...value,
|
|
3132
|
+
{ name: '', strength: '', quantity: '', refills: '', daysSupply: '', sig: '', dispenseUnit: '', medId: '' }
|
|
3133
|
+
], field.id)}
|
|
3134
|
+
>
|
|
3135
|
+
Add Medication
|
|
3136
|
+
</Button>
|
|
3137
|
+
</Grid>
|
|
3138
|
+
</Grid>
|
|
3139
|
+
)
|
|
3140
|
+
}
|
|
3141
|
+
|
|
2974
3142
|
export const contact_is_valid = (e: Partial<Enduser>) => {
|
|
2975
3143
|
if (e.email) {
|
|
2976
3144
|
try {
|