@engagebay/engagebay-form-module 1.0.0-beta.3-3 → 1.0.0-beta.3-4
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/package.json
CHANGED
|
@@ -1,203 +1,311 @@
|
|
|
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
19
|
import SwitchField from "./SwitchField";
|
|
14
20
|
import FormField from "../FormField";
|
|
15
21
|
import RenderFormField from "../util/RenderFormField";
|
|
16
|
-
import {TrashIcon, XMarkIcon} from "@heroicons/react/24/outline";
|
|
22
|
+
import { TrashIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
|
17
23
|
import Tippy from "@tippyjs/react";
|
|
24
|
+
import { set } from "lodash";
|
|
18
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
|
+
};
|
|
19
91
|
|
|
20
|
-
export const BusinessHoursField: React.FC<FormFieldComponentPropSchema> = (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const hookProps = useMemo(() => formContext.register(props.fieldConfig.name, registerOptions), [formContext, props.fieldConfig.name, registerOptions]);
|
|
27
|
-
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
fetchData();
|
|
30
|
-
}, []);
|
|
31
|
-
|
|
32
|
-
const getTimeConfig = (mappedName: string): FormFieldSchema => {
|
|
33
|
-
return {
|
|
34
|
-
required: true,
|
|
35
|
-
name: mappedName + ".sessions",
|
|
36
|
-
wrapper: ({children}) => {
|
|
37
|
-
return <div style={{border: '1px sold #ddd', padding: '0px'}}>{children}</div>;
|
|
38
|
-
},
|
|
39
|
-
arrayWrapper: ({children, append,getValues}) => {
|
|
40
|
-
return (
|
|
41
|
-
<>
|
|
42
|
-
<div style={{border: '1px sold #ddd',}}>
|
|
43
|
-
{children}
|
|
44
|
-
</div>
|
|
45
|
-
<div className='w-full sm:w-full text-end mr-[2.3em]'>
|
|
46
|
-
<button type='button' className={`text-end text-primary cursor-pointer font-[13px] font-medium ${getValues(`${mappedName}.sessions`)?.length > 1 ? "mr-9" : ''}`}
|
|
47
|
-
onClick={() => {
|
|
48
|
-
const lastEndTime = getValues(`${mappedName}.sessions`)?.[getValues(`${mappedName}.sessions`).length - 1]?.endTime || '08:30';
|
|
49
|
-
|
|
50
|
-
const newStartTime = lastEndTime; // Start new session at last session's end time
|
|
51
|
-
const newEndTime = "23:00"; // Calculate end time, but cap at 23:00
|
|
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);
|
|
52
98
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
>
|
|
59
|
-
+ Add
|
|
60
|
-
</button>
|
|
61
|
-
</div>
|
|
62
|
-
</>
|
|
63
|
-
);
|
|
64
|
-
},
|
|
65
|
-
arrayIndexWrapper: ({
|
|
66
|
-
mappedName,
|
|
67
|
-
getValues,
|
|
68
|
-
children,
|
|
69
|
-
childByFieldName,
|
|
70
|
-
append,
|
|
71
|
-
prepend,
|
|
72
|
-
remove,
|
|
73
|
-
index
|
|
74
|
-
}) => {
|
|
75
|
-
return (
|
|
76
|
-
<div className="flex items-center gap-4 form-group !mb-2">
|
|
77
|
-
<div>{childByFieldName('startTime')}</div>
|
|
78
|
-
<p>To</p>
|
|
79
|
-
<div>{childByFieldName('endTime')}</div>
|
|
80
|
-
{index > 0 ?
|
|
81
|
-
<button
|
|
82
|
-
className="Button__StyledButton-sc-1l1v2a6-0 gVdTUT"
|
|
83
|
-
type="button"
|
|
84
|
-
onClick={() => {
|
|
85
|
-
remove(index);
|
|
86
|
-
}}
|
|
87
|
-
>
|
|
88
|
-
{/* <TrashIcon height={18} width={18} className=""/> */}
|
|
89
|
-
<Tippy content="Delete">
|
|
90
|
-
<XMarkIcon aria-hidden="true" height={18} width={18} className="" />
|
|
91
|
-
</Tippy>
|
|
92
|
-
|
|
93
|
-
</button> : <></>}
|
|
94
|
-
</div>
|
|
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
|
+
);
|
|
95
104
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
align: FieldAlignType.HORIZONTAL,
|
|
100
|
-
disableDefaultWrapper: true,
|
|
101
|
-
defaultValue: {
|
|
102
|
-
startTime: "08:30",
|
|
103
|
-
endTime: "18:00"
|
|
104
|
-
},
|
|
105
|
-
children: [
|
|
106
|
-
{
|
|
107
|
-
required: false,
|
|
108
|
-
formFieldType: FormFieldType.TIME,
|
|
109
|
-
name: "startTime",
|
|
110
|
-
disableDefaultWrapper:true,
|
|
111
|
-
defaultValue: "08:30",
|
|
112
|
-
customClassNames: {
|
|
113
|
-
fieldClassName: "border-none bg-blue-100",
|
|
114
|
-
},
|
|
115
|
-
}, {
|
|
116
|
-
required: false,
|
|
117
|
-
formFieldType: FormFieldType.TIME,
|
|
118
|
-
name: "endTime",
|
|
119
|
-
disableDefaultWrapper: true,
|
|
120
|
-
defaultValue: "18:00",
|
|
121
|
-
customClassNames: {
|
|
122
|
-
fieldClassName: "border-none bg-blue-100",
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
;
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
fetchData();
|
|
107
|
+
}, []);
|
|
129
108
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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";
|
|
141
135
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
setListOptions(data);
|
|
145
|
-
setLoading(false);
|
|
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
|
|
146
138
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
+
},
|
|
158
207
|
},
|
|
159
|
-
|
|
160
|
-
|
|
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
|
+
};
|
|
221
|
+
const fetchData = useCallback(async () => {
|
|
222
|
+
setLoading(true);
|
|
223
|
+
// if (!props.fieldConfig.fetchUrl) return;
|
|
224
|
+
let url = "/api/core/user-prefs/get-default-business-days";
|
|
225
|
+
if (props.fieldConfig.fetchUrl) {
|
|
226
|
+
url = props.fieldConfig.fetchUrl;
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
let response = await (props.fieldConfig.disableHeaderInFetch
|
|
230
|
+
? axios.get(url)
|
|
231
|
+
: formContext.axiosInstance?.get(url));
|
|
161
232
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const dayInfo = listOptions[day as any];
|
|
167
|
-
return (
|
|
168
|
-
<>
|
|
169
|
-
<div className="flex baseline mb-6" data-testid="" key={day}>
|
|
170
|
-
<div className="max-w-sm space-y-2">
|
|
171
|
-
<div
|
|
172
|
-
className="group flex items-center w-full gap-x-2 text-sm font-normal leading-none text-gray-700 mt-3">
|
|
173
|
-
<SwitchField fieldConfig={{
|
|
174
|
-
name: props.fieldConfig.name + "." + day + ".enabledDay",
|
|
175
|
-
defaultValue: dayInfo.enabledDay,
|
|
176
|
-
required: false,
|
|
177
|
-
formFieldType: FormFieldType.SWITCH,
|
|
178
|
-
disableDefaultWrapper: true,
|
|
179
|
-
customClassNames: {
|
|
180
|
-
fieldClassName: "!mb-0",
|
|
181
|
-
},
|
|
182
|
-
}}/>
|
|
183
|
-
<p className="flex justify-between border-gray-900 text-sm text-gray-900 font-medium ml-2 w-24 leading-none">
|
|
184
|
-
<span className="w-full">{convertToTitleCase(day)}</span>
|
|
185
|
-
</p>
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|
|
233
|
+
if (response?.data) {
|
|
234
|
+
const data: FieldOptionsSchema[] = response.data;
|
|
235
|
+
setListOptions(data);
|
|
236
|
+
setLoading(false);
|
|
188
237
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
238
|
+
if (props.fieldConfig.fetchCallback) {
|
|
239
|
+
props.fieldConfig.fetchCallback(response);
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
setListOptions(defaultBusinessHours);
|
|
243
|
+
console.error(response?.statusText);
|
|
244
|
+
setLoading(false);
|
|
245
|
+
}
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error("Fetch error:", error);
|
|
248
|
+
setLoading(false);
|
|
198
249
|
}
|
|
250
|
+
}, [
|
|
251
|
+
props.fieldConfig.fetchUrl,
|
|
252
|
+
props.fieldConfig.optionsConfig,
|
|
253
|
+
props.fieldConfig.fetchCallback,
|
|
254
|
+
props.fieldConfig.disableHeaderInFetch,
|
|
255
|
+
]);
|
|
199
256
|
|
|
257
|
+
function getInput() {
|
|
200
258
|
return (
|
|
201
|
-
|
|
259
|
+
<>
|
|
260
|
+
{loading ? (
|
|
261
|
+
<></>
|
|
262
|
+
) : (
|
|
263
|
+
listOptions &&
|
|
264
|
+
Object.keys(listOptions).map((day) => {
|
|
265
|
+
const dayInfo = listOptions[day as any];
|
|
266
|
+
return (
|
|
267
|
+
<>
|
|
268
|
+
<div className="flex baseline mb-6" data-testid="" key={day}>
|
|
269
|
+
<div className="max-w-sm space-y-2">
|
|
270
|
+
<div className="group flex items-center w-full gap-x-2 text-sm font-normal leading-none text-gray-700 mt-3">
|
|
271
|
+
<SwitchField
|
|
272
|
+
fieldConfig={{
|
|
273
|
+
name:
|
|
274
|
+
props.fieldConfig.name + "." + day + ".enabledDay",
|
|
275
|
+
defaultValue: dayInfo.enabledDay,
|
|
276
|
+
required: false,
|
|
277
|
+
formFieldType: FormFieldType.SWITCH,
|
|
278
|
+
disableDefaultWrapper: true,
|
|
279
|
+
customClassNames: {
|
|
280
|
+
fieldClassName: "!mb-0",
|
|
281
|
+
},
|
|
282
|
+
}}
|
|
283
|
+
/>
|
|
284
|
+
<p className="flex justify-between border-gray-900 text-sm text-gray-900 font-medium ml-2 w-24 leading-none">
|
|
285
|
+
<span className="w-full">
|
|
286
|
+
{convertToTitleCase(day)}
|
|
287
|
+
</span>
|
|
288
|
+
</p>
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
|
|
292
|
+
<div className=" flex items-center text-gray-500 focus-within:text-blue-500">
|
|
293
|
+
<FormField
|
|
294
|
+
fieldConfig={getTimeConfig(
|
|
295
|
+
props.fieldConfig.name + "." + day
|
|
296
|
+
)}
|
|
297
|
+
/>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
</>
|
|
301
|
+
);
|
|
302
|
+
})
|
|
303
|
+
)}
|
|
304
|
+
</>
|
|
202
305
|
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return (
|
|
309
|
+
<RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
|
|
310
|
+
);
|
|
203
311
|
};
|