@tellescope/react-components 1.205.0 → 1.207.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 (68) hide show
  1. package/lib/cjs/Forms/form_responses.d.ts +6 -2
  2. package/lib/cjs/Forms/form_responses.d.ts.map +1 -1
  3. package/lib/cjs/Forms/form_responses.js +8 -7
  4. package/lib/cjs/Forms/form_responses.js.map +1 -1
  5. package/lib/cjs/Forms/forms.d.ts +5 -1
  6. package/lib/cjs/Forms/forms.d.ts.map +1 -1
  7. package/lib/cjs/Forms/forms.js +12 -8
  8. package/lib/cjs/Forms/forms.js.map +1 -1
  9. package/lib/cjs/Forms/hooks.d.ts.map +1 -1
  10. package/lib/cjs/Forms/hooks.js +4 -5
  11. package/lib/cjs/Forms/hooks.js.map +1 -1
  12. package/lib/cjs/Forms/inputs.d.ts +8 -3
  13. package/lib/cjs/Forms/inputs.d.ts.map +1 -1
  14. package/lib/cjs/Forms/inputs.js +51 -34
  15. package/lib/cjs/Forms/inputs.js.map +1 -1
  16. package/lib/cjs/displays.d.ts +2 -0
  17. package/lib/cjs/displays.d.ts.map +1 -1
  18. package/lib/cjs/displays.js.map +1 -1
  19. package/lib/cjs/inputs_shared.d.ts.map +1 -1
  20. package/lib/cjs/inputs_shared.js +25 -1
  21. package/lib/cjs/inputs_shared.js.map +1 -1
  22. package/lib/cjs/layout.d.ts +2 -1
  23. package/lib/cjs/layout.d.ts.map +1 -1
  24. package/lib/cjs/layout.js +2 -2
  25. package/lib/cjs/layout.js.map +1 -1
  26. package/lib/cjs/state.d.ts +37 -0
  27. package/lib/cjs/state.d.ts.map +1 -1
  28. package/lib/cjs/state.js +19 -3
  29. package/lib/cjs/state.js.map +1 -1
  30. package/lib/esm/Forms/form_responses.d.ts +6 -2
  31. package/lib/esm/Forms/form_responses.d.ts.map +1 -1
  32. package/lib/esm/Forms/form_responses.js +8 -7
  33. package/lib/esm/Forms/form_responses.js.map +1 -1
  34. package/lib/esm/Forms/forms.d.ts +5 -1
  35. package/lib/esm/Forms/forms.d.ts.map +1 -1
  36. package/lib/esm/Forms/forms.js +12 -8
  37. package/lib/esm/Forms/forms.js.map +1 -1
  38. package/lib/esm/Forms/hooks.d.ts.map +1 -1
  39. package/lib/esm/Forms/hooks.js +4 -5
  40. package/lib/esm/Forms/hooks.js.map +1 -1
  41. package/lib/esm/Forms/inputs.d.ts +8 -3
  42. package/lib/esm/Forms/inputs.d.ts.map +1 -1
  43. package/lib/esm/Forms/inputs.js +51 -34
  44. package/lib/esm/Forms/inputs.js.map +1 -1
  45. package/lib/esm/displays.d.ts +2 -0
  46. package/lib/esm/displays.d.ts.map +1 -1
  47. package/lib/esm/displays.js.map +1 -1
  48. package/lib/esm/inputs_shared.d.ts.map +1 -1
  49. package/lib/esm/inputs_shared.js +25 -1
  50. package/lib/esm/inputs_shared.js.map +1 -1
  51. package/lib/esm/layout.d.ts +2 -1
  52. package/lib/esm/layout.d.ts.map +1 -1
  53. package/lib/esm/layout.js +2 -2
  54. package/lib/esm/layout.js.map +1 -1
  55. package/lib/esm/state.d.ts +37 -0
  56. package/lib/esm/state.d.ts.map +1 -1
  57. package/lib/esm/state.js +15 -0
  58. package/lib/esm/state.js.map +1 -1
  59. package/lib/tsconfig.tsbuildinfo +1 -1
  60. package/package.json +11 -11
  61. package/src/Forms/form_responses.tsx +9 -8
  62. package/src/Forms/forms.tsx +13 -2
  63. package/src/Forms/hooks.tsx +1 -3
  64. package/src/Forms/inputs.tsx +38 -5
  65. package/src/displays.tsx +2 -0
  66. package/src/inputs_shared.tsx +17 -1
  67. package/src/layout.tsx +3 -2
  68. package/src/state.tsx +22 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellescope/react-components",
