@tellescope/react-components 1.159.0 → 1.160.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.
Files changed (42) hide show
  1. package/lib/cjs/CMS/components.d.ts +0 -1
  2. package/lib/cjs/CMS/components.d.ts.map +1 -1
  3. package/lib/cjs/Forms/form_responses.d.ts +0 -1
  4. package/lib/cjs/Forms/form_responses.d.ts.map +1 -1
  5. package/lib/cjs/Forms/forms.d.ts +2 -2
  6. package/lib/cjs/Forms/forms.d.ts.map +1 -1
  7. package/lib/cjs/Forms/forms.js +4 -4
  8. package/lib/cjs/Forms/forms.js.map +1 -1
  9. package/lib/cjs/Forms/hooks.d.ts +0 -1
  10. package/lib/cjs/Forms/hooks.d.ts.map +1 -1
  11. package/lib/cjs/Forms/inputs.d.ts +3 -2
  12. package/lib/cjs/Forms/inputs.d.ts.map +1 -1
  13. package/lib/cjs/Forms/inputs.js +86 -9
  14. package/lib/cjs/Forms/inputs.js.map +1 -1
  15. package/lib/cjs/Forms/types.d.ts +1 -0
  16. package/lib/cjs/Forms/types.d.ts.map +1 -1
  17. package/lib/cjs/controls.d.ts +2 -2
  18. package/lib/cjs/inputs.native.d.ts +0 -1
  19. package/lib/cjs/inputs.native.d.ts.map +1 -1
  20. package/lib/esm/CMS/components.d.ts +0 -1
  21. package/lib/esm/CMS/components.d.ts.map +1 -1
  22. package/lib/esm/Forms/forms.d.ts +4 -4
  23. package/lib/esm/Forms/forms.d.ts.map +1 -1
  24. package/lib/esm/Forms/forms.js +4 -4
  25. package/lib/esm/Forms/forms.js.map +1 -1
  26. package/lib/esm/Forms/inputs.d.ts +4 -3
  27. package/lib/esm/Forms/inputs.d.ts.map +1 -1
  28. package/lib/esm/Forms/inputs.js +84 -8
  29. package/lib/esm/Forms/inputs.js.map +1 -1
  30. package/lib/esm/Forms/inputs.native.d.ts +0 -1
  31. package/lib/esm/Forms/inputs.native.d.ts.map +1 -1
  32. package/lib/esm/Forms/types.d.ts +1 -0
  33. package/lib/esm/Forms/types.d.ts.map +1 -1
  34. package/lib/esm/controls.d.ts +2 -2
  35. package/lib/esm/inputs.d.ts +1 -1
  36. package/lib/esm/layout.d.ts +1 -1
  37. package/lib/esm/state.d.ts +256 -256
  38. package/lib/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +9 -9
  40. package/src/Forms/forms.tsx +5 -4
  41. package/src/Forms/inputs.tsx +176 -7
  42. package/src/Forms/types.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellescope/react-components",
3
- "version": "1.159.0",
3
+ "version": "1.160.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.6.2",
48
48
  "@stripe/react-stripe-js": "^2.9.0",
49
49
  "@stripe/stripe-js": "^1.52.1",
50
- "@tellescope/constants": "^1.159.0",
51
- "@tellescope/sdk": "^1.159.0",
52
- "@tellescope/types-client": "^1.159.0",
53
- "@tellescope/types-models": "^1.159.0",
54
- "@tellescope/types-utilities": "^1.159.0",
55
- "@tellescope/utilities": "^1.159.0",
56
- "@tellescope/validation": "^1.159.0",
50
+ "@tellescope/constants": "^1.160.1",
51
+ "@tellescope/sdk": "^1.160.1",
52
+ "@tellescope/types-client": "^1.160.1",
53
+ "@tellescope/types-models": "^1.160.1",
54
+ "@tellescope/types-utilities": "^1.160.1",
55
+ "@tellescope/utilities": "^1.160.1",
56
+ "@tellescope/validation": "^1.160.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",
@@ -80,7 +80,7 @@
80
80
  "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
81
81
  "react-native": "^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.71.0"
82
82
  },
