@tellescope/react-components 1.153.1 → 1.154.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.
Files changed (40) 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/hooks.d.ts +0 -1
  6. package/lib/cjs/Forms/hooks.d.ts.map +1 -1
  7. package/lib/cjs/Forms/inputs.d.ts.map +1 -1
  8. package/lib/cjs/Forms/inputs.js +83 -35
  9. package/lib/cjs/Forms/inputs.js.map +1 -1
  10. package/lib/cjs/controls.d.ts +2 -2
  11. package/lib/cjs/inputs.native.d.ts +0 -1
  12. package/lib/cjs/inputs.native.d.ts.map +1 -1
  13. package/lib/cjs/inputs_shared.d.ts +4 -1
  14. package/lib/cjs/inputs_shared.d.ts.map +1 -1
  15. package/lib/cjs/inputs_shared.js +7 -1
  16. package/lib/cjs/inputs_shared.js.map +1 -1
  17. package/lib/cjs/state.d.ts +36 -0
  18. package/lib/cjs/state.d.ts.map +1 -1
  19. package/lib/cjs/state.js +19 -3
  20. package/lib/cjs/state.js.map +1 -1
  21. package/lib/esm/Forms/forms.d.ts +3 -3
  22. package/lib/esm/Forms/inputs.d.ts +1 -1
  23. package/lib/esm/Forms/inputs.d.ts.map +1 -1
  24. package/lib/esm/Forms/inputs.js +84 -36
  25. package/lib/esm/Forms/inputs.js.map +1 -1
  26. package/lib/esm/controls.d.ts +2 -2
  27. package/lib/esm/inputs.d.ts +1 -1
  28. package/lib/esm/inputs_shared.d.ts +4 -1
  29. package/lib/esm/inputs_shared.d.ts.map +1 -1
  30. package/lib/esm/inputs_shared.js +6 -1
  31. package/lib/esm/inputs_shared.js.map +1 -1
  32. package/lib/esm/state.d.ts +88 -52
  33. package/lib/esm/state.d.ts.map +1 -1
  34. package/lib/esm/state.js +15 -0
  35. package/lib/esm/state.js.map +1 -1
  36. package/lib/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +9 -9
  38. package/src/Forms/inputs.tsx +89 -29
  39. package/src/inputs_shared.tsx +13 -2
  40. package/src/state.tsx +21 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellescope/react-components",
3
- "version": "1.153.1",
3
+ "version": "1.154.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.153.1",
51
- "@tellescope/sdk": "^1.153.1",
52
- "@tellescope/types-client": "^1.153.1",
53
- "@tellescope/types-models": "^1.153.1",
54
- "@tellescope/types-utilities": "^1.153.1",
55
- "@tellescope/utilities": "^1.153.1",
56
- "@tellescope/validation": "^1.153.1",
50
+ "@tellescope/constants": "^1.154.0",
51
+ "@tellescope/sdk": "^1.154.0",
52
+ "@tellescope/types-client": "^1.154.0",
53
+ "@tellescope/types-models": "^1.154.0",
54
+ "@tellescope/types-utilities": "^1.154.0",
55
+ "@tellescope/utilities": "^1.154.0",
56
+ "@tellescope/validation": "^1.154.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",
@@ -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": "0ad06bdf4ec4ea7871d68bedfc10fd1154fc742b",
83
+ "gitHead": "d96f27c5787398546a644b88fe6ad75208836bad",
84
84
  "publishConfig": {
85
85
  "access": "public"
86
86
  }
@@ -1,6 +1,6 @@
1
1
  import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react"
2
2
  import axios from "axios"
3
- import { Autocomplete, Box, Button, Checkbox, Divider, FormControl, FormControlLabel, FormLabel, Grid, InputLabel, MenuItem, Radio, RadioGroup, Select, SxProps, TextField, TextFieldProps, Typography } from "@mui/material"
3
+ import { Autocomplete, Box, Button, Checkbox, Chip, Divider, FormControl, FormControlLabel, FormLabel, Grid, InputLabel, MenuItem, Radio, RadioGroup, Select, SxProps, TextField, TextFieldProps, Typography } from "@mui/material"
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"
@@ -1447,6 +1447,7 @@ export const StripeInput = ({ field, value, onChange, setCustomerId }: FormInput
1447
1447
  const [isCheckout, setIsCheckout] = useState(false)
1448
1448
  const [stripePromise, setStripePromise] = useState<ReturnType<typeof loadStripe>>()
1449
1449
  const [, { findById: findProduct }] = useProducts({ dontFetch: true })
1450
+ const [answertext, setAnswertext] = useState('')
1450
1451
 
1451
1452
  const fetchRef = useRef(false)
1452
1453
  useEffect(() => {
@@ -1457,12 +1458,13 @@ export const StripeInput = ({ field, value, onChange, setCustomerId }: FormInput
1457
1458
  fetchRef.current = true
1458
1459
 
1459
1460
  session.api.form_responses.stripe_details({ fieldId: field.id })
1460
- .then(({ clientSecret, publishableKey, stripeAccount, businessName, customerId, isCheckout }) => {
1461
+ .then(({ clientSecret, publishableKey, stripeAccount, businessName, customerId, isCheckout, answerText }) => {
1461
1462
  setIsCheckout(!!isCheckout)
1462
1463
  setClientSecret(clientSecret)
1463
1464
  setStripePromise(loadStripe(publishableKey, { stripeAccount }))
1464
1465
  setBusinessName(businessName)
1465
1466
  setCustomerId(customerId)
1467
+ setAnswertext(answerText || '')
1466
1468
  })
1467
1469
  .catch(console.error)
1468
1470
  }, [session, value, field.id])
@@ -1488,7 +1490,7 @@ export const StripeInput = ({ field, value, onChange, setCustomerId }: FormInput
1488
1490
  <EmbeddedCheckoutProvider stripe={stripePromise}
1489
1491
  options={{
1490
1492
  clientSecret,
1491
- onComplete: () => onChange('Completed checkout', field.id),
1493
+ onComplete: () => onChange(answertext || 'Completed checkout', field.id),
1492
1494
  }}
1493
1495
  >
1494
1496
  <EmbeddedCheckout />
@@ -1498,7 +1500,7 @@ export const StripeInput = ({ field, value, onChange, setCustomerId }: FormInput
1498
1500
  <Elements stripe={stripePromise} options={{
1499
1501
  clientSecret,
1500
1502
  }}>
1501
- <StripeForm businessName={businessName} onSuccess={() => onChange('Saved card details', field.id)}
1503
+ <StripeForm businessName={businessName} onSuccess={() => onChange(answertext || 'Saved card details', field.id)}
1502
1504
  cost={cost}
1503
1505
  field={field}
1504
1506
  />
@@ -1841,6 +1843,7 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
1841
1843
  if (!doneLoading) return <LinearProgress />
1842
1844
  return (
1843
1845
  <Autocomplete id={field.id} freeSolo={false}
1846
+ componentsProps={{ popper: { sx: { wordBreak: "break-word" } } } }
1844
1847
  options={filteredChoices} multiple={true}
1845
1848
  getOptionLabel={o => (
1846
1849
  Array.isArray(o) // edge case
@@ -1872,6 +1875,16 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
1872
1875
  inputValue={typing}
1873
1876
  onInputChange={(e, v) => e && setTyping(v)}
1874
1877
  renderInput={params => <TextField {...params} InputProps={{ ...params.InputProps, sx: defaultInputProps.sx }} />}
1878
+ // use custom Chip to ensure very long entries break properly (whitespace: normal)
1879
+ renderTags={(value, getTagProps) =>
1880
+ value.map((value, index) => (
1881
+ <Chip
1882
+ label={<Typography style={{whiteSpace: 'normal'}}>{Array.isArray(value) ? '' : label_for_database_record(field, value)}</Typography>}
1883
+ {...getTagProps({ index })}
1884
+ sx={{height:"100%", py: 0.5 }}
1885
+ />
1886
+ ))
1887
+ }
1875
1888
  />
1876
1889
  )
1877
1890
  }
@@ -2861,6 +2874,12 @@ export const AllergiesInput = ({ goToNextField, goToPreviousField, field, value,
2861
2874
  const [query, setQuery] = useState('')
2862
2875
  const [results, setResults] = useState<{ code: string, display: string }[]>([])
2863
2876
 
2877
+ // if two allergy questions shown in a row, reset state
2878
+ useEffect(() => {
2879
+ setQuery('')
2880
+ setResults([])
2881
+ }, [field.id])
2882
+
2864
2883
  const fetchRef = useRef(query)
2865
2884
  useEffect(() => {
2866
2885
  if (fetchRef.current === query) return
@@ -2869,36 +2888,55 @@ export const AllergiesInput = ({ goToNextField, goToPreviousField, field, value,
2869
2888
  if (!query) return
2870
2889
 
2871
2890
  const t = setTimeout(() => {
2872
- session.api.integrations
2873
- .proxy_read({
2874
- integration: CANVAS_TITLE,
2875
- type: 'allergies',
2876
- query,
2877
- })
2878
- .then((r : { data: AllergyResult }) => {
2879
- const deduped: typeof results = []
2880
- const totalResults = (
2881
- (r.data.entry || [])
2882
- .flatMap(v => v?.resource?.code?.coding || [])
2883
- .filter(v => v.system.includes('fdbhealth'))
2884
- .map(v => ({ code: v.code, display: v.display, system: v.system }))
2885
- )
2886
- for (const v of totalResults) {
2887
- if (deduped.find(d => d.display === v.display)) { continue }
2891
+ if (field.options?.dataSource === CANVAS_TITLE) {
2892
+ session.api.integrations
2893
+ .proxy_read({
2894
+ integration: CANVAS_TITLE,
2895
+ type: 'allergies',
2896
+ query,
2897
+ })
2898
+ .then((r : { data: AllergyResult }) => {
2899
+ const deduped: typeof results = []
2900
+ const totalResults = (
2901
+ (r.data.entry || [])
2902
+ .flatMap(v => v?.resource?.code?.coding || [])
2903
+ .filter(v => v.system.includes('fdbhealth'))
2904
+ .map(v => ({ code: v.code, display: v.display, system: v.system }))
2905
+ )
2906
+ for (const v of totalResults) {
2907
+ if (deduped.find(d => d.display === v.display)) { continue }
2888
2908
 
2889
- deduped.push(v)
2890
- }
2891
- setResults(deduped)
2892
- })
2909
+ deduped.push(v)
2910
+ }
2911
+ setResults(deduped)
2912
+ })
2913
+ } else {
2914
+ session.api.allergy_codes.getSome({ search: { query }})
2915
+ .then(results => {
2916
+ const deduped: typeof results = []
2917
+ for (const v of results) {
2918
+ if (deduped.find(d => d.display === v.display)) { continue }
2919
+
2920
+ deduped.push(v)
2921
+ }
2922
+ setResults(deduped)
2923
+ })
2924
+ }
2925
+
2926
+
2893
2927
  }, 200)
2894
2928
 
2895
2929
  return () => { clearTimeout(t) }
2896
- }, [session, query])
2930
+ }, [session, query, field?.options?.dataSource])
2897
2931
 
2898
2932
  return (
2899
- <Autocomplete multiple value={value || []} options={[...results, ...(value || [])]} style={{ marginTop: 5 }}
2933
+ <Autocomplete multiple value={value || []} options={results} style={{ marginTop: 5 }}
2900
2934
  noOptionsText={query.length ? 'No results found' : 'Type to start search'}
2901
- onChange={(e, v) => v && onChange(v, field.id)}
2935
+ onChange={(e, v) => {
2936
+ if (!v) { return }
2937
+ onChange(v, field.id)
2938
+ setResults([])
2939
+ }}
2902
2940
  getOptionLabel={v => first_letter_capitalized(v.display)} filterOptions={o => o}
2903
2941
  inputValue={query} onInputChange={(e, v) => e && setQuery(v) }
2904
2942
  renderInput={(params) => (
@@ -2906,6 +2944,15 @@ export const AllergiesInput = ({ goToNextField, goToPreviousField, field, value,
2906
2944
  required={!field.isOptional} size="small" label="" placeholder="Search allergies..."
2907
2945
  />
2908
2946
  )}
2947
+ renderTags={(value, getTagProps) =>
2948
+ value.map((value, index) => (
2949
+ <Chip
2950
+ label={<Typography style={{whiteSpace: 'normal'}}>{value.display}</Typography>}
2951
+ {...getTagProps({ index })}
2952
+ sx={{height:"100%", py: 0.5 }}
2953
+ />
2954
+ ))
2955
+ }
2909
2956
  />
2910
2957
  )
2911
2958
  }
@@ -2939,9 +2986,13 @@ export const ConditionsInput = ({ goToNextField, goToPreviousField, field, value
2939
2986
  }, [session, query])
2940
2987
 
2941
2988
  return (
2942
- <Autocomplete multiple value={value || []} options={[...results, ...(value || [])]} style={{ marginTop: 5 }}
2989
+ <Autocomplete multiple value={value || []} options={results} style={{ marginTop: 5 }}
2943
2990
  noOptionsText={query.length ? 'No results found' : 'Type to start search'}
2944
- onChange={(e, v) => v && onChange(v, field.id)}
2991
+ onChange={(e, v) => {
2992
+ if (!v) { return }
2993
+ onChange(v, field.id)
2994
+ setResults([])
2995
+ }}
2945
2996
  getOptionLabel={v => first_letter_capitalized(v.display)} filterOptions={o => o}
2946
2997
  inputValue={query} onInputChange={(e, v) => e && setQuery(v) }
2947
2998
  renderInput={(params) => (
@@ -2949,6 +3000,15 @@ export const ConditionsInput = ({ goToNextField, goToPreviousField, field, value
2949
3000
  required={!field.isOptional} size="small" label="" placeholder="Search conditions..."
2950
3001
  />
2951
3002
  )}
3003
+ renderTags={(value, getTagProps) =>
3004
+ value.map((value, index) => (
3005
+ <Chip
3006
+ label={<Typography style={{whiteSpace: 'normal'}}>{value.display}</Typography>}
3007
+ {...getTagProps({ index })}
3008
+ sx={{height:"100%", py: 0.5 }}
3009
+ />
3010
+ ))
3011
+ }
2952
3012
  />
2953
3013
  )
2954
3014
  }
@@ -5,8 +5,8 @@ import { LoadFunction, LoadFunctionArguments } from "@tellescope/sdk"
5
5
  import { ALL_ACCESS, UNSEARCHABLE_FIELDS } from "@tellescope/constants"
6
6
  import { SearchAPIProps, useSearchAPI } from "./hooks"
7
7
  import { TextFieldProps } from "./mui"
8
- import { AppointmentBookingPage, AppointmentLocation, AutomationTrigger, CalendarEventTemplate, CallHoldQueue, ChatRoom, Database, DatabaseRecord, DiagnosisCode, Enduser, EnduserOrder, FaxLog, File, Form, FormGroup, Forum, Journey, ManagedContentRecord, MessageTemplateSnippet, Organization, PrescriptionRoute, SuggestedContact, Template, Ticket, TicketQueue, User, UserNotification } from "@tellescope/types-client"
9
- import { Button, Checkbox, Flex, HoverPaper, LoadingButton, LoadingData, LoadingLinear, ScrollingList, SearchTextInput, Typography, useAppointmentBookingPages, useAppointmentLocations, useAutomationTriggers, useCalendarEventTemplates, useCallHoldQueues, useChatRooms, useDatabaseRecords, useDatabases, useDiagnosisCodes, useEnduserOrders, useEndusers, useFaxLogs, useFiles, useFormGroups, useForms, useForums, useJourneys, useManagedContentRecords, useMessageTemplateSnippets, useNotifications, useOrganization, useOrganizations, usePrescriptionRoutes, useResolvedSession, useSession, useSuggestedContacts, useTemplates, useTicketQueues, useTickets, useUsers, value_is_loaded } from "."
8
+ import { AllergyCode, AppointmentBookingPage, AppointmentLocation, AutomationTrigger, CalendarEventTemplate, CallHoldQueue, ChatRoom, Database, DatabaseRecord, DiagnosisCode, Enduser, EnduserOrder, FaxLog, File, Form, FormGroup, Forum, Journey, ManagedContentRecord, MessageTemplateSnippet, Organization, PrescriptionRoute, SuggestedContact, Template, Ticket, TicketQueue, User, UserNotification } from "@tellescope/types-client"
9
+ import { Button, Checkbox, Flex, HoverPaper, LoadingButton, LoadingData, LoadingLinear, ScrollingList, SearchTextInput, Typography, useAllergyCodes, useAppointmentBookingPages, useAppointmentLocations, useAutomationTriggers, useCalendarEventTemplates, useCallHoldQueues, useChatRooms, useDatabaseRecords, useDatabases, useDiagnosisCodes, useEnduserOrders, useEndusers, useFaxLogs, useFiles, useFormGroups, useForms, useForums, useJourneys, useManagedContentRecords, useMessageTemplateSnippets, useNotifications, useOrganization, useOrganizations, usePrescriptionRoutes, useResolvedSession, useSession, useSuggestedContacts, useTemplates, useTicketQueues, useTickets, useUsers, value_is_loaded } from "."
10
10
  import { SxProps } from "@mui/material"
11
11
  import { AccessPermissions } from "@tellescope/types-models"
12
12
 
@@ -618,6 +618,17 @@ export const SuggestedContactSearch = (props: Omit<GenericSearchProps<SuggestedC
618
618
  )
619
619
  }
620
620
 
621
+ export const AllergyCodeSearch = (props: Omit<GenericSearchProps<AllergyCode>, 'filterKey'> & { filterKey?: string }) => {
622
+ const session = useSession()
623
+ const [, { addLocalElements }] = useAllergyCodes({ dontFetch: true })
624
+ return (
625
+ <ModelSearchInput filterKey="allergy-code" {...props}
626
+ searchAPI={session.api.allergy_codes.getSome}
627
+ onLoad={addLocalElements}
628
+ />
629
+ )
630
+ }
631
+
621
632
  export const DiagnosisCodeSearch = (props: Omit<GenericSearchProps<DiagnosisCode>, 'filterKey'> & { filterKey?: string }) => {
622
633
  const session = useSession()
623
634
  const [, { addLocalElements }] = useDiagnosisCodes({ dontFetch: true })
package/src/state.tsx CHANGED
@@ -94,6 +94,7 @@ import {
94
94
  CallHoldQueue,
95
95
  SuggestedContact,
96
96
  DiagnosisCode,
97
+ AllergyCode,
97
98
  } from "@tellescope/types-client"
98
99
 
99
100
  import {
@@ -355,6 +356,7 @@ const messageTemplateSnippetsSlice = createSliceForList<MessageTemplateSnippet,
355
356
  const faxLogsSlice = createSliceForList<FaxLog, 'fax_logs'>('fax_logs')
356
357
  const suggestedContactsSlice = createSliceForList<SuggestedContact, 'suggested_contacts'>('suggested_contacts')
357
358
  const diagnosisCodesSlice = createSliceForList<DiagnosisCode, 'diagnosis_codes'>('diagnosis_codes')
359
+ const allergyCodesSlice = createSliceForList<AllergyCode, 'allergy_codes'>('allergy_codes')
358
360
 
359
361
  const roleBasedAccessPermissionsSlice = createSliceForList<RoleBasedAccessPermission, 'role_based_access_permissions'>('role_based_access_permissions')
360
362
 
@@ -443,6 +445,7 @@ export const sharedConfig = {
443
445
  call_hold_queues: callHoldQueuesSlice.reducer,
444
446
  suggested_contacts: suggestedContactsSlice.reducer,
445
447
  diagnosis_codes: diagnosisCodesSlice.reducer,
448
+ allergy_codes: allergyCodesSlice.reducer,
446
449
  },
447
450
  }
448
451
 
@@ -1259,6 +1262,24 @@ export const usePortalBrandings = (options={} as HookOptions<PortalBranding>) =>
1259
1262
  },
1260
1263
  )
1261
1264
  }
1265
+ export const useAllergyCodes = (options={} as HookOptions<AllergyCode>) => {
1266
+ const session = useResolvedSession()
1267
+
1268
+ return useListStateHook('allergy_codes', useTypedSelector(s => s.allergy_codes), session, allergyCodesSlice,
1269
+ {
1270
+ loadQuery: session.api.allergy_codes.getSome,
1271
+ findOne: session.api.allergy_codes.getOne,
1272
+ findByIds: session.api.allergy_codes.getByIds,
1273
+ addOne: session.api.allergy_codes.createOne,
1274
+ addSome: session.api.allergy_codes.createSome,
1275
+ deleteOne: session.api.allergy_codes.deleteOne,
1276
+ updateOne: session.api.allergy_codes.updateOne,
1277
+ },
1278
+ {
1279
+ ...options,
1280
+ },
1281
+ )
1282
+ }
1262
1283
  export const useDiagnosisCodes = (options={} as HookOptions<DiagnosisCode>) => {
1263
1284
  const session = useResolvedSession()
1264
1285