@tellescope/react-components 1.230.1 → 1.231.0
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 +30 -28
- 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 -30
- package/lib/cjs/Forms/forms.v2.js.map +1 -1
- package/lib/cjs/Forms/hooks.d.ts +111 -3
- package/lib/cjs/Forms/hooks.d.ts.map +1 -1
- package/lib/cjs/Forms/hooks.js +26 -8
- package/lib/cjs/Forms/hooks.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 +28 -1
- 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 +32 -32
- package/lib/cjs/Forms/inputs.v2.js.map +1 -1
- package/lib/esm/Forms/forms.d.ts +3 -3
- package/lib/esm/Forms/forms.d.ts.map +1 -1
- package/lib/esm/Forms/forms.js +31 -29
- package/lib/esm/Forms/forms.js.map +1 -1
- package/lib/esm/Forms/forms.v2.d.ts +3 -3
- package/lib/esm/Forms/forms.v2.d.ts.map +1 -1
- package/lib/esm/Forms/forms.v2.js +33 -31
- package/lib/esm/Forms/forms.v2.js.map +1 -1
- package/lib/esm/Forms/hooks.d.ts +111 -3
- package/lib/esm/Forms/hooks.d.ts.map +1 -1
- package/lib/esm/Forms/hooks.js +28 -10
- package/lib/esm/Forms/hooks.js.map +1 -1
- package/lib/esm/Forms/inputs.d.ts +2 -1
- package/lib/esm/Forms/inputs.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.js +26 -0
- 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 +32 -33
- package/lib/esm/Forms/inputs.v2.js.map +1 -1
- package/lib/esm/controls.d.ts +2 -2
- package/lib/esm/inputs.d.ts +1 -1
- package/lib/esm/state.d.ts +319 -319
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/Forms/forms.tsx +6 -2
- package/src/Forms/forms.v2.tsx +16 -12
- package/src/Forms/hooks.tsx +46 -12
- package/src/Forms/inputs.tsx +158 -0
- package/src/Forms/inputs.v2.tsx +179 -65
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellescope/react-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.231.0",
|
|
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.
|
|
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.231.0",
|
|
51
|
+
"@tellescope/sdk": "1.231.0",
|
|
52
|
+
"@tellescope/types-client": "1.231.0",
|
|
53
|
+
"@tellescope/types-models": "1.231.0",
|
|
54
|
+
"@tellescope/types-utilities": "1.231.0",
|
|
55
|
+
"@tellescope/utilities": "1.231.0",
|
|
56
|
+
"@tellescope/validation": "1.231.0",
|
|
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": "55bd4ea4e0ef23c03fee4eeff595f42bc501a0f9",
|
|
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
|
|
|
@@ -324,7 +325,7 @@ export const QuestionForField = ({
|
|
|
324
325
|
<StringLong field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'string' | 'stringLong'>} form={form} />
|
|
325
326
|
)
|
|
326
327
|
: field.type === 'Rich Text' ? (
|
|
327
|
-
<RichText field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'Rich Text'>} form={form} />
|
|
328
|
+
<RichText key={field.id} field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'Rich Text'>} form={form} />
|
|
328
329
|
)
|
|
329
330
|
: field.type === 'email' ? (
|
|
330
331
|
<Email field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'email'>} form={form} />
|
|
@@ -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"
|
|
@@ -183,6 +183,7 @@ export const QuestionForField = ({
|
|
|
183
183
|
const Allergies = customInputs?.['Allergies'] ?? AllergiesInput
|
|
184
184
|
const Conditions = customInputs?.['Conditions'] ?? ConditionsInput
|
|
185
185
|
const RichText = customInputs?.['Rich Text'] ?? RichTextInput
|
|
186
|
+
const BelugaPatientPreference = customInputs?.['Beluga Patient Preference'] ?? BelugaPatientPreferenceInput
|
|
186
187
|
|
|
187
188
|
const validationMessage = validateField(field)
|
|
188
189
|
|
|
@@ -203,9 +204,9 @@ export const QuestionForField = ({
|
|
|
203
204
|
) {
|
|
204
205
|
return null
|
|
205
206
|
}
|
|
206
|
-
return (
|
|
207
|
+
return (
|
|
207
208
|
// margin leaves room for error message in Question Group
|
|
208
|
-
<Flex column flex={1} style={{ marginBottom: spacing ?? 25 }} id={field.id}>
|
|
209
|
+
<Flex column flex={1} style={{ marginBottom: spacing ?? 25 }} id={field.id}>
|
|
209
210
|
{field.type !== 'Redirect' && field.title &&
|
|
210
211
|
<Typography component="h4" style={{
|
|
211
212
|
marginTop: 15, // ensures PDF display doesn't push description into overlap with logo / title at top of form
|
|
@@ -222,13 +223,15 @@ export const QuestionForField = ({
|
|
|
222
223
|
<div style={{ marginTop: 15 }}></div>
|
|
223
224
|
}
|
|
224
225
|
|
|
225
|
-
{
|
|
226
|
+
<Description field={field} style={{ fontSize: 14, color: '#00000099', marginBottom: 11 }} />
|
|
227
|
+
|
|
228
|
+
{feedback.length > 0 &&
|
|
226
229
|
<Flex column style={{ marginBottom: 11, marginTop: 3, }}>
|
|
227
230
|
{feedback.map((f, i) => (
|
|
228
231
|
<Typography key={i} color="error" style={{ fontSize: 20 }}>
|
|
229
232
|
{f}
|
|
230
233
|
</Typography>
|
|
231
|
-
))}
|
|
234
|
+
))}
|
|
232
235
|
</Flex>
|
|
233
236
|
}
|
|
234
237
|
|
|
@@ -316,7 +319,7 @@ export const QuestionForField = ({
|
|
|
316
319
|
<StringLong field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'string' | 'stringLong'>} form={form} error={!!validationMessage && (!['A response is required', 'A value must be checked', 'A file is required', 'Enter a valid phone number', 'Insurer is required'].includes(validationMessage) || value.touched)} />
|
|
317
320
|
)
|
|
318
321
|
: field.type === 'Rich Text' ? (
|
|
319
|
-
<RichText field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'Rich Text'>} form={form} />
|
|
322
|
+
<RichText key={field.id} field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'Rich Text'>} form={form} />
|
|
320
323
|
)
|
|
321
324
|
: field.type === 'email' ? (
|
|
322
325
|
<Email field={field} disabled={value.disabled} value={value.answer.value as string} onChange={onFieldChange as ChangeHandler<'email'>} form={form} error={!!validationMessage && (!['A response is required', 'A value must be checked', 'A file is required', 'Enter a valid phone number', 'Insurer is required'].includes(validationMessage) || value.touched)} />
|
|
@@ -349,6 +352,9 @@ export const QuestionForField = ({
|
|
|
349
352
|
: field.type === 'Medications' ? (
|
|
350
353
|
<Medications field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Medications'>} form={form}/>
|
|
351
354
|
)
|
|
355
|
+
: field.type === 'Beluga Patient Preference' ? (
|
|
356
|
+
<BelugaPatientPreference field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Beluga Patient Preference'>} form={form}/>
|
|
357
|
+
)
|
|
352
358
|
: field.type === 'Insurance' ? (
|
|
353
359
|
<Insurance field={field} value={value.answer.value as any} form={form}
|
|
354
360
|
onDatabaseSelect={handleDatabaseSelect}
|
|
@@ -431,17 +437,15 @@ export const QuestionForField = ({
|
|
|
431
437
|
</Flex>
|
|
432
438
|
)}
|
|
433
439
|
|
|
434
|
-
<Description field={field} style={{ fontSize: 14, color: '#00000099', marginTop: 4 }} />
|
|
435
|
-
|
|
436
440
|
{field.type !== 'Question Group' &&
|
|
437
|
-
<Typography color="error" style={{ marginTop: 3, height: 10, fontSize: 14, marginBottom: -10 }}>
|
|
441
|
+
<Typography color="error" style={{ marginTop: 3, height: 10, fontSize: 14, marginBottom: -10 }}>
|
|
438
442
|
{(validationMessage === 'A response is required' || validationMessage === 'A value must be checked' || validationMessage === 'A file is required' || 'Enter a valid phone number' || 'Insurer is required')
|
|
439
|
-
? value.touched
|
|
443
|
+
? value.touched
|
|
440
444
|
? form_display_text_for_language(form, validationMessage)
|
|
441
|
-
: null
|
|
445
|
+
: null
|
|
442
446
|
: form_display_text_for_language(form, validationMessage)
|
|
443
447
|
}
|
|
444
|
-
</Typography>
|
|
448
|
+
</Typography>
|
|
445
449
|
}
|
|
446
450
|
</Flex>
|
|
447
451
|
)
|
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[] = []
|
|
@@ -684,7 +684,27 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
684
684
|
setResponses(initializeFields())
|
|
685
685
|
}, [formId, initializeFields])
|
|
686
686
|
|
|
687
|
-
|
|
687
|
+
// Create templated versions of responses for UI display
|
|
688
|
+
// This applies template value replacements (e.g., {{enduser.BMI}}) to field titles/descriptions
|
|
689
|
+
// The templated responses are used ONLY for display and submission, not for navigation logic
|
|
690
|
+
const templatedResponses = useMemo(() => {
|
|
691
|
+
return responses.map(response => {
|
|
692
|
+
const originalField = fields.find(f => f.id === response.fieldId) || response.field
|
|
693
|
+
|
|
694
|
+
return {
|
|
695
|
+
...response,
|
|
696
|
+
fieldTitle: replace_form_field_template_values(originalField.title || '', { enduser, responses }),
|
|
697
|
+
fieldDescription: replace_form_field_template_values(originalField.description || '', { enduser, responses }),
|
|
698
|
+
fieldHtmlDescription: replace_form_field_template_values(originalField.htmlDescription || '', { enduser, responses }),
|
|
699
|
+
field: {
|
|
700
|
+
...response.field,
|
|
701
|
+
title: replace_form_field_template_values(originalField.title || '', { enduser, responses }),
|
|
702
|
+
description: replace_form_field_template_values(originalField.description || '', { enduser, responses }),
|
|
703
|
+
htmlDescription: replace_form_field_template_values(originalField.htmlDescription || '', { enduser, responses }),
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
})
|
|
707
|
+
}, [responses, fields, enduser])
|
|
688
708
|
|
|
689
709
|
// placeholders for initial files, reset when fields prop changes, since questions are now different (e.g. different form selected)
|
|
690
710
|
const fileInitRef = useRef('')
|
|
@@ -706,15 +726,28 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
706
726
|
}, [formId, initializeFiles])
|
|
707
727
|
|
|
708
728
|
const currentValue = (
|
|
709
|
-
|
|
729
|
+
templatedResponses.find(f => f.fieldId === activeField.value.id)
|
|
710
730
|
)
|
|
711
731
|
const currentFileValue = (
|
|
712
732
|
selectedFiles.find(f => f.fieldId === activeField.value.id)
|
|
713
733
|
)
|
|
714
734
|
|
|
735
|
+
// Create templated version of activeField for UI display
|
|
736
|
+
// This applies template replacements to the field's title/description
|
|
737
|
+
const templatedActiveField = useMemo(() => {
|
|
738
|
+
const templatedResponse = templatedResponses.find(r => r.fieldId === activeField.value.id)
|
|
739
|
+
if (templatedResponse) {
|
|
740
|
+
return {
|
|
741
|
+
...activeField,
|
|
742
|
+
value: templatedResponse.field
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
return activeField
|
|
746
|
+
}, [activeField, templatedResponses])
|
|
747
|
+
|
|
715
748
|
const logicOptions: NextFieldLogicOptions = {
|
|
716
749
|
urlLogicValue,
|
|
717
|
-
activeResponses:
|
|
750
|
+
activeResponses: templatedResponses.filter(r => r.includeInSubmit),
|
|
718
751
|
dateOfBirth: enduser?.dateOfBirth,
|
|
719
752
|
gender: enduser?.gender,
|
|
720
753
|
state: enduser?.state,
|
|
@@ -1274,10 +1307,11 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1274
1307
|
|
|
1275
1308
|
if (!accessCode && session.type === 'enduser') throw new Error('enduser session without accessCode')
|
|
1276
1309
|
try {
|
|
1310
|
+
// Use templatedResponses for submission to ensure template values are resolved
|
|
1277
1311
|
const responsesToSubmit = (
|
|
1278
|
-
options?.includedFieldIds
|
|
1279
|
-
? options.includedFieldIds.map(id =>
|
|
1280
|
-
:
|
|
1312
|
+
options?.includedFieldIds
|
|
1313
|
+
? options.includedFieldIds.map(id => templatedResponses.find(r => r.fieldId === id)!)
|
|
1314
|
+
: templatedResponses.filter(r => r.includeInSubmit)
|
|
1281
1315
|
)
|
|
1282
1316
|
|
|
1283
1317
|
// ensure Question Group responses are included
|
|
@@ -1286,7 +1320,7 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1286
1320
|
if (r.answer.type !== 'Question Group') continue
|
|
1287
1321
|
|
|
1288
1322
|
for (const f of r.answer.value ?? []) {
|
|
1289
|
-
const match =
|
|
1323
|
+
const match = templatedResponses.find(r => r.fieldId === f?.id)
|
|
1290
1324
|
if (!match || responsesToSubmit.find(r => r.fieldId === match.fieldId)) continue
|
|
1291
1325
|
|
|
1292
1326
|
// hidden in group by conditional logic
|
|
@@ -1403,7 +1437,7 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1403
1437
|
} finally {
|
|
1404
1438
|
setSubmittingStatus(undefined)
|
|
1405
1439
|
}
|
|
1406
|
-
}, [accessCode, automationStepId, enduserId, responses, selectedFiles, session, handleUpload, existingResponses, ga4measurementId, rootResponseId, parentResponseId, calendarEventId, goBackURL, logicOptions, handleFileUpload])
|
|
1440
|
+
}, [accessCode, automationStepId, enduserId, responses, templatedResponses, selectedFiles, session, handleUpload, existingResponses, ga4measurementId, rootResponseId, parentResponseId, calendarEventId, goBackURL, logicOptions, handleFileUpload])
|
|
1407
1441
|
|
|
1408
1442
|
const isNextDisabled = useCallback(() => {
|
|
1409
1443
|
if (uploadingFiles.length) { return true }
|
|
@@ -1589,12 +1623,12 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
1589
1623
|
return {
|
|
1590
1624
|
enduserId,
|
|
1591
1625
|
formResponseId,
|
|
1592
|
-
activeField,
|
|
1626
|
+
activeField: templatedActiveField, // Use templated activeField for UI display
|
|
1593
1627
|
currentValue,
|
|
1594
1628
|
currentFileValue,
|
|
1595
1629
|
getResponsesWithQuestionGroupAnswers,
|
|
1596
1630
|
fields,
|
|
1597
|
-
responses,
|
|
1631
|
+
responses: templatedResponses, // Use templated responses - only display fields differ, answer values unchanged
|
|
1598
1632
|
selectedFiles,
|
|
1599
1633
|
onFieldChange,
|
|
1600
1634
|
onAddFile,
|
package/src/Forms/inputs.tsx
CHANGED
|
@@ -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 {
|