83
- "gitHead": "105154b2072ee3c52f066e163aec77441d7e6c7d",
83
+ "gitHead": "28dfaf3ce3542b7e879639ddc9264611fece8c62",
84
84
  "publishConfig": {
85
85
  "access": "public"
86
86
  }
@@ -132,6 +132,7 @@ export const QuestionForField = ({
132
132
  goToNextField,
133
133
  spacing,
134
134
  isSinglePage,
135
+ rootResponseId,
135
136
  } : {
136
137
  spacing?: number,
137
138
  form?: Form,
@@ -142,7 +143,7 @@ export const QuestionForField = ({
142
143
  field: FormField,
143
144
  setCustomerId: React.Dispatch<React.SetStateAction<string | undefined>>,
144
145
  isSinglePage?: boolean,
145
- } & Pick<TellescopeFormProps, "goToNextField" | "groupId" | "groupInstance" | "submit" | "formResponseId" | 'enduserId' | 'isPreviousDisabled' | 'goToPreviousField' | 'enduser' | 'handleDatabaseSelect' | 'onAddFile' | 'onFieldChange' | 'fields' | 'customInputs' | 'responses' | 'selectedFiles' | 'validateField'>) => {
146
+ } & Pick<TellescopeFormProps, "rootResponseId" | "goToNextField" | "groupId" | "groupInstance" | "submit" | "formResponseId" | 'enduserId' | 'isPreviousDisabled' | 'goToPreviousField' | 'enduser' | 'handleDatabaseSelect' | 'onAddFile' | 'onFieldChange' | 'fields' | 'customInputs' | 'responses' | 'selectedFiles' | 'validateField'>) => {
146
147
  const String = customInputs?.['string'] ?? StringInput
147
148
  const StringLong = customInputs?.['stringLong'] ?? StringLongInput
148
149
  const Email = customInputs?.['email'] ?? EmailInput
@@ -254,7 +255,7 @@ export const QuestionForField = ({
254
255
  <Height field={field} disabled={value.disabled} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<any>} form={form} />
255
256
  )
256
257
  : field.type === 'Redirect' ? (
257
- <Redirect responses={responses} enduser={enduser} groupId={groupId} groupInsance={groupInstance} submit={submit} field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<any>} form={form} />
258
+ <Redirect rootResponseId={rootResponseId} formResponseId={formResponseId} responses={responses} enduser={enduser} groupId={groupId} groupInsance={groupInstance} submit={submit} field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<any>} form={form} />
258
259
  )
259
260
  : field.type === 'Related Contacts' ? (
260
261
  <RelatedContacts field={field} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<any>} form={form} />