3
- "version": "1.205.0",
3
+ "version": "1.207.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.205.0",
51
- "@tellescope/sdk": "^1.205.0",
52
- "@tellescope/types-client": "^1.205.0",
53
- "@tellescope/types-models": "^1.205.0",
54
- "@tellescope/types-utilities": "^1.205.0",
55
- "@tellescope/utilities": "^1.205.0",
56
- "@tellescope/validation": "^1.205.0",
50
+ "@tellescope/constants": "^1.207.0",
51
+ "@tellescope/sdk": "^1.207.0",
52
+ "@tellescope/types-client": "^1.207.0",
53
+ "@tellescope/types-models": "^1.207.0",
54
+ "@tellescope/types-utilities": "^1.207.0",
55
+ "@tellescope/utilities": "^1.207.0",
56
+ "@tellescope/validation": "^1.207.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,11 +80,11 @@
80
80
  "yup": "^0.32.10"
81
81
  },
82
82
  "peerDependencies": {
83
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
84
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
83
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
84
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
85
85
  "react-native": "^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.71.0"
86
86
  },
87
- "gitHead": "2207d17c9959fcef3194f08245f8890817739b4e",
87
+ "gitHead": "ddf48910e1681e4fc241e85af98f4c6a0f3f42bb",
88
88
  "publishConfig": {
89
89
  "access": "public"
90
90
  }
@@ -1,8 +1,8 @@
1
- import React from "react"
1
+ import React, { useEffect } from "react"
2
2
  import { Divider, Grid, Typography } from "@mui/material"
3
3
  import { Enduser, FormResponse } from "@tellescope/types-client"
4
4
  import { form_response_value_to_string, formatted_date, getOrgnizationLogoURL, remove_script_tags, user_display_name } from "@tellescope/utilities"
5
- import { DownloadFileIconButton, LabeledIconButton, SecureImage, useEndusers, useOrganization, useResolvedSession, useSession, useUsers, value_is_loaded } from "../index"
5
+ import { DownloadFileIconButton, ImageProps, LabeledIconButton, SecureImage, useEndusers, useOrganization, useResolvedSession, useSession, useUsers, value_is_loaded } from "../index"
6
6
  import CloseIcon from '@mui/icons-material/Close';
7
7
  import { DatabaseSelectResponse, FormResponseAnswerAddress, FormResponseValueAnswer } from "@tellescope/types-models"
8
8
  import { Image } from "../layout"
