@engagebay/engagebay-form-module 1.0.1 → 1.0.2-beta.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.
- package/link.sh +1 -1
- package/package.json +17 -1
- package/src/api/AxiosConfigProvider.tsx +53 -0
- package/src/api/index.ts +15 -1
- package/src/form/Form.tsx +6 -0
- package/src/form/context/FormContext.tsx +2 -0
- package/src/form/formfields/BusinessHoursField.tsx +293 -181
- package/src/form/formfields/ColorPickerField.tsx +43 -42
- package/src/form/formfields/DatePickerField.tsx +66 -69
- package/src/form/formfields/DynamicMultiSelect.tsx +166 -166
- package/src/form/formfields/DynamicSelect.tsx +4 -5
- package/src/form/formfields/MultipleSelectField.tsx +70 -74
- package/src/form/formfields/RadioField.tsx +73 -86
- package/src/form/formfields/Typeahead.tsx +6 -7
- package/src/form/formfields/TypeaheadMultiSelect.tsx +189 -175
- package/src/form/schema/FormFieldSchema.ts +17 -0
- package/src/form/util/RenderFormField.tsx +2 -0
- package/src/form/util/RenderListOptions.tsx +46 -34
- package/src/index.js +116 -0
- package/src/util/svg/HELPER_ICONS.ts +1 -0
package/link.sh
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
sudo npm link
|
|
1
|
+
sudo npm link /home/eb137/IdeaProjects/engagebay-frontend/node_modules/react
|
|
2
2
|
npm link
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@engagebay/engagebay-form-module",
|
|
3
|
-
"version": "1.0.1",
|
|
3
|
+
"version": "1.0.2-beta.1",
|
|
4
4
|
"description": "Provide base form components to reacho",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -26,5 +26,21 @@
|
|
|
26
26
|
"react-redux": ">=8.0.4",
|
|
27
27
|
"react-tailwindcss-datepicker": ">=1.6.6",
|
|
28
28
|
"redux-saga": ">=1.3.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@headlessui/react": ">=2.1.2",
|
|
32
|
+
"@heroicons/react": ">=2.1.5",
|
|
33
|
+
"@reduxjs/toolkit": ">=2.2.7",
|
|
34
|
+
"@tippyjs/react": ">=4.2.6",
|
|
35
|
+
"@types/lodash": ">=4.17.7",
|
|
36
|
+
"@types/react-redux": ">=7.1.33",
|
|
37
|
+
"axios": ">=1.7.2",
|
|
38
|
+
"clsx": ">=2.1.1",
|
|
39
|
+
"moment": ">=2.30.1",
|
|
40
|
+
"react-hook-form": ">=7.52.1",
|
|
41
|
+
"react-popper": ">=2.3.0",
|
|
42
|
+
"react-redux": ">=8.0.4",
|
|
43
|
+
"react-tailwindcss-datepicker": ">=1.6.6",
|
|
44
|
+
"redux-saga": ">=1.3.0"
|
|
29
45
|
}
|
|
30
46
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React, { createContext, useContext, ReactNode } from 'react';
|
|
2
|
+
import { AxiosInstance } from 'axios';
|
|
3
|
+
|
|
4
|
+
interface AxiosConfigContextType {
|
|
5
|
+
axiosInstance: AxiosInstance;
|
|
6
|
+
baseURL?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const AxiosConfigContext = createContext<AxiosConfigContextType | null>(null);
|
|
12
|
+
|
|
13
|
+
interface AxiosConfigProviderProps {
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
axiosInstance: AxiosInstance;
|
|
16
|
+
baseURL?: string;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const AxiosConfigProvider: React.FC<AxiosConfigProviderProps> = ({
|
|
22
|
+
children,
|
|
23
|
+
axiosInstance,
|
|
24
|
+
baseURL,
|
|
25
|
+
timeout,
|
|
26
|
+
headers,
|
|
27
|
+
}) => {
|
|
28
|
+
const config: AxiosConfigContextType = {
|
|
29
|
+
axiosInstance,
|
|
30
|
+
baseURL,
|
|
31
|
+
timeout,
|
|
32
|
+
headers,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<AxiosConfigContext.Provider value={config}>
|
|
37
|
+
{children}
|
|
38
|
+
</AxiosConfigContext.Provider>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const useAxiosConfig = (): AxiosConfigContextType => {
|
|
43
|
+
const context = useContext(AxiosConfigContext);
|
|
44
|
+
if (!context) {
|
|
45
|
+
throw new Error('useAxiosConfig must be used within an AxiosConfigProvider');
|
|
46
|
+
}
|
|
47
|
+
return context;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Hook for optional usage (doesn't throw error if not provided)
|
|
51
|
+
export const useAxiosConfigOptional = (): AxiosConfigContextType | null => {
|
|
52
|
+
return useContext(AxiosConfigContext);
|
|
53
|
+
};
|
package/src/api/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import axios, { AxiosRequestConfig
|
|
1
|
+
import axios, {AxiosInstance, AxiosRequestConfig} from "axios";
|
|
2
|
+
import {FormFieldSchema} from "../form/schema/FormFieldSchema";
|
|
2
3
|
|
|
3
4
|
const BASE_API: AxiosRequestConfig = {
|
|
4
5
|
baseURL:
|
|
@@ -23,3 +24,16 @@ reachoAPI.interceptors.request.use(
|
|
|
23
24
|
return Promise.reject(error);
|
|
24
25
|
}
|
|
25
26
|
);
|
|
27
|
+
|
|
28
|
+
export const getAxiosInstance = (axiosInstance: AxiosInstance | undefined, fieldConfig: FormFieldSchema): AxiosInstance => {
|
|
29
|
+
|
|
30
|
+
if (fieldConfig && fieldConfig.axiosInstance) {
|
|
31
|
+
return fieldConfig.axiosInstance;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (axiosInstance) {
|
|
35
|
+
return axiosInstance;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return fieldConfig.disableHeaderInFetch ? axios : reachoAPI;
|
|
39
|
+
};
|
package/src/form/Form.tsx
CHANGED
|
@@ -9,9 +9,11 @@ import {
|
|
|
9
9
|
UseFormTrigger,
|
|
10
10
|
UseFormUnregister,
|
|
11
11
|
UseFormResetField,
|
|
12
|
+
Control,
|
|
12
13
|
} from "react-hook-form";
|
|
13
14
|
import { FormFieldSchema } from "./schema/FormFieldSchema";
|
|
14
15
|
import { FormContext } from "./context/FormContext";
|
|
16
|
+
import { AxiosInstance } from 'axios';
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Props for the Form component
|
|
@@ -26,6 +28,7 @@ import { FormContext } from "./context/FormContext";
|
|
|
26
28
|
*/
|
|
27
29
|
type FormPropsSchema = {
|
|
28
30
|
fieldSchema: FormFieldSchema[];
|
|
31
|
+
axiosInstance?: AxiosInstance
|
|
29
32
|
formData: any;
|
|
30
33
|
onError?: (error: any) => void;
|
|
31
34
|
onSubmit?: (data: FormData) => void;
|
|
@@ -40,6 +43,7 @@ type FormPropsSchema = {
|
|
|
40
43
|
trigger: UseFormTrigger<any>;
|
|
41
44
|
unregister: UseFormUnregister<any>;
|
|
42
45
|
resetField: UseFormResetField<any>;
|
|
46
|
+
control: Control<any, any, any>;
|
|
43
47
|
}) => React.ReactNode;
|
|
44
48
|
customClass?: string;
|
|
45
49
|
};
|
|
@@ -132,6 +136,7 @@ export default function Form(props: FormPropsSchema): JSX.Element {
|
|
|
132
136
|
setError,
|
|
133
137
|
setFocus,
|
|
134
138
|
unregister,
|
|
139
|
+
axiosInstance: props.axiosInstance,
|
|
135
140
|
}}>
|
|
136
141
|
{/* Form element */}
|
|
137
142
|
<form
|
|
@@ -149,6 +154,7 @@ export default function Form(props: FormPropsSchema): JSX.Element {
|
|
|
149
154
|
trigger,
|
|
150
155
|
unregister,
|
|
151
156
|
resetField,
|
|
157
|
+
control,
|
|
152
158
|
})}
|
|
153
159
|
</form>
|
|
154
160
|
</FormContext.Provider>
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
UseFormWatch,
|
|
18
18
|
} from "react-hook-form";
|
|
19
19
|
import { FormFieldSchema } from "../schema/FormFieldSchema";
|
|
20
|
+
import { AxiosInstance } from "axios";
|
|
20
21
|
|
|
21
22
|
export interface FormContextType {
|
|
22
23
|
formFields: FormFieldSchema[];
|
|
@@ -43,6 +44,7 @@ export interface FormContextType {
|
|
|
43
44
|
// control: Control<TFieldValues, TContext>;
|
|
44
45
|
// register: UseFormRegister<TFieldValues>;
|
|
45
46
|
setFocus: UseFormSetFocus<any>;
|
|
47
|
+
axiosInstance?: AxiosInstance;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
export const FormContext = createContext({
|
|
@@ -1,204 +1,316 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
FieldAlignType,
|
|
3
|
+
FieldOptionsSchema,
|
|
4
|
+
FormFieldComponentPropSchema,
|
|
5
|
+
FormFieldSchema,
|
|
6
|
+
FormFieldType,
|
|
7
7
|
} from "../schema/FormFieldSchema";
|
|
8
|
-
import React, {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
import React, {
|
|
9
|
+
useCallback,
|
|
10
|
+
useContext,
|
|
11
|
+
useEffect,
|
|
12
|
+
useMemo,
|
|
13
|
+
useState,
|
|
14
|
+
} from "react";
|
|
15
|
+
import { FormContext } from "../context/FormContext";
|
|
16
|
+
import { RegisterOptions } from "react-hook-form";
|
|
17
|
+
import { convertToTitleCase, registerFormField } from "../util";
|
|
12
18
|
import axios from "axios";
|
|
13
|
-
import {reachoAPI} from "../../api";
|
|
14
19
|
import SwitchField from "./SwitchField";
|
|
15
20
|
import FormField from "../FormField";
|
|
16
21
|
import RenderFormField from "../util/RenderFormField";
|
|
17
|
-
import {TrashIcon, XMarkIcon} from "@heroicons/react/24/outline";
|
|
22
|
+
import { TrashIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
|
18
23
|
import Tippy from "@tippyjs/react";
|
|
24
|
+
import { set } from "lodash";
|
|
19
25
|
|
|
26
|
+
const defaultBusinessHours = {
|
|
27
|
+
MONDAY: {
|
|
28
|
+
enabledDay: true,
|
|
29
|
+
sessions: [
|
|
30
|
+
{
|
|
31
|
+
startTime: "10:00",
|
|
32
|
+
endTime: "18:00",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
TUESDAY: {
|
|
37
|
+
enabledDay: true,
|
|
38
|
+
sessions: [
|
|
39
|
+
{
|
|
40
|
+
startTime: "10:00",
|
|
41
|
+
endTime: "18:00",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
WEDNESDAY: {
|
|
46
|
+
enabledDay: true,
|
|
47
|
+
sessions: [
|
|
48
|
+
{
|
|
49
|
+
startTime: "10:00",
|
|
50
|
+
endTime: "18:00",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
THURSDAY: {
|
|
55
|
+
enabledDay: true,
|
|
56
|
+
sessions: [
|
|
57
|
+
{
|
|
58
|
+
startTime: "10:00",
|
|
59
|
+
endTime: "18:00",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
FRIDAY: {
|
|
64
|
+
enabledDay: true,
|
|
65
|
+
sessions: [
|
|
66
|
+
{
|
|
67
|
+
startTime: "10:00",
|
|
68
|
+
endTime: "18:00",
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
SATURDAY: {
|
|
73
|
+
enabledDay: false,
|
|
74
|
+
sessions: [
|
|
75
|
+
{
|
|
76
|
+
startTime: "10:00",
|
|
77
|
+
endTime: "18:00",
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
SUNDAY: {
|
|
82
|
+
enabledDay: false,
|
|
83
|
+
sessions: [
|
|
84
|
+
{
|
|
85
|
+
startTime: "10:00",
|
|
86
|
+
endTime: "18:00",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
};
|
|
20
91
|
|
|
21
|
-
export const BusinessHoursField: React.FC<FormFieldComponentPropSchema> = (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const hookProps = useMemo(() => formContext.register(props.fieldConfig.name, registerOptions), [formContext, props.fieldConfig.name, registerOptions]);
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
fetchData();
|
|
31
|
-
}, []);
|
|
92
|
+
export const BusinessHoursField: React.FC<FormFieldComponentPropSchema> = (
|
|
93
|
+
props: FormFieldComponentPropSchema
|
|
94
|
+
) => {
|
|
95
|
+
const formContext = useContext(FormContext);
|
|
96
|
+
const [listOptions, setListOptions] = useState<any>(defaultBusinessHours);
|
|
97
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
32
98
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return <div style={{border: '1px sold #ddd', padding: '0px'}}>{children}</div>;
|
|
39
|
-
},
|
|
40
|
-
arrayWrapper: ({children, append,getValues}) => {
|
|
41
|
-
return (
|
|
42
|
-
<>
|
|
43
|
-
<div style={{border: '1px sold #ddd',}}>
|
|
44
|
-
{children}
|
|
45
|
-
</div>
|
|
46
|
-
<div className='w-full sm:w-full text-end mr-[2.3em]'>
|
|
47
|
-
<button type='button' className={`text-end text-primary cursor-pointer font-[13px] font-medium ${getValues(`${mappedName}.sessions`)?.length > 1 ? "mr-9" : ''}`}
|
|
48
|
-
onClick={() => {
|
|
49
|
-
const lastEndTime = getValues(`${mappedName}.sessions`)?.[getValues(`${mappedName}.sessions`).length - 1]?.endTime || '08:30';
|
|
99
|
+
let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
|
|
100
|
+
const hookProps = useMemo(
|
|
101
|
+
() => formContext.register(props.fieldConfig.name, registerOptions),
|
|
102
|
+
[formContext, props.fieldConfig.name, registerOptions]
|
|
103
|
+
);
|
|
50
104
|
|
|
51
|
-
|
|
52
|
-
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
fetchData();
|
|
107
|
+
}, []);
|
|
53
108
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<div>{childByFieldName('endTime')}</div>
|
|
81
|
-
{index > 0 ?
|
|
82
|
-
<button
|
|
83
|
-
className="Button__StyledButton-sc-1l1v2a6-0 gVdTUT"
|
|
84
|
-
type="button"
|
|
85
|
-
onClick={() => {
|
|
86
|
-
remove(index);
|
|
87
|
-
}}
|
|
88
|
-
>
|
|
89
|
-
{/* <TrashIcon height={18} width={18} className=""/> */}
|
|
90
|
-
<Tippy content="Delete">
|
|
91
|
-
<XMarkIcon aria-hidden="true" height={18} width={18} className="" />
|
|
92
|
-
</Tippy>
|
|
93
|
-
|
|
94
|
-
</button> : <></>}
|
|
95
|
-
</div>
|
|
109
|
+
const getTimeConfig = (mappedName: string): FormFieldSchema => {
|
|
110
|
+
return {
|
|
111
|
+
required: true,
|
|
112
|
+
name: mappedName + ".sessions",
|
|
113
|
+
wrapper: ({ children }) => {
|
|
114
|
+
return (
|
|
115
|
+
<div style={{ border: "1px sold #ddd", padding: "0px" }}>
|
|
116
|
+
{children}
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
},
|
|
120
|
+
arrayWrapper: ({ children, append, getValues }) => {
|
|
121
|
+
return (
|
|
122
|
+
<>
|
|
123
|
+
<div style={{ border: "1px sold #ddd" }}>{children}</div>
|
|
124
|
+
<div className="w-full sm:w-full text-end mr-[2.3em]">
|
|
125
|
+
<button
|
|
126
|
+
type="button"
|
|
127
|
+
className={`text-end text-primary cursor-pointer font-[13px] font-medium ${
|
|
128
|
+
getValues(`${mappedName}.sessions`)?.length > 1 ? "mr-9" : ""
|
|
129
|
+
}`}
|
|
130
|
+
onClick={() => {
|
|
131
|
+
const lastEndTime =
|
|
132
|
+
getValues(`${mappedName}.sessions`)?.[
|
|
133
|
+
getValues(`${mappedName}.sessions`).length - 1
|
|
134
|
+
]?.endTime || "08:30";
|
|
96
135
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
formFieldType: FormFieldType.ARRAY,
|
|
100
|
-
align: FieldAlignType.HORIZONTAL,
|
|
101
|
-
disableDefaultWrapper: true,
|
|
102
|
-
defaultValue: {
|
|
103
|
-
startTime: "08:30",
|
|
104
|
-
endTime: "18:00"
|
|
105
|
-
},
|
|
106
|
-
children: [
|
|
107
|
-
{
|
|
108
|
-
required: false,
|
|
109
|
-
formFieldType: FormFieldType.TIME,
|
|
110
|
-
name: "startTime",
|
|
111
|
-
disableDefaultWrapper:true,
|
|
112
|
-
defaultValue: "08:30",
|
|
113
|
-
customClassNames: {
|
|
114
|
-
fieldClassName: "border-none bg-blue-100",
|
|
115
|
-
},
|
|
116
|
-
}, {
|
|
117
|
-
required: false,
|
|
118
|
-
formFieldType: FormFieldType.TIME,
|
|
119
|
-
name: "endTime",
|
|
120
|
-
disableDefaultWrapper: true,
|
|
121
|
-
defaultValue: "18:00",
|
|
122
|
-
customClassNames: {
|
|
123
|
-
fieldClassName: "border-none bg-blue-100",
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
],
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
;
|
|
136
|
+
const newStartTime = lastEndTime; // Start new session at last session's end time
|
|
137
|
+
const newEndTime = "23:00"; // Calculate end time, but cap at 23:00
|
|
130
138
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
append({
|
|
140
|
+
startTime: newStartTime,
|
|
141
|
+
endTime: newEndTime,
|
|
142
|
+
});
|
|
143
|
+
}}
|
|
144
|
+
>
|
|
145
|
+
+ Add
|
|
146
|
+
</button>
|
|
147
|
+
</div>
|
|
148
|
+
</>
|
|
149
|
+
);
|
|
150
|
+
},
|
|
151
|
+
arrayIndexWrapper: ({
|
|
152
|
+
mappedName,
|
|
153
|
+
getValues,
|
|
154
|
+
children,
|
|
155
|
+
childByFieldName,
|
|
156
|
+
append,
|
|
157
|
+
prepend,
|
|
158
|
+
remove,
|
|
159
|
+
index,
|
|
160
|
+
}) => {
|
|
161
|
+
return (
|
|
162
|
+
<div className="flex items-center gap-4 form-group !mb-2">
|
|
163
|
+
<div>{childByFieldName("startTime")}</div>
|
|
164
|
+
<p>To</p>
|
|
165
|
+
<div>{childByFieldName("endTime")}</div>
|
|
166
|
+
{index > 0 ? (
|
|
167
|
+
<button
|
|
168
|
+
className="Button__StyledButton-sc-1l1v2a6-0 gVdTUT"
|
|
169
|
+
type="button"
|
|
170
|
+
onClick={() => {
|
|
171
|
+
remove(index);
|
|
172
|
+
}}
|
|
173
|
+
>
|
|
174
|
+
{/* <TrashIcon height={18} width={18} className=""/> */}
|
|
175
|
+
<Tippy content="Delete">
|
|
176
|
+
<XMarkIcon
|
|
177
|
+
aria-hidden="true"
|
|
178
|
+
height={18}
|
|
179
|
+
width={18}
|
|
180
|
+
className=""
|
|
181
|
+
/>
|
|
182
|
+
</Tippy>
|
|
183
|
+
</button>
|
|
184
|
+
) : (
|
|
185
|
+
<></>
|
|
186
|
+
)}
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
},
|
|
190
|
+
formFieldType: FormFieldType.ARRAY,
|
|
191
|
+
align: FieldAlignType.HORIZONTAL,
|
|
192
|
+
disableDefaultWrapper: true,
|
|
193
|
+
defaultValue: {
|
|
194
|
+
startTime: "08:30",
|
|
195
|
+
endTime: "18:00",
|
|
196
|
+
},
|
|
197
|
+
children: [
|
|
198
|
+
{
|
|
199
|
+
required: false,
|
|
200
|
+
formFieldType: FormFieldType.TIME,
|
|
201
|
+
name: "startTime",
|
|
202
|
+
disableDefaultWrapper: true,
|
|
203
|
+
defaultValue: "08:30",
|
|
204
|
+
customClassNames: {
|
|
205
|
+
fieldClassName: "border-none bg-blue-100",
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
required: false,
|
|
210
|
+
formFieldType: FormFieldType.TIME,
|
|
211
|
+
name: "endTime",
|
|
212
|
+
disableDefaultWrapper: true,
|
|
213
|
+
defaultValue: "18:00",
|
|
214
|
+
customClassNames: {
|
|
215
|
+
fieldClassName: "border-none bg-blue-100",
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
};
|
|
142
221
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
222
|
+
const timeConfigs = useMemo(() => {
|
|
223
|
+
const configs: Record<string, FormFieldSchema> = {};
|
|
224
|
+
Object.keys(listOptions || {}).forEach((day) => {
|
|
225
|
+
configs[day] = getTimeConfig(props.fieldConfig.name + "." + day);
|
|
226
|
+
});
|
|
227
|
+
return configs;
|
|
228
|
+
}, [props.fieldConfig.name, listOptions]);
|
|
147
229
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
},
|
|
160
|
-
[props.fieldConfig.fetchUrl, props.fieldConfig.optionsConfig, props.fieldConfig.fetchCallback, props.fieldConfig.disableHeaderInFetch]
|
|
161
|
-
);
|
|
230
|
+
const fetchData = useCallback(async () => {
|
|
231
|
+
setLoading(true);
|
|
232
|
+
// if (!props.fieldConfig.fetchUrl) return;
|
|
233
|
+
let url = "/api/core/user-prefs/get-default-business-days";
|
|
234
|
+
if (props.fieldConfig.fetchUrl) {
|
|
235
|
+
url = props.fieldConfig.fetchUrl;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
let response = await (props.fieldConfig.disableHeaderInFetch
|
|
239
|
+
? axios.get(url)
|
|
240
|
+
: formContext.axiosInstance?.get(url));
|
|
162
241
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const dayInfo = listOptions[day as any];
|
|
168
|
-
return (
|
|
169
|
-
<>
|
|
170
|
-
<div className="flex baseline mb-6" data-testid="" key={day}>
|
|
171
|
-
<div className="max-w-sm space-y-2">
|
|
172
|
-
<div
|
|
173
|
-
className="group flex items-center w-full gap-x-2 text-sm font-normal leading-none text-gray-700 mt-3">
|
|
174
|
-
<SwitchField fieldConfig={{
|
|
175
|
-
name: props.fieldConfig.name + "." + day + ".enabledDay",
|
|
176
|
-
defaultValue: dayInfo.enabledDay,
|
|
177
|
-
required: false,
|
|
178
|
-
formFieldType: FormFieldType.SWITCH,
|
|
179
|
-
disableDefaultWrapper: true,
|
|
180
|
-
customClassNames: {
|
|
181
|
-
fieldClassName: "!mb-0",
|
|
182
|
-
},
|
|
183
|
-
}}/>
|
|
184
|
-
<p className="flex justify-between border-gray-900 text-sm text-gray-900 font-medium ml-2 w-24 leading-none">
|
|
185
|
-
<span className="w-full">{convertToTitleCase(day)}</span>
|
|
186
|
-
</p>
|
|
187
|
-
</div>
|
|
188
|
-
</div>
|
|
242
|
+
if (response?.data) {
|
|
243
|
+
const data: FieldOptionsSchema[] = response.data;
|
|
244
|
+
setListOptions(data);
|
|
245
|
+
setLoading(false);
|
|
189
246
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
247
|
+
if (props.fieldConfig.fetchCallback) {
|
|
248
|
+
props.fieldConfig.fetchCallback(response);
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
setListOptions(defaultBusinessHours);
|
|
252
|
+
console.error(response?.statusText);
|
|
253
|
+
setLoading(false);
|
|
254
|
+
}
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error("Fetch error:", error);
|
|
257
|
+
setLoading(false);
|
|
199
258
|
}
|
|
259
|
+
}, [
|
|
260
|
+
props.fieldConfig.fetchUrl,
|
|
261
|
+
props.fieldConfig.optionsConfig,
|
|
262
|
+
props.fieldConfig.fetchCallback,
|
|
263
|
+
props.fieldConfig.disableHeaderInFetch,
|
|
264
|
+
]);
|
|
200
265
|
|
|
266
|
+
function getInput() {
|
|
201
267
|
return (
|
|
202
|
-
|
|
268
|
+
<>
|
|
269
|
+
{loading ? (
|
|
270
|
+
<></>
|
|
271
|
+
) : (
|
|
272
|
+
listOptions &&
|
|
273
|
+
Object.keys(listOptions).map((day) => {
|
|
274
|
+
const dayInfo = listOptions[day as any];
|
|
275
|
+
return (
|
|
276
|
+
<>
|
|
277
|
+
<div className="flex baseline mb-6" data-testid="" key={day}>
|
|
278
|
+
<div className="max-w-sm space-y-2">
|
|
279
|
+
<div className="group flex items-center w-full gap-x-2 text-sm font-normal leading-none text-gray-700 mt-3">
|
|
280
|
+
<SwitchField
|
|
281
|
+
fieldConfig={{
|
|
282
|
+
name:
|
|
283
|
+
props.fieldConfig.name + "." + day + ".enabledDay",
|
|
284
|
+
defaultValue: dayInfo.enabledDay,
|
|
285
|
+
required: false,
|
|
286
|
+
formFieldType: FormFieldType.SWITCH,
|
|
287
|
+
disableDefaultWrapper: true,
|
|
288
|
+
customClassNames: {
|
|
289
|
+
fieldClassName: "!mb-0",
|
|
290
|
+
},
|
|
291
|
+
}}
|
|
292
|
+
/>
|
|
293
|
+
<p className="flex justify-between border-gray-900 text-sm text-gray-900 font-medium ml-2 w-24 leading-none">
|
|
294
|
+
<span className="w-full">
|
|
295
|
+
{convertToTitleCase(day)}
|
|
296
|
+
</span>
|
|
297
|
+
</p>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
|
|
301
|
+
<div className=" flex items-center text-gray-500 focus-within:text-blue-500">
|
|
302
|
+
<FormField fieldConfig={timeConfigs[day]} />
|
|
303
|
+
</div>
|
|
304
|
+
</div>
|
|
305
|
+
</>
|
|
306
|
+
);
|
|
307
|
+
})
|
|
308
|
+
)}
|
|
309
|
+
</>
|
|
203
310
|
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return (
|
|
314
|
+
<RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
|
|
315
|
+
);
|
|
204
316
|
};
|