@@ -337,7 +338,7 @@ export const QuestionForField = ({
337
338
  <Flex key={id} flex={1}>
338
339
  <QuestionForField groupId={groupId} groupInstance={groupInstance} customInputs={customInputs} field={match} fields={fields} handleDatabaseSelect={handleDatabaseSelect}
339
340
  enduser={enduser} goToPreviousField={goToPreviousField} isPreviousDisabled={isPreviousDisabled} goToNextField={goToNextField}
340
- form={form} formResponseId={formResponseId} submit={submit}
341
+ form={form} formResponseId={formResponseId} rootResponseId={rootResponseId} submit={submit}
341
342
  repeats={repeats} onRepeatsChange={onRepeatsChange} setCustomerId={setCustomerId}
342
343
  value={value} file={file}
343
344
  onAddFile={onAddFile} onFieldChange={onFieldChange}
@@ -987,7 +988,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
987
988
  <Flex key={activeField.id} style={{ marginBottom: 5 }}>
988
989
  <Flex column flex={1}>
989
990
  <QuestionForField isSinglePage fields={fields} field={activeField} handleDatabaseSelect={handleDatabaseSelect}
990
- enduserId={props.enduserId} formResponseId={props.formResponseId} submit={submit}
991
+ enduserId={props.enduserId} formResponseId={props.formResponseId} rootResponseId={rootResponseId} submit={submit}
991
992
  enduser={enduser} goToPreviousField={goToPreviousField} isPreviousDisabled={isPreviousDisabled} goToNextField={goToNextField}
992
993
  repeats={repeats} onRepeatsChange={setRepeats} setCustomerId={setCustomerId}
993
994
  value={value} file={file}
@@ -5,7 +5,7 @@ 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
7
  import { MM_DD_YYYY_to_YYYY_MM_DD, capture_is_supported, downloadFile, first_letter_capitalized, form_response_value_to_string, getLocalTimezone, getPublicFileURL, mm_dd_yyyy, replace_enduser_template_values, truncate_string, user_display_name } from "@tellescope/utilities"
8
- import { DatabaseSelectResponse, Enduser, EnduserRelationship, FormResponseValue, InsuranceRelationship, MultipleChoiceOptions, TellescopeGender } from "@tellescope/types-models"
8
+ import { DatabaseSelectResponse, Enduser, EnduserRelationship, FormResponseValue, InsuranceRelationship, MedicationResponse, MultipleChoiceOptions, TellescopeGender } 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';
@@ -1941,11 +1941,12 @@ const DRUGS_FOR_DISPLAY_TERM = {} as Record<string, Drug[]>
1941
1941
  const RX_NORM_CODE_FOR_DRUG = {} as Record<string, string>
1942
1942
  const NDC_CODES_FOR_RX_NORM_CODE = {} as Record<string, string[]>
1943
1943
 
1944
- const useMedications = () => {
1944
+ const useMedications = ({ dontFetch } : { dontFetch?: boolean }) => {
1945
1945
  const [displayTerms, setDisplayTerms] = useState(displayTermsCache)
1946
1946
  const fetchRef = useRef(displayTerms !== undefined)
1947
1947
 
1948
1948
  useEffect(() => {
1949
+ if (dontFetch) return
1949
1950
  if (fetchRef.current) return
1950
1951
  fetchRef.current = true
1951
1952
 
@@ -1972,7 +1973,7 @@ const useMedications = () => {
1972
1973
  })
1973
1974
  )
1974
1975
  .catch(console.error)
1975
- }, [])
1976
+ }, [dontFetch])
1976
1977
 
