@engagebay/engagebay-form-module 1.0.0-beta.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 (50) hide show
  1. package/README.md +126 -0
  2. package/link.sh +2 -0
  3. package/package.json +30 -0
  4. package/src/api/index.ts +25 -0
  5. package/src/form/Form.tsx +157 -0
  6. package/src/form/FormField.tsx +80 -0
  7. package/src/form/FormFieldUtils.ts +241 -0
  8. package/src/form/FormFields.tsx +41 -0
  9. package/src/form/context/FormContext.tsx +66 -0
  10. package/src/form/formfields/ArrayField.tsx +169 -0
  11. package/src/form/formfields/BusinessHoursField.tsx +204 -0
  12. package/src/form/formfields/CheckboxButtonsField.tsx +97 -0
  13. package/src/form/formfields/CheckboxField.tsx +118 -0
  14. package/src/form/formfields/ColorPickerField.tsx +59 -0
  15. package/src/form/formfields/ComboMultiSelect.tsx +290 -0
  16. package/src/form/formfields/ComboSelect.tsx +278 -0
  17. package/src/form/formfields/DatePickerField.tsx +89 -0
  18. package/src/form/formfields/DateRangePickerField.tsx +104 -0
  19. package/src/form/formfields/DynamicMultiSelect.tsx +189 -0
  20. package/src/form/formfields/DynamicSelect.tsx +187 -0
  21. package/src/form/formfields/Error.tsx +15 -0
  22. package/src/form/formfields/ErrorContextHandler.tsx +77 -0
  23. package/src/form/formfields/FileUploadField.tsx +196 -0
  24. package/src/form/formfields/IframeField.tsx +65 -0
  25. package/src/form/formfields/InputField.tsx +67 -0
  26. package/src/form/formfields/InputGroupField.tsx +44 -0
  27. package/src/form/formfields/MultipleSelectField.tsx +98 -0
  28. package/src/form/formfields/NumberField.tsx +61 -0
  29. package/src/form/formfields/PasswordField.tsx +93 -0
  30. package/src/form/formfields/PhoneNumberField.tsx +163 -0
  31. package/src/form/formfields/RadioField.tsx +104 -0
  32. package/src/form/formfields/RadioGroupComponent.tsx +94 -0
  33. package/src/form/formfields/RangeField.tsx +53 -0
  34. package/src/form/formfields/SelectField.tsx +82 -0
  35. package/src/form/formfields/SwitchField.tsx +131 -0
  36. package/src/form/formfields/TextAreaField.tsx +48 -0
  37. package/src/form/formfields/TimeField.tsx +53 -0
  38. package/src/form/formfields/Typeahead.tsx +211 -0
  39. package/src/form/formfields/TypeaheadMultiSelect.tsx +203 -0
  40. package/src/form/formfields/UrlField.tsx +53 -0
  41. package/src/form/hooks/useDynamicReducer.tsx +42 -0
  42. package/src/form/schema/CustomValidators.ts +63 -0
  43. package/src/form/schema/FormFieldSchema.ts +342 -0
  44. package/src/form/util/RenderFormField.tsx +149 -0
  45. package/src/form/util/RenderListOptions.tsx +424 -0
  46. package/src/form/util/index.ts +185 -0
  47. package/src/util/LoaderWithText.tsx +28 -0
  48. package/src/util/svg/HELPER_ICONS.ts +16 -0
  49. package/src/util/svg/SVGIcon.tsx +23 -0
  50. package/tsconfig.json +25 -0