@@ -64,6 +64,7 @@ export const ResponseAnswer = ({ formResponse, fieldId, isHTML, answer: a, print
64
64
  : (
65
65
  <SecureImage secureName={a.value.secureName} onImageClick={onImageClick}
66
66
  style={{ maxHeight: 400, maxWidth: 400 }}
67
+ crossOrigin="anonymous"
67
68
  />
68
69
  )
69
70
  }
@@ -181,7 +182,7 @@ export const ResponseAnswer = ({ formResponse, fieldId, isHTML, answer: a, print
181
182
  )
182
183
  )
183
184
 
184
- export const OrganizationLogo = () => {
185
+ export const OrganizationLogo = ({ crossOrigin } : { crossOrigin?: ImageProps['crossOrigin'] }) => {
185
186
  const [organizationLoading] = useOrganization()
186
187
 
187
188
  if (!value_is_loaded(organizationLoading)) return null
@@ -190,7 +191,7 @@ export const OrganizationLogo = () => {
190
191
  const logoURL = getOrgnizationLogoURL(organizationLoading.value)
191
192
 
192
193
  return (
193
- <Image
194
+ <Image crossOrigin={crossOrigin}
194
195
  src={logoURL}
195
196
  alt=""
196
197
  maxWidth={400}
@@ -199,12 +200,12 @@ export const OrganizationLogo = () => {
199
200
  )
200
201
  }
201
202
 
202
- export const ResolveOrganizationLogo = ({ logoURL } : { logoURL?: string }) => {
203
+ export const ResolveOrganizationLogo = ({ logoURL, crossOrigin } : { logoURL?: string, crossOrigin?: ImageProps['crossOrigin'] }) => {
203
204
  const session = useResolvedSession()
204
205
 
205
206
  if (logoURL) {
206
207
  return (
207
- <Image
208
+ <Image crossOrigin={crossOrigin}
208
209
  src={logoURL}
209
210
  alt=""
210
211
  maxWidth={400}
@@ -215,7 +216,7 @@ export const ResolveOrganizationLogo = ({ logoURL } : { logoURL?: string }) => {
215
216
 
216
217
  if (session.type === 'enduser') return null
217
218
 
218
- return <OrganizationLogo />
219
+ return <OrganizationLogo crossOrigin={crossOrigin} />
219
220
  }
220
221
 
221
222
  interface FormResponse_T {
@@ -245,7 +246,7 @@ export const FormResponseView = ({ showAnswerInline=true, logoURL, enduser, onCl
245
246
  <div style={{ textAlign: 'center' }}>
246
247
  {!hideHeader &&
247
248
  <>
248
- <ResolveOrganizationLogo logoURL={logoURL} />
249
+ <ResolveOrganizationLogo logoURL={logoURL} crossOrigin="anonymous" />
249
250
 
250
251
  <h2 style={{
251
252
  fontSize: 20,
@@ -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 { 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, defaultButtonStyles } from "./inputs"
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, 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"
@@ -35,6 +35,7 @@ export const TellescopeFormContainer = ({ businessId, organizationIds, ...props
35
35
 
36
36
  const TellescopeFormContainerWithTheme: typeof TellescopeFormContainer = ({ children, language, onChangeLanguage, style, hideBg, backgroundColor, hideLogo, logoHeight }) => {
37
37
  const theme = useOrganizationTheme()
38
+ console.log('logoHeight',logoHeight)
38
39
 
39
40
  const formContent = (
40
41
  <Flex flex={1} column>
@@ -96,12 +97,13 @@ export interface TellescopeFormProps extends ReturnType<typeof useTellescopeForm
96
97
  enduser?: Partial<Enduser>,
97
98
  groupId?: string,
98
99
  groupInstance?: string,
100
+ logoHeight?: number,
99
101
  }
100
102
 
101
103
  const LOGO_HEIGHT = 40
102
104
  export const TellescopeForm = (props : TellescopeFormProps & Styled & { hideBg?: boolean, theme?: OrganizationTheme, inputStyle?: React.CSSProperties }) => (
103
105
  <WithOrganizationTheme>
104
- <TellescopeFormWithContext {...props} />
106
+ <TellescopeFormWithContext {...props} logoHeight={props?.logoHeight || props?.form?.customization?.logoHeight} />
105
107
  </WithOrganizationTheme>
106
108
  )
107
109
 
@@ -137,6 +139,7 @@ export const QuestionForField = ({
137
139
  logicOptions,
138
140
  uploadingFiles, setUploadingFiles, handleFileUpload,
139
141
  groupFields,
142
+ AddToDatabase,
140
143
  } : {
141
144
  spacing?: number,
142
145
  form?: Form,
@@ -154,6 +157,7 @@ export const QuestionForField = ({
154
157
  uploadingFiles: { fieldId: string }[]
155
158
  setUploadingFiles: React.Dispatch<React.SetStateAction<{ fieldId: string }[]>>,
156
159
  groupFields?: FormField[],
160
+ AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
157
161
  } & Pick<TellescopeFormProps, "rootResponseId" | "goToNextField" | "groupId" | "groupInstance" | "submit" | "formResponseId" | 'enduserId' | 'isPreviousDisabled' | 'goToPreviousField' | 'enduser' | 'handleDatabaseSelect' | 'onAddFile' | 'onFieldChange' | 'fields' | 'customInputs' | 'responses' | 'selectedFiles' | 'validateField'>) => {
158
162
  const String = customInputs?.['string'] ?? StringInput
159
163
  const StringLong = customInputs?.['stringLong'] ?? StringLongInput
@@ -325,6 +329,7 @@ export const QuestionForField = ({
325
329
  <DatabaseSelect field={field} disabled={value.disabled} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Database Select'>}
326
330
  onDatabaseSelect={handleDatabaseSelect}
327
331
  responses={responses} form={form}
332
+ AddToDatabase={AddToDatabase}
328
333
  />
329
334
  )
330
335
  : field.type === 'Medications' ? (
@@ -332,6 +337,7 @@ export const QuestionForField = ({
332
337
  )
333
338
  : field.type === 'Insurance' ? (
334
339
  <Insurance field={field} value={value.answer.value as any} form={form}
340
+ onDatabaseSelect={handleDatabaseSelect}
335
341
  enduser={enduser} responses={responses} // for filtering insurers by state
336
342
  onChange={(v, fieldId) => (onFieldChange as ChangeHandler<'Insurance'>)({
337
343
  ...v,
@@ -381,6 +387,7 @@ export const QuestionForField = ({
381
387
  questionGroupSize={field.options?.subFields?.length}
382
388
  uploadingFiles={uploadingFiles} setUploadingFiles={setUploadingFiles}
383
389
  handleFileUpload={handleFileUpload}
390
+ AddToDatabase={AddToDatabase}
384
391
  />
385
392
  </Flex>
386
393
  )
@@ -692,6 +699,7 @@ const TellescopeFormWithContext: typeof TellescopeForm = (props) => {
692
699
  return (
693
700
  <TellescopeFormContainer style={props.style} dontAddContext
694
701
  hideBg={props.hideBg || props.form?.customization?.hideBg}
702
+ logoHeight={props.logoHeight}
695
703
  backgroundColor={props.backgroundColor}
696
704
  hideLogo={props?.customization?.hideLogo}
697
705
  >
@@ -918,6 +926,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
918
926
  updatedAt?: Date,
919
927
  otherEnduserIds?: string[],
920
928
  onBulkErrors?: (errors: { enduserId: string, message: string }[]) => void,
929
+ AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
921
930
  }> = ({
922
931
  customInputs,
923
932
  submitErrorMessage,
@@ -969,6 +978,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
969
978
  groupId,
970
979
  groupInstance,
971
980
  uploadingFiles, setUploadingFiles, handleFileUpload,
981
+ AddToDatabase,
972
982
  ...props
973
983
  }) => {
974
984
  const list = useListForFormFields(fields, responses, { form: props.form, gender: enduser?.gender })
@@ -1051,6 +1061,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
1051
1061
  groupId={groupId} groupInstance={groupInstance}
1052
1062
  uploadingFiles={uploadingFiles} setUploadingFiles={setUploadingFiles}
1053
1063
  handleFileUpload={handleFileUpload}
1064
+ AddToDatabase={AddToDatabase}
1054
1065
  />
1055
1066
  </Flex>
1056
1067
  </Flex>
@@ -653,9 +653,7 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
653
653
  ? (
654
654
  (f.options?.default && !isNaN(parseInt(f.options.default)))
655
655
  ? parseInt(f.options.default)
656
- : f.isOptional
657
- ? undefined
658
- : (f.options?.from || 1)
656
+ : undefined // shows no selection on slider
659
657
  )
660
658
  : f.type === 'Related Contacts'
661
659
  ? (f.isOptional ? [] : [{ relationships: f?.options?.relatedContactTypes?.length === 1 ? [{ type: f.options.relatedContactTypes[0] as EnduserRelationship['type'], id: ''! } ] : [] }])
@@ -532,10 +532,10 @@ export const NumberInput = ({ field, value, onChange, form, ...props }: FormInpu
532
532
  )
533
533
  }
534
534
 
535
- export const InsuranceInput = ({ field, value, onChange, form, responses, enduser, ...props }: FormInputProps<'Insurance'>) => {
535
+ export const InsuranceInput = ({ field, onDatabaseSelect, value, onChange, form, responses, enduser, ...props }: FormInputProps<'Insurance'>) => {
536
536
  const session = useResolvedSession()
537
537
 
538
- const [payers, setPayers] = useState<{ id: string, name: string, type?: string, state?: string }[]>([])
538
+ const [payers, setPayers] = useState<{ id: string, name: string, databaseRecord?: DatabaseRecord, type?: string, state?: string }[]>([])
539
539
  const [query, setQuery] = useState('')
540
540
 
541
541
  const addressQuestion = useMemo(() => responses?.find(r => {
@@ -567,6 +567,7 @@ export const InsuranceInput = ({ field, value, onChange, form, responses, enduse
567
567
  name: c.values.find(v => v.label?.trim()?.toLowerCase() === 'name')?.value?.toString() || '',
568
568
  state: c.values.find(v => v.label?.trim()?.toLowerCase() === 'state')?.value?.toString() || '',
569
569
  type: c.values.find(v => v.label?.trim()?.toLowerCase() === 'type')?.value?.toString() || '',
570
+ databaseRecord: c,
570
571
  }))
571
572
  .filter(c => !c.state || !state || (c.state === state))
572
573
  ))
@@ -613,6 +614,11 @@ export const InsuranceInput = ({ field, value, onChange, form, responses, enduse
613
614
  : (e, v) => {
614
615
  if (v) { setQuery(v) }
615
616
 
617
+ const databaseRecord = payers.find(p => p.name === v)?.databaseRecord
618
+ if (databaseRecord) {
619
+ onDatabaseSelect?.([databaseRecord])
620
+ }
621
+
616
622
  onChange({
617
623
  ...value,
618
624
  payerName: v || '',
@@ -1864,7 +1870,18 @@ const useDatabaseChoices = ({ databaseId='', field, otherAnswers } : { databaseI
1864
1870
  })
1865
1871
  }, [session, field, databaseId, renderCount])
1866
1872
 
1873
+ const addChoice = useCallback((record: DatabaseRecord) => {
1874
+ if (!choicesForDatabase[databaseId]) {
1875
+ choicesForDatabase[databaseId] = {
1876
+ done: false,
1877
+ records: [],
1878
+ }
1879
+ }
1880
+ choicesForDatabase[databaseId].records!.push(record)
1881
+ }, [choicesForDatabase, databaseId])
1882
+
1867
1883
  return {
1884
+ addChoice,
1868
1885
  doneLoading: choicesForDatabase[databaseId]?.done ?? false,
1869
1886
  choices: [
1870
1887
  ...choicesForDatabase[databaseId]?.records ?? [],
@@ -1915,11 +1932,17 @@ const get_other_answers = (_value?: DatabaseSelectResponse[], typing?: string) =
1915
1932
  return []
1916
1933
  }
1917
1934
 
1918
- export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabaseSelect, responses, size, disabled }: FormInputProps<'Database Select'> & {
1935
+ export interface AddToDatabaseProps {
1936
+ databaseId: string,
1937
+ onAdd: (record: DatabaseRecord) => void
1938
+ }
1939
+
1940
+ export const DatabaseSelectInput = ({ AddToDatabase, field, value: _value, onChange, onDatabaseSelect, responses, size, disabled }: FormInputProps<'Database Select'> & {
1919
1941
  responses: FormResponseValue[],
1942
+ AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
1920
1943
  }) => {
1921
1944
  const [typing, setTyping] = useState('')
1922
- const { choices, doneLoading } = useDatabaseChoices({
1945
+ const { addChoice, choices, doneLoading } = useDatabaseChoices({
1923
1946
  databaseId: field.options?.databaseId,
1924
1947
  field,
1925
1948
  otherAnswers: get_other_answers(_value, field?.options?.other ? typing : undefined),
@@ -2010,6 +2033,7 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
2010
2033
 
2011
2034
  if (!doneLoading) return <LinearProgress />
2012
2035
  return (
2036
+ <>
2013
2037
  <Autocomplete id={field.id} freeSolo={false} size={size}
2014
2038
  componentsProps={{ popper: { sx: { wordBreak: "break-word" } } } }
2015
2039
  options={filteredChoices} multiple={true}
@@ -2022,7 +2046,11 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
2022
2046
  disabled={disabled}
2023
2047
  onChange={(_, v) => {
2024
2048
  if (v.length && onDatabaseSelect) {
2025
- onDatabaseSelect(v)
2049
+ onDatabaseSelect(
2050
+ field.options?.radio
2051
+ ? [v[v.length - 1]] // if radio, only last selected
2052
+ : v
2053
+ )
2026
2054
  }
2027
2055
  return onChange(
2028
2056
  (
@@ -2055,6 +2083,11 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
2055
2083
  ))
2056
2084
  }
2057
2085
  />
2086
+
2087
+ {AddToDatabase && field?.options?.allowAddToDatabase && (
2088
+ <AddToDatabase databaseId={field.options?.databaseId!} onAdd={addChoice} />
2089
+ )}
2090
+ </>
2058
2091
  )
2059
2092
  }
2060
2093
 
package/src/displays.tsx CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  value_is_loaded,
9
9
  useUsers,
10
10
  convertHEIC,
11
+ ImageProps,
11
12
  } from "./index"
12
13
 
13
14
  import { Avatar, AvatarProps, Styled } from "./mui"
@@ -72,6 +73,7 @@ export const SecureImage = ({ secureName, placeholder, onImageClick, ...props }
72
73
  secureName: string,
73
74
  alt?: string,
74
75
  onImageClick?: (args: { src: string }) => void,
76
+ crossOrigin?: ImageProps['crossOrigin'],
75
77
  } & ImageDimensions & Styled) => {
76
78
  const loadedImage = useFileForSecureName({ secureName })
77
79
 
@@ -9,6 +9,7 @@ import { AgentRecord, AllergyCode, AppointmentBookingPage, AppointmentLocation,
9
9
  import { Button, Checkbox, Flex, HoverPaper, LoadingButton, LoadingData, ScrollingList, SearchTextInput, Typography, useAgentRecords, useAllergyCodes, useAppointmentBookingPages, useAppointmentLocations, useAutomationTriggers, useCalendarEventTemplates, useCallHoldQueues, useChatRooms, useDatabaseRecords, useDatabases, useDiagnosisCodes, useEnduserCustomTypes, useEnduserOrders, useEndusers, useFaxLogs, useFiles, useFormGroups, useForms, useForums, useJourneys, useManagedContentRecords, useMessageTemplateSnippets, useNotifications, useOrganization, useOrganizations, usePrescriptionRoutes, useResolvedSession, useSession, useSuggestedContacts, useTemplates, useTicketQueues, useTickets, useUsers, useWaitlists, value_is_loaded } from "."
10
10
  import { SxProps } from "@mui/material"
11
11
  import { AccessPermissions, ListOfStringsWithQualifier } from "@tellescope/types-models"
12
+ import { phoneValidator } from "@tellescope/validation"
12
13
 
13
14
  export type FilterV2 = Record<string, any>
14
15
  export type FiltersV2 = Record<string, FilterV2>
@@ -885,7 +886,22 @@ export const EnduserSearch = (props: Omit<GenericSearchProps<Enduser>, 'filterKe
885
886
  if (((session.userInfo as any)?.access as AccessPermissions)?.users?.read === ALL_ACCESS && !value_is_loaded(usersLoading)) return null
886
887
  return (
887
888
  <ModelSearchInput filterKey="endusers" {...props}
888
- searchAPI={session.api.endusers.getSome}
889
+ searchAPI={async ({ search }) => {
890
+ // handle case of formatted phone number in search bar by parsing to standard phone format and searching explicitly by phone
891
+ // in this case, also search by generic search term in case user is intending to search by something else (e.g. externalId)
892
+ try {
893
+ const phone = phoneValidator.validate()(search.query)
894
+ if (phone) {
895
+ return (
896
+ await Promise.all([
897
+ session.api.endusers.getSome({ filter: { phone }}),
898
+ session.api.endusers.getSome({ search }),
899
+ ])
900
+ ).flatMap(v => v)
901
+ }
902
+ } catch(err) {}
903
+ return session.api.endusers.getSome({ search })
904
+ }}
889
905
  onLoad={addLocalElements}
890
906
  attachSearchableFields={t => {
891
907
  const users = t.assignedTo?.map(userId => findUser(userId, { batch: true })).filter(u => u) as User[]
package/src/layout.tsx CHANGED
@@ -41,9 +41,10 @@ export interface ImageProps extends ImageDimensions, Styled {
41
41
  src: string,
42
42
  alt?: string,
43
43
  onClick?: () => void,
44
+ crossOrigin?: 'anonymous' | 'use-credentials',
44
45
  }
45
- export const Image = ({ src, alt, style, onClick, ...props }: ImageProps) => (
46
- <img src={src} alt={alt} onClick={onClick} style={{ cursor: !!onClick ? 'pointer' : undefined, ...props, ...style }} />
46
+ export const Image = ({ src, alt, style, onClick, crossOrigin, ...props }: ImageProps) => (
47
+ <img crossOrigin={crossOrigin} src={src} alt={alt} onClick={onClick} style={{ cursor: !!onClick ? 'pointer' : undefined, ...props, ...style }} />
47
48
  )
48
49
 
49
50
  export interface VideoProps extends Styled {
package/src/state.tsx CHANGED
@@ -99,6 +99,7 @@ import {
99
99
  EnduserEligibilityResult,
100
100
  AgentRecord,
101
101
  Waitlist,
102
+ AIConversation,
102
103
  } from "@tellescope/types-client"
103
104
 
104
105
  import {
@@ -366,6 +367,7 @@ const integrationLogsSlice = createSliceForList<IntegrationLog, 'integration_log
366
367
  const enduserEligibilityResultsSlice = createSliceForList<EnduserEligibilityResult, 'enduser_eligibility_results'>('enduser_eligibility_results')
367
368
  const agentRecordsSlice = createSliceForList<AgentRecord, 'agent_records'>('agent_records')
368
369
  const waitlistsSlice = createSliceForList<Waitlist, 'waitlists'>('waitlists')
370
+ const aiConversationsSlice = createSliceForList<AIConversation, 'ai_conversations'>('ai_conversations')
369
371
 
370
372
  const roleBasedAccessPermissionsSlice = createSliceForList<RoleBasedAccessPermission, 'role_based_access_permissions'>('role_based_access_permissions')
371
373
 
@@ -374,6 +376,7 @@ const userLogsSlice = createSliceForList<UserLog, 'user_logs'>('user_logs')
374
376
 
375
377
  export const sharedConfig = {
376
378
  reducer: {
379
+ ai_conversations: aiConversationsSlice.reducer,
377
380
  agent_records: agentRecordsSlice.reducer,
378
381
  enduser_eligibility_results: enduserEligibilityResultsSlice.reducer,
379
382
  integration_logs: integrationLogsSlice.reducer,
@@ -1312,6 +1315,25 @@ export const useEnduserEligibilityResults = (options={} as HookOptions<EnduserEl
1312
1315
  )
1313
1316
  }
1314
1317
 
1318
+ export const useAIConversations = (options={} as HookOptions<AIConversation>) => {
1319
+ const session = useSession()
1320
+
1321
+ return useListStateHook('ai_conversations', useTypedSelector(s => s.ai_conversations), session, aiConversationsSlice,
1322
+ {
1323
+ loadQuery: session.api.ai_conversations.getSome,
1324
+ findOne: session.api.ai_conversations.getOne,
1325
+ findByIds: session.api.ai_conversations.getByIds,
1326
+ addOne: session.api.ai_conversations.createOne,
1327
+ addSome: session.api.ai_conversations.createSome,
1328
+ deleteOne: session.api.ai_conversations.deleteOne,
1329
+ updateOne: session.api.ai_conversations.updateOne,
1330
+ },
1331
+ {
1332
+ ...options,
1333
+ },
1334
+ )
1335
+ }
1336
+
1315
1337
  export const useAgentRecords = (options={} as HookOptions<AgentRecord>) => {
1316
1338
  const session = useSession()
1317
1339