1977
1978
  const getDrugsForDisplayTerm = useCallback(async (s: string) => {
1978
1979
  const drugs = DRUGS_FOR_DISPLAY_TERM[s] || (
@@ -2050,8 +2051,172 @@ const filterOptions = (options: string[], { inputValue } : { inputValue: string
2050
2051
  .slice(0, 100) // dramatic performance improvement (when not virtualized) to show a subset like this
2051
2052
  )
2052
2053
 
2053
- export const MedicationsInput = ({ field, value, onChange }: FormInputProps<'Medications'>) => {
2054
- const { displayTerms, doneLoading, getCodesForDrug, getDrugsForDisplayTerm } = useMedications()
2054
+ const FDB_URL = "http://www.fdbhealth.com/"
2055
+ type CanvasMedicationResult = {
2056
+ entry?: { resource: { code: { coding: { system: string, code: string, display: string } []}} }[]
2057
+ }
2058
+
2059
+ export const CanvasMedicationsInput = ({ field, value=[], onChange }: FormInputProps<'Medications'>) => {
2060
+ const session = useResolvedSession()
2061
+ const [query, setQuery] = useState('')
2062
+ const [results, setResults] = useState<MedicationResponse[]>([])
2063
+
2064
+ // if two Medications questions shown in a row, reset state
2065
+ useEffect(() => {
2066
+ setQuery('')
2067
+ setResults([])
2068
+ }, [field.id])
2069
+
2070
+ const fetchRef = useRef(query)
2071
+ useEffect(() => {
2072
+ if (fetchRef.current === query) return
2073
+ fetchRef.current = query
2074
+
2075
+ if (!query) return
2076
+
2077
+ const t = setTimeout(() => {
2078
+ session.api.integrations
2079
+ .proxy_read({
2080
+ integration: CANVAS_TITLE,
2081
+ type: 'medications',
2082
+ query,
2083
+ })
2084
+ .then((r : { data: CanvasMedicationResult }) => {
2085
+ setResults(
2086
+ (r.data?.entry || [])
2087
+ .map(v => {
2088
+ const fdbCode = v.resource.code.coding.find(c => c.system === FDB_URL)
2089
+
2090
+ return {
2091
+ displayTerm: fdbCode?.display || '',
2092
+ drugName: fdbCode?.display || '',
2093
+ fdbCode: fdbCode?.code || '',
2094
+ }
2095
+ })
2096
+ )
2097
+ })
2098
+ }, 200)
2099
+
2100
+ return () => { clearTimeout(t) }
2101
+ }, [session, query, field?.options?.dataSource])
2102
+
2103
+ return (
2104
+ <Grid container direction="column" spacing={1}>
2105
+ <Grid item>
2106
+ <Autocomplete multiple value={value} options={results} style={{ marginTop: 5 }}
2107
+ noOptionsText={query.length ? 'No results found' : 'Type to start search'}
2108
+ onChange={(e, v) => {
2109
+ if (!v) { return }
2110
+ onChange(v, field.id)
2111
+ setResults([])
2112
+ }}
2113
+ getOptionLabel={v => first_letter_capitalized(v.displayTerm)} filterOptions={o => o}
2114
+ inputValue={query} onInputChange={(e, v) => e && setQuery(v) }
2115
+ renderInput={(params) => (
2116
+ <TextField {...params} InputProps={{ ...params.InputProps, sx: defaultInputProps.sx }}
2117
+ required={!field.isOptional} size="small" label="" placeholder="Search medications..."
2118
+ />
2119
+ )}
2120
+ renderTags={(value, getTagProps) =>
2121
+ value.map((value, index) => (
2122
+ <Chip
2123
+ label={<Typography style={{whiteSpace: 'normal'}}>{value.displayTerm}</Typography>}
2124
+ {...getTagProps({ index })}
2125
+ sx={{height:"100%", py: 0.5 }}
2126
+ />
2127
+ ))
2128
+ }
2129
+ />
2130
+ </Grid>
2131
+
2132
+ {(value || []).map((medication, i) => (
2133
+ <Grid item key={i}>
2134
+ <Grid container direction="column" spacing={0.75}>
2135
+ <Grid item>
2136
+ <Typography noWrap sx={{ fontSize: 14 }}>
2137
+ {medication.drugName}
2138
+ </Typography>
2139
+ </Grid>
2140
+
2141
+ <Grid item>
2142
+ <Grid container alignItems="center" wrap="nowrap" columnGap={0.5} justifyContent={"space-between"}>
2143
+ <Grid item sx={{ width: '50%', mr: 1 }}>
2144
+ <TextField type="number" InputProps={{ sx: defaultInputProps.sx }} fullWidth size="small"
2145
+ label="Units (e.g. capsule, table, puff) per dose?"
2146
+ value={medication.dosage?.quantity || ''}
2147
+ onChange={e => (
2148
+ onChange((value || []).map((v, _i) =>
2149
+ i === _i
2150
+ ? { ...v, dosage: { ...v.dosage!, quantity: e.target.value } }
2151
+ : v
2152
+ ),
2153
+ field.id
2154
+ )
2155
+ )} />
2156
+ </Grid>
2157
+
2158
+ <Grid item sx={{ width: '30%' }}>
2159
+ <StringSelector size="small" label="How many times?"
2160
+ options={["1", "2", "3", "4", "5", "6", "As Needed"]}
2161
+ value={medication.dosage?.frequency ?? ''}
2162
+ onChange={async (frequency) => {
2163
+ onChange(
2164
+ (value ?? []).map((_v, _i) => (
2165
+ i === _i
2166
+ ? {
2167
+ ..._v,
2168
+ dosage: {
2169
+ ..._v.dosage!,
2170
+ frequency: frequency || ''
2171
+ }
2172
+ }
2173
+ : _v
2174
+ )),
2175
+ field.id,
2176
+ )
2177
+ }}
2178
+ />
2179
+ </Grid>
2180
+
2181
+ <Grid item sx={{ width: '20%' }}>
2182
+ <StringSelector options={['Day', 'Week', 'Month', "Year"]} size="small" label="Per"
2183
+ value={medication.dosage?.frequencyDescriptor || 'Day'}
2184
+ onChange={frequencyDescriptor => (
2185
+ onChange((value || []).map((v, _i) =>
2186
+ i === _i
2187
+ ? { ...v, dosage: { ...v.dosage!, frequencyDescriptor } }
2188
+ : v
2189
+ ),
2190
+ field.id
2191
+ )
2192
+ )}
2193
+ getDisplayValue={first_letter_capitalized}
2194
+ />
2195
+ </Grid>
2196
+ </Grid>
2197
+ </Grid>
2198
+
2199
+ <Grid item>
2200
+ <TextField InputProps={{ sx: defaultInputProps.sx }} fullWidth size="small" label="Reason for taking medication"
2201
+ value={medication.reasonForTaking || ''}
2202
+ onChange={e => onChange((value || []).map((v, _i) => i === _i ? { ...v, reasonForTaking: e.target.value } : v), field.id)}
2203
+ />
2204
+ </Grid>
2205
+
2206
+ <Grid item>
2207
+ <Divider flexItem sx={{ my: 0.5 }} />
2208
+ </Grid>
2209
+ </Grid>
2210
+ </Grid>
2211
+ ))}
2212
+ </Grid>
2213
+ )
2214
+ }
2215
+
2216
+ export const MedicationsInput = ({ field, value, onChange, ...props }: FormInputProps<'Medications'>) => {
2217
+ const { displayTerms, doneLoading, getCodesForDrug, getDrugsForDisplayTerm } = useMedications({
2218
+ dontFetch: field.options?.dataSource === CANVAS_TITLE
2219
+ })
2055
2220
  const [drugs, setDrugs] = useState<Record<string, Drug[]>>({})
2056
2221
 
2057
2222
  // uncomment to load data after initial typing
@@ -2080,6 +2245,9 @@ export const MedicationsInput = ({ field, value, onChange }: FormInputProps<'Med
2080
2245
  // .catch(console.error)
2081
2246
  // }, [value, getDrugsForDisplayTerm])
2082
2247
 
2248
+ if (field.options?.dataSource === CANVAS_TITLE) {
2249
+ return <CanvasMedicationsInput field={field} value={value} onChange={onChange} {...props} />
2250
+ }
2083
2251
  return (
2084
2252
  <Grid container direction="column" sx={{ mt: 2 }}>
2085
2253
  {(value ?? []).map((v, i) => (
@@ -2776,7 +2944,8 @@ export const HeightInput = ({ field, value={} as any, onChange, ...props }: Form
2776
2944
  </Grid>
2777
2945
  )
2778
2946
 
2779
- export const RedirectInput = ({ groupId, groupInsance, formResponseId, field, submit, value={} as any, onChange, responses, enduser, ...props }: FormInputProps<'Redirect'>) => {
2947
+ export const RedirectInput = ({ groupId, groupInsance, rootResponseId, formResponseId, field, submit, value={} as any, onChange, responses, enduser, ...props }: FormInputProps<'Redirect'>) => {
2948
+ console.log('formResponseId', formResponseId, 'rootResponseId', rootResponseId)
2780
2949
  const session = useResolvedSession()
2781
2950
 
2782
2951
  let eId = ''
@@ -2839,7 +3008,7 @@ export const RedirectInput = ({ groupId, groupInsance, formResponseId, field, su
2839
3008
  session.api.form_responses.prepare_form_response({
2840
3009
  enduserId: session.userInfo.id || eId,
2841
3010
  formId: field.options.redirectFormId,
2842
- rootResponseId: formResponseId,
3011
+ rootResponseId: rootResponseId || formResponseId,
2843
3012
  parentResponseId: formResponseId,
2844
3013
  })
2845
3014
  .then(({ fullURL }) => (
@@ -26,6 +26,7 @@ export interface FormInputProps<K extends keyof AnswerForType> {
26
26
  goToNextField?: () => void,
27
27
  isPreviousDisabled?: () => boolean,
28
28
  formResponseId?: string,
29
+ rootResponseId?: string,
29
30
  submit?: () => Promise<void>,
30
31
  groupId?: string,
31
32
  groupInsance?: string,