@@ -0,0 +1,278 @@
1
+ // import {Combobox, Transition} from '@headlessui/react';
2
+ // import {CheckIcon, ChevronDownIcon} from '@heroicons/react/20/solid';
3
+ // import React, {Fragment, useContext, useEffect, useState} from 'react';
4
+ // import {RegisterOptions} from 'react-hook-form';
5
+ // import {reachoAPI} from '../../../../api';
6
+ // import {getListOptions} from '../FormFieldUtils';
7
+ // import {FormContext} from '../context/FormContext';
8
+ // import {
9
+ // FieldAlignType,
10
+ // FieldOptionsSchema,
11
+ // FormFieldComponentPropSchema,
12
+ // FormFieldPatternsImpl
13
+ // } from '../schema/FormFieldSchema';
14
+ // import ErrorContextHandler from './ErrorContextHandler';
15
+ // import {PlusIcon} from '@heroicons/react/16/solid';
16
+ // import {usePopper} from 'react-popper';
17
+ // import {CancelTokenSource} from 'axios';
18
+
19
+ import React from "react";
20
+ import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
21
+
22
+ const ComboSelect: React.FC<FormFieldComponentPropSchema> = (
23
+ props: FormFieldComponentPropSchema
24
+ ) => {
25
+ // const formContext = useContext(FormContext);
26
+
27
+ // const [selectedOption, setSelectedOption] = useState<string>(formContext.getValues(props.fieldConfig.name) ? formContext.getValues(props.fieldConfig.name) : '');
28
+ // const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
29
+ // const [loading, setLoading] = useState<boolean>(false);
30
+ // const [query, setQuery] = useState<string>('');
31
+ // const [cancelToken, setCancelToken] = useState<CancelTokenSource | undefined>(undefined);
32
+
33
+ // let [referenceElement, setReferenceElement] = useState<any>();
34
+ // let [popperElement, setPopperElement] = useState<any>();
35
+ // let {styles, attributes} = usePopper(referenceElement, popperElement, {
36
+ // placement: 'auto-start',
37
+ // });
38
+
39
+ // if (props.fieldConfig.fetchUrl) {
40
+ // useEffect(() => {
41
+ // fetchData();
42
+ // }, []);
43
+ // } else if (props.fieldConfig.options && props.fieldConfig.options?.length > 0) {
44
+ // setListOptions(props.fieldConfig.options);
45
+ // }
46
+
47
+ // const fetchData = async () => {
48
+ // try {
49
+ // if (!props.fieldConfig.fetchUrl) return;
50
+
51
+ // let response = await reachoAPI.get(props.fieldConfig.fetchUrl);
52
+ // if (response.data) {
53
+ // const data: FieldOptionsSchema[] = getListOptions(response.data, props.fieldConfig.optionsConfig);
54
+ // setListOptions([...data]);
55
+ // }
56
+ // } catch (err) {
57
+ // } finally {
58
+ // setLoading(false);
59
+ // }
60
+ // };
61
+
62
+ // const createItem = async () => {
63
+ // setLoading(true);
64
+ // try {
65
+ // if (!props.fieldConfig.postUrl) {
66
+ // const data: FieldOptionsSchema = {
67
+ // label: query,
68
+ // value: query,
69
+ // };
70
+ // setListOptions([...listOptions, data]);
71
+ // handleSelect(query);
72
+ // return;
73
+ // }
74
+ // // const data = {
75
+ // // value: query,
76
+ // // };
77
+
78
+ // // let url: string = props.fieldConfig.postUrl;
79
+
80
+ // // let response = await reachoAPI.post(url, data);
81
+ // // if (response.data) {
82
+ // // const newItem: FieldOptionsSchema = props.fieldConfig.optionsConfig
83
+ // // ? {
84
+ // // label: response.data[props.fieldConfig.optionsConfig.label],
85
+ // // value: response.data[props.fieldConfig.optionsConfig.value],
86
+ // // }
87
+ // // : {
88
+ // // value: response.data.id,
89
+ // // label: response.data.value,
90
+ // // };
91
+
92
+ // // setListOptions([...listOptions, newItem]);
93
+
94
+ // // handleSelect(newItem.value);
95
+ // // }
96
+ // } catch (e: any) {
97
+ // console.error('Error in Creating the object ', e);
98
+ // } finally {
99
+ // setQuery('');
100
+ // setLoading(false);
101
+ // }
102
+ // };
103
+
104
+ // const getSelectedOption = () => {
105
+ // let value: string | undefined = formContext.getValues(props.fieldConfig.name) + '';
106
+ // if (value == '' || value === undefined) {
107
+ // value = props.fieldConfig.defaultValue ? props.fieldConfig.defaultValue : undefined;
108
+ // }
109
+ // return listOptions.find((option) => option.value == value)?.label as string;
110
+ // };
111
+ // const handleSelect = (option: string) => {
112
+ // formContext.setValue(props.fieldConfig.name, option, {
113
+ // shouldValidate: true,
114
+ // shouldDirty: formContext.getFieldState(props.fieldConfig.name).isDirty,
115
+ // shouldTouch: formContext.getFieldState(props.fieldConfig.name).isTouched,
116
+ // });
117
+
118
+ // if (props.onChange) props.onChange(option);
119
+ // };
120
+
121
+ // let registerOptions: RegisterOptions = {required: props.fieldConfig.required ? FormFieldPatternsImpl.REQUIRED.getMessage() : false};
122
+ // if (props.fieldConfig?.formFieldPattern) {
123
+ // registerOptions.pattern = props.fieldConfig?.formFieldPattern[0].getPattern();
124
+ // }
125
+ // formContext.register(props.fieldConfig.name, registerOptions);
126
+
127
+ // const filteredPeople = query && query != '' ? listOptions.filter((item) => item.label.toLowerCase().replace(/\s+/g, '').includes(query.toLowerCase().replace(/\s+/g, ''))) : listOptions;
128
+
129
+ // function getInput() {
130
+ // return (
131
+ // <Combobox
132
+ // value={formContext.getValues(props.fieldConfig.name) == '' ? undefined : formContext.getValues(props.fieldConfig.name)}
133
+ // name={props.fieldConfig.name}
134
+ // defaultValue={props.fieldConfig.defaultValue}
135
+ // >
136
+ // <div className="relative form-combobox flex-1" ref={setReferenceElement}>
137
+ // <Combobox.Button
138
+ // className={props.fieldConfig.customClassName ? 'form-combobox-select ' + props.fieldConfig.customClassName : 'form-combobox-select w-full justify-between'}>
139
+ // <Combobox.Input className="form-input" displayValue={() => getSelectedOption()}
140
+ // onChange={(event) => setQuery(event.target.value)}/>
141
+ // <ChevronDownIcon className="h-5 w-5 text-gray-400 form-combobox-svg" aria-hidden="true"/>
142
+ // </Combobox.Button>
143
+ // <Transition as={Fragment} leave="transition ease-in duration-100" leaveFrom="opacity-100"
144
+ // leaveTo="opacity-0" afterLeave={() => setQuery('')}>
145
+ // <Combobox.Options ref={setPopperElement} style={styles.popper} {...attributes.popper}
146
+ // className="form-combobox-options">
147
+ // {filteredPeople.length === 0 && query !== ''
148
+ // ? props.fieldConfig.enableCreateOption && (
149
+ // <Combobox.Option
150
+ // key={'create_new'}
151
+ // className={({active}) => `form-combobox-option ${active ? 'bg-[#f6f6f6] text-primary' : 'text-gray-900'}`}
152
+ // value={'create'}
153
+ // onClick={() => createItem()}
154
+ // >
155
+ // {({selected}) => (
156
+ // <>
157
+ // <div className="flex items-center justify-between">
158
+ // <span>{query}</span>
159
+ // <span className="text-success flex items-center gap-x-1">
160
+ // <PlusIcon className="h-3 w-3"/>
161
+ // Create & select
162
+ // </span>
163
+ // </div>
164
+ // </>
165
+ // )}
166
+ // </Combobox.Option>
167
+ // )
168
+ // : filteredPeople.length == 0 ? <Combobox.Option
169
+ // key={"no-list-options"}
170
+ // disabled={true}
171
+ // className={({active}) => `form-combobox-option ${active ? 'bg-[#f6f6f6] text-primary' : 'text-gray-900'}`}
172
+ // value={null}
173
+ // >
174
+ // {({selected, active}) => (
175
+ // <>
176
+ // <span
177
+ // className={`block truncate ${selected ? 'font-medium' : 'font-normal'}`}>No Data </span>
178
+ // </>
179
+ // )}
180
+ // </Combobox.Option>
181
+ // : filteredPeople.map((option) => (
182
+ // <Combobox.Option
183
+ // key={option.value}
184
+ // onClick={() => handleSelect(option.value)}
185
+ // disabled={option.isDisabled}
186
+ // className={({active}) => `form-combobox-option ${active ? 'bg-[#f6f6f6] text-primary' : 'text-gray-900'}`}
187
+ // value={option.value}
188
+ // >
189
+ // {({selected, active}) => (
190
+ // <>
191
+ // <span
192
+ // className={`block truncate ${selected ? 'font-medium' : 'font-normal'}`}>{option.label}</span>
193
+ // {selected ? (
194
+ // <span className="icon">
195
+ // <CheckIcon className="h-5 w-5" aria-hidden="true"/>
196
+ // </span>
197
+ // ) : null}
198
+ // <p className="form-listbox-helptext">{option.helpText}</p>
199
+ // </>
200
+ // )}
201
+ // </Combobox.Option>
202
+ // ))}
203
+ // </Combobox.Options>
204
+ // </Transition>
205
+ // </div>
206
+ // </Combobox>
207
+ // );
208
+ // }
209
+
210
+ // function formTypeHorizontal() {
211
+ // return (
212
+ // <div className="form-group flex sm:flex-row flex-col">
213
+ // {props.fieldConfig.label ? (
214
+ // <label htmlFor="email" className="form-label sm:w-1/4 sm:ltr:mr-2 rtl:ml-2">
215
+ // {props.fieldConfig.label}
216
+ // </label>
217
+ // ) : (
218
+ // <></>
219
+ // )}
220
+ // <div className="flex-1">
221
+ // {getInput()}
222
+
223
+ // <ErrorContextHandler fieldConfig={props.fieldConfig}/>
224
+
225
+ // {props.fieldConfig && props.fieldConfig.helpText ? (
226
+ // <p className="mt-2 text-sm text-gray-500" id="email-description">
227
+ // {props.fieldConfig.helpText}
228
+ // </p>
229
+ // ) : (
230
+ // <></>
231
+ // )}
232
+ // </div>
233
+ // </div>
234
+ // );
235
+ // }
236
+
237
+ // function formTypeVertical() {
238
+ // return (
239
+ // <div className="form-group">
240
+ // {props.fieldConfig.label ? (
241
+ // <label htmlFor="email" className="form-label">
242
+ // {props.fieldConfig.label}
243
+ // </label>
244
+ // ) : (
245
+ // <></>
246
+ // )}
247
+
248
+ // <div className="flex-1">
249
+ // {getInput()}
250
+
251
+ // <ErrorContextHandler fieldConfig={props.fieldConfig}/>
252
+
253
+ // {props.fieldConfig && props.fieldConfig.helpText ? (
254
+ // <p className="mt-2 text-sm text-gray-500" id="email-description">
255
+ // {props.fieldConfig.helpText}
256
+ // </p>
257
+ // ) : (
258
+ // <></>
259
+ // )}
260
+ // </div>
261
+ // </div>
262
+ // );
263
+ // }
264
+
265
+ // return (
266
+ // <>
267
+ // {props.fieldConfig && props.fieldConfig.disableDefaultWrapper ? (
268
+ // <>{getInput()}</>
269
+ // ) : (
270
+ // <>{props.fieldConfig.align === FieldAlignType.HORIZONTAL ? <>{formTypeHorizontal()}</> : <>{formTypeVertical()}</>}</>
271
+ // )}
272
+ // </>
273
+ // );
274
+
275
+ return <></>;
276
+ };
277
+
278
+ export default ComboSelect;
@@ -0,0 +1,89 @@
1
+ import { RegisterOptions } from "react-hook-form";
2
+ import React, { useContext, useEffect, useRef, useState } from "react";
3
+ import Datepicker from "react-tailwindcss-datepicker";
4
+ import { FormContext } from "../context/FormContext";
5
+ import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
6
+ import RenderFormField from "../util/RenderFormField";
7
+ import { handleChange, registerFormField } from "../util";
8
+ import moment from "moment";
9
+
10
+ const DatePicker: React.FC<FormFieldComponentPropSchema> = (
11
+ props: FormFieldComponentPropSchema
12
+ ) => {
13
+ const formContext = useContext(FormContext);
14
+ const initialDate = formContext.getValues(props.fieldConfig.name)
15
+ ? {
16
+ startDate: formContext.getValues(props.fieldConfig.name),
17
+ endDate: formContext.getValues(props.fieldConfig.name),
18
+ }
19
+ : { startDate: "", endDate: "" };
20
+
21
+ useEffect(() => {
22
+ if (
23
+ props.fieldConfig.defaultValue &&
24
+ !formContext.getValues(props.fieldConfig.name)
25
+ ) {
26
+ formContext.setValue(
27
+ props.fieldConfig.name,
28
+ props.fieldConfig.defaultValue
29
+ );
30
+ }
31
+ }, [props.fieldConfig.forceUpdate]);
32
+
33
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
34
+
35
+ let hookProps = formContext.register(
36
+ props.fieldConfig.name,
37
+ registerOptions
38
+ );
39
+
40
+ function getInput() {
41
+ return (
42
+ <Datepicker
43
+ value={
44
+ initialDate || {
45
+ startDate: props.fieldConfig.defaultValue,
46
+ endDate: props.fieldConfig.defaultValue,
47
+ }
48
+ }
49
+ {...hookProps}
50
+ placeholder={
51
+ props.fieldConfig.placeholder
52
+ ? props.fieldConfig.placeholder
53
+ : "YYYY-MM-DD"
54
+ }
55
+ asSingle={true}
56
+ popoverDirection="down"
57
+ useRange={false}
58
+ inputName={props.fieldConfig.name}
59
+ key={props.fieldConfig.name}
60
+ containerClassName={"relative"}
61
+ minDate={props.fieldConfig.minDate}
62
+ maxDate={props.fieldConfig.maxDate}
63
+ inputClassName={
64
+ props.fieldConfig.customClassNames?.fieldClassName
65
+ ? "form-input " +
66
+ props.fieldConfig.customClassNames.fieldClassName
67
+ : "form-input flex-1"
68
+ }
69
+ onChange={(dates) => {
70
+ let date = null;
71
+ if (dates?.startDate != null)
72
+ date = moment(dates?.startDate).format("YYYY-MM-DD");
73
+
74
+ handleChange(
75
+ date,
76
+ formContext,
77
+ props.fieldConfig,
78
+ props.onChange
79
+ );
80
+ }}
81
+ />
82
+ );
83
+ }
84
+ return (
85
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
86
+ );
87
+ };
88
+
89
+ export default DatePicker;
@@ -0,0 +1,104 @@
1
+ import { RegisterOptions } from "react-hook-form";
2
+ import { useContext, useEffect, useState } from "react";
3
+ import Datepicker, { DateValueType } from "react-tailwindcss-datepicker";
4
+ import { FormContext } from "../context/FormContext";
5
+ import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
6
+ import React from "react";
7
+ import RenderFormField from "../util/RenderFormField";
8
+ import { handleChange, registerFormField } from "../util";
9
+ import moment from "moment";
10
+
11
+ /**
12
+ *
13
+ * reference: https://react-tailwindcss-datepicker.vercel.app/
14
+ *
15
+ * @param props FormFieldComponentPropSchema
16
+ * @returns
17
+ */
18
+
19
+ const DateRangePicker: React.FC<FormFieldComponentPropSchema> = (
20
+ props: FormFieldComponentPropSchema
21
+ ) => {
22
+ const formContext = useContext(FormContext);
23
+
24
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
25
+
26
+ let hookProps = formContext.register(
27
+ props.fieldConfig.name,
28
+ registerOptions
29
+ );
30
+
31
+ const [date, setDate] = useState<DateValueType>(
32
+ formContext.getValues(props.fieldConfig.name)
33
+ ? {
34
+ startDate: formContext.getValues(props.fieldConfig.name),
35
+ endDate: formContext.getValues(props.fieldConfig.name),
36
+ }
37
+ : { startDate: "", endDate: "" }
38
+ );
39
+ useEffect(() => {
40
+ if (
41
+ props.fieldConfig.defaultValue &&
42
+ !formContext.getValues(props.fieldConfig.name)
43
+ ) {
44
+ const date = {
45
+ start: props.fieldConfig.defaultValue,
46
+ end: props.fieldConfig.defaultValue,
47
+ };
48
+ formContext.setValue(props.fieldConfig.name, date);
49
+ }
50
+ }, []);
51
+
52
+ function getInput() {
53
+ return (
54
+ <Datepicker
55
+ {...hookProps}
56
+ placeholder={
57
+ props.fieldConfig.placeholder
58
+ ? props.fieldConfig.placeholder
59
+ : "YYYY-MM-DD to YYYY-MM-DD"
60
+ }
61
+ inputName={props.fieldConfig.name}
62
+ key={props.fieldConfig.name}
63
+ value={date}
64
+ separator={"to"}
65
+ showFooter={true}
66
+ popoverDirection="down"
67
+ readOnly={props.fieldConfig.readOnly}
68
+ showShortcuts={true}
69
+ containerClassName={"relative"}
70
+ minDate={props.fieldConfig.minDate}
71
+ maxDate={props.fieldConfig.maxDate}
72
+ inputClassName={
73
+ props.fieldConfig.customClassNames?.fieldClassName
74
+ ? "form-input " +
75
+ props.fieldConfig.customClassNames.fieldClassName
76
+ : "form-input flex-1"
77
+ }
78
+ onChange={(dates) => {
79
+ let dateObject = null;
80
+ if (dates?.startDate && dates?.endDate) {
81
+ dateObject = {
82
+ start: moment(dates?.startDate).format(
83
+ "YYYY-MM-DD"
84
+ ),
85
+ end: moment(dates?.endDate).format("YYYY-MM-DD"),
86
+ };
87
+ }
88
+ setDate(dates);
89
+ handleChange(
90
+ dateObject,
91
+ formContext,
92
+ props.fieldConfig,
93
+ props.onChange
94
+ );
95
+ }}
96
+ />
97
+ );
98
+ }
99
+ return (
100
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
101
+ );
102
+ };
103
+
104
+ export default DateRangePicker;
@@ -0,0 +1,189 @@
1
+ import React, {useContext, useEffect, useRef, useState} from "react";
2
+ import {
3
+ FieldOptionsSchema,
4
+ FormFieldComponentPropSchema,
5
+ FormFieldType,
6
+ StoreStateSchema,
7
+ } from "../schema/FormFieldSchema";
8
+ import {RegisterOptions} from "react-hook-form";
9
+ import {Listbox, ListboxButton} from "@headlessui/react";
10
+
11
+ import {FormContext} from "../context/FormContext";
12
+ import {getListOptions} from "../FormFieldUtils";
13
+ import axios from "axios";
14
+ import useDymanicReducer from "../hooks/useDynamicReducer";
15
+ import {useDispatch} from "react-redux";
16
+ import RenderFormField from "../util/RenderFormField";
17
+ import {handleChange, registerFormField} from "../util";
18
+ import RenderListOptions, {renderListBoxValue,} from "../util/RenderListOptions";
19
+ import {reachoAPI} from "../../api";
20
+
21
+ const DynamicMultiSelect: React.FC<FormFieldComponentPropSchema> = (
22
+ props: FormFieldComponentPropSchema
23
+ ) => {
24
+ const dynamicSelectRef = useRef<HTMLUListElement>(null);
25
+
26
+ const formContext = useContext(FormContext);
27
+
28
+ const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
29
+ const [loading, setLoading] = useState<boolean>(false);
30
+
31
+ useEffect(() => {
32
+ const {fieldConfig} = props;
33
+
34
+ // Initialize dropdownFieldConfig with defaults if not already set
35
+ fieldConfig.dropdownFieldConfig = {
36
+ showCreateOption:
37
+ fieldConfig.dropdownFieldConfig?.showCreateOption ?? false,
38
+ showDeleteOption:
39
+ fieldConfig.dropdownFieldConfig?.showDeleteOption ?? true,
40
+ showSearchBox:
41
+ fieldConfig.dropdownFieldConfig?.showSearchBox ?? true,
42
+ showSelectedCount:
43
+ fieldConfig.dropdownFieldConfig?.showSelectedCount ?? true,
44
+ };
45
+
46
+ if (
47
+ !formContext.getValues(props.fieldConfig.name) &&
48
+ props.fieldConfig.defaultValue
49
+ ) {
50
+ formContext.setValue(
51
+ props.fieldConfig.name,
52
+ props.fieldConfig.defaultValue
53
+ );
54
+ }
55
+ }, []);
56
+
57
+ if (props.fieldConfig.store) {
58
+ const {state: state} = useDymanicReducer<StoreStateSchema<any>>({
59
+ reducerConfig: props.fieldConfig.store,
60
+ });
61
+
62
+ const dispatch = useDispatch();
63
+
64
+ useEffect(() => {
65
+ if (
66
+ props.fieldConfig.store?.initialFetchReducerAction &&
67
+ (!state || !state.data)
68
+ ) {
69
+ dispatch(props.fieldConfig.store.initialFetchReducerAction(""));
70
+ } else {
71
+ if (state && state.data && Array.isArray(state.data)) {
72
+ const list: FieldOptionsSchema[] = getListOptions(
73
+ state.data,
74
+ props.fieldConfig.optionsConfig
75
+ );
76
+ setListOptions([...list]);
77
+ setLoading(false);
78
+ }
79
+ }
80
+ }, []);
81
+
82
+ useEffect(() => {
83
+ if (state && state.data && Array.isArray(state.data)) {
84
+ const list = getListOptions(
85
+ state.data,
86
+ props.fieldConfig.optionsConfig
87
+ );
88
+ setListOptions([...list]);
89
+ setLoading(false);
90
+ }
91
+ }, [state]);
92
+ } else if (props.fieldConfig.fetchUrl) {
93
+ useEffect(() => {
94
+ fetchData();
95
+ }, []);
96
+ }
97
+ if (props.fieldConfig.options && props.fieldConfig.options.length > 0) {
98
+ let options = props.fieldConfig.options;
99
+ setListOptions(prevState => [...options, ...prevState]);
100
+ }
101
+ const fetchData = async () => {
102
+ if (!props.fieldConfig.fetchUrl) return;
103
+
104
+ let response = await (props.fieldConfig.disableHeaderInFetch
105
+ ? axios.get(props.fieldConfig.fetchUrl)
106
+ : reachoAPI.get(props.fieldConfig.fetchUrl));
107
+ if (response.data) {
108
+ const data: FieldOptionsSchema[] = getListOptions(
109
+ response.data,
110
+ props.fieldConfig.optionsConfig
111
+ );
112
+ setListOptions([...data]);
113
+ if (props.fieldConfig.fetchCallback) {
114
+ props.fieldConfig.fetchCallback(response);
115
+ }
116
+ } else {
117
+ console.error(response.statusText);
118
+ setLoading(false);
119
+ }
120
+ };
121
+
122
+ let registerOptions: RegisterOptions = registerFormField(
123
+ props.fieldConfig,
124
+ true
125
+ );
126
+
127
+ let hookProps = formContext.register(
128
+ props.fieldConfig.name,
129
+ registerOptions
130
+ );
131
+
132
+ function getInput() {
133
+ return (
134
+ <Listbox
135
+ multiple
136
+ as={"div"}
137
+ value={formContext.getValues(props.fieldConfig.name) ?? []}
138
+ {...hookProps}
139
+ onChange={(selectedOptions) =>
140
+ handleChange(
141
+ selectedOptions,
142
+ formContext,
143
+ props.fieldConfig,
144
+ props.onChange
145
+ )
146
+ }
147
+ defaultValue={props.fieldConfig.defaultValue}
148
+ name={props.fieldConfig.name}
149
+ disabled={props.fieldConfig.disabled}
150
+ className={`relative form-listbox flex-1`}>
151
+ <ListboxButton
152
+ className={
153
+ props.fieldConfig.customClassNames?.fieldClassName
154
+ ? "form-listbox-select " +
155
+ props.fieldConfig.customClassNames.fieldClassName
156
+ : "form-listbox-select"
157
+ }>
158
+ {renderListBoxValue(
159
+ formContext,
160
+ props.fieldConfig,
161
+ listOptions,
162
+ props.onChange
163
+ )
164
+ }
165
+ </ListboxButton>
166
+ <RenderListOptions
167
+ formContext={formContext}
168
+ onChange={props.onChange}
169
+ formField={FormFieldType.DYNAMIC_MULTI_SELECT}
170
+ ref={dynamicSelectRef}
171
+ fieldConfig={props.fieldConfig}
172
+ listOptions={listOptions}
173
+ setListOptions={setListOptions}
174
+ loading={loading}
175
+ setLoading={setLoading}
176
+ />
177
+ </Listbox>
178
+ );
179
+ }
180
+ if(props.fieldConfig.hideWhenNoResults && listOptions.length==0 )
181
+ {
182
+ return <></>
183
+ }
184
+
185
+ return (
186
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput}/>
187
+ );
188
+ };
189
+ export default DynamicMultiSelect;