ui-soxo-bootstrap-core 2.4.24 → 2.4.25-dev.6

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 (33) hide show
  1. package/.github/workflows/npm-publish.yml +37 -15
  2. package/README.md +260 -0
  3. package/core/components/extra-info/extra-info-details.js +109 -126
  4. package/core/components/landing-api/landing-api.js +22 -30
  5. package/core/lib/Store.js +20 -18
  6. package/core/lib/components/index.js +4 -1
  7. package/core/lib/components/sidemenu/sidemenu.js +153 -256
  8. package/core/lib/components/sidemenu/sidemenu.scss +39 -26
  9. package/core/lib/hooks/index.js +2 -12
  10. package/core/lib/hooks/use-otp-timer.js +99 -0
  11. package/core/lib/pages/login/login.js +255 -139
  12. package/core/lib/pages/login/login.scss +140 -32
  13. package/core/models/dashboard/dashboard.js +14 -0
  14. package/core/models/doctor/components/doctor-add/doctor-add.js +403 -0
  15. package/core/models/doctor/components/doctor-add/doctor-add.scss +32 -0
  16. package/core/models/menus/components/menu-add/menu-add.js +230 -268
  17. package/core/models/menus/components/menu-lists/menu-lists.js +126 -89
  18. package/core/models/menus/components/menu-lists/menu-lists.scss +9 -0
  19. package/core/models/menus/menus.js +247 -267
  20. package/core/models/roles/components/role-add/role-add.js +269 -227
  21. package/core/models/roles/components/role-list/role-list.js +8 -6
  22. package/core/models/roles/roles.js +182 -174
  23. package/core/models/users/components/user-add/user-add.js +619 -365
  24. package/core/models/users/components/user-add/user-edit.js +90 -0
  25. package/core/models/users/users.js +261 -165
  26. package/core/modules/index.js +5 -8
  27. package/core/modules/reporting/components/index.js +5 -0
  28. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +65 -2
  29. package/core/modules/steps/action-buttons.js +79 -0
  30. package/core/modules/steps/steps.js +553 -0
  31. package/core/modules/steps/steps.scss +158 -0
  32. package/core/modules/steps/timeline.js +49 -0
  33. package/package.json +2 -2
@@ -2,8 +2,7 @@ import React, { useState, useEffect, useContext } from 'react';
2
2
 
3
3
  import { useLocation } from 'react-router-dom';
4
4
 
5
- import { Skeleton, Typography, message, Switch, Form, Input, Select, Checkbox } from 'antd';
6
-
5
+ import { Skeleton, Typography, message, Switch, Form, Input, Select, Checkbox, Row, Col } from 'antd';
7
6
 
8
7
  import AsyncSelect from 'react-select/async';
9
8
 
@@ -12,350 +11,593 @@ import { Table, Card, Button, JSONInput, GlobalContext } from './../../../../lib
12
11
  import { ModelsAPI, PagesAPI } from '../../..';
13
12
 
14
13
  import { UsersAPI } from '../../..';
14
+ import DoctorAdd from '../../../doctor/components/doctor-add/doctor-add';
15
15
 
16
16
  const { Title } = Typography;
17
17
 
18
18
  const { Option } = Select;
19
19
 
20
- const UserAdd = ({ model, callback, edit, history, formContent, match, additional_queries, props }) => {
21
-
22
- /**Getting user data */
23
- const { user = {} } = useContext(GlobalContext);
24
- let mode = 'Add';
25
-
26
- const [disabled, setDisabled] = useState(true);
27
-
28
- const [selectedOption, setSelectedOption] = useState(null);
29
-
30
- //Need to check this condition
31
- const [authentication, setAuthentication] = useState(false);
32
-
33
- /**To store user values */
34
- const [users, setUsers] = useState([]);
35
-
36
- /**Converting to JSON */
37
- let firmDetails = JSON.parse(user.firm.f_otherdetails1);
38
-
39
- /**Variable for cheaking mandatory condition of mobile*/
40
- let mobileRequired;
41
-
42
- /**If mode is mobile and fa is 'MND' or 'USR' then mobile is mandatory */
43
- if ((firmDetails && firmDetails.FA === 'MND' || firmDetails && firmDetails.FA === 'USR') && (firmDetails.mode === 'mobile')) {
44
-
45
- mobileRequired = true
46
-
47
- } else {
48
-
49
- mobileRequired = false
50
- }
51
-
52
- if (formContent.id) {
53
- mode = 'Edit'
54
- } else if (formContent.copy) {
55
- mode = 'Copy'
56
- }
57
-
58
- if (formContent.attributes) {
59
-
60
- if (typeof formContent.attributes === 'string') {
61
-
62
- if (formContent.attributes !== '') {
63
-
64
- formContent.attributes = JSON.parse(formContent.attributes);
65
-
66
- } else {
67
-
68
- formContent.attributes = {};
69
-
70
- }
20
+ const UserAdd = ({ model, callback, edit, history, formContent, match, additional_queries, props, mode = 'Add', attributes }) => {
21
+ /**Getting user data */
22
+ const { user = {} } = useContext(GlobalContext);
23
+ // let mode = 'Add';
24
+
25
+ const [disabled, setDisabled] = useState(true);
26
+
27
+ const [selectedOption, setSelectedOption] = useState(null);
28
+ // for selected branches
29
+ const [selectedBranches, setSelectedBranches] = useState([]);
30
+
31
+ // for default branch
32
+ const [defaultBranch, setDefaultBranch] = useState(null);
33
+ //Need to check this condition
34
+ const [authentication, setAuthentication] = useState(false);
35
+
36
+ /**To store user values */
37
+ const [users, setUsers] = useState([]);
38
+ const [doctorID, setDoctorID] = useState(false);
39
+ const [selectedDoctor, setSelectedDoctor] = useState(null);
40
+ /**Converting to JSON */
41
+ let firmDetails = JSON.parse(user.firm.f_otherdetails1);
42
+
43
+ /**Variable for cheaking mandatory condition of mobile*/
44
+ let mobileRequired;
45
+
46
+ /**If mode is mobile and fa is 'MND' or 'USR' then mobile is mandatory */
47
+ if (((firmDetails && firmDetails.FA === 'MND') || (firmDetails && firmDetails.FA === 'USR')) && firmDetails.mode === 'mobile') {
48
+ mobileRequired = true;
49
+ } else {
50
+ mobileRequired = false;
51
+ }
52
+
53
+ if (formContent?.id) {
54
+ mode = 'Edit';
55
+ } else if (formContent?.copy) {
56
+ mode = 'Copy';
57
+ }
58
+
59
+ if (formContent?.attributes) {
60
+ if (typeof formContent.attributes === 'string') {
61
+ if (formContent.attributes !== '') {
62
+ formContent.attributes = JSON.parse(formContent.attributes);
63
+ } else {
64
+ if (formContent) {
65
+ formContent.attributes = {};
71
66
  }
72
- } else {
73
- formContent.attributes = {}
67
+ }
74
68
  }
75
-
76
- const [loading, setLoading] = useState(true);
77
-
78
- const [form] = Form.useForm();
79
-
80
- const [body, setBody] = useState(formContent);
81
-
82
- const [isPasswordVisible, setIsPasswordVisible] = useState(false);
83
-
84
- const formData = {
85
- ...body,
86
- /**If panel is open then takes password in body */
87
- password: !isPasswordVisible ? "" : body.password
69
+ } else {
70
+ if (formContent) {
71
+ formContent.attributes = {};
88
72
  }
89
-
90
-
91
- let passwordRegex
92
- let passwordRegexMessage
93
-
94
- if (props && props?.passwordRegex && props?.passwordRegexMessage) {
95
- passwordRegex = props.passwordRegex
96
- passwordRegexMessage = props.passwordRegexMessage
97
- } else if (process.env.REACT_APP_PASSWORD_REGEX && process.env.REACT_APP_PASSWORD_REGEX_MESSAGE) {
98
- passwordRegex = process.env.REACT_APP_PASSWORD_REGEX
99
- passwordRegexMessage = process.env.REACT_APP_PASSWORD_REGEX_MESSAGE
100
- } else {
101
- passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>])[A-Za-z\d!@#$%^&*(),.?":{}|<>]{8,}$/
102
- passwordRegexMessage = "Password must be at least 8 characters long and contain atleast one uppercase letter, one lowercase letter, one digit and one special character"
73
+ }
74
+
75
+ const [loading, setLoading] = useState(true);
76
+ // user type state
77
+ const [userType, setUserType] = useState('general');
78
+ // state for branches list
79
+ const [branches, setBranches] = useState([]);
80
+ // designation list state
81
+ const [designations, setDesignations] = useState([]);
82
+ // department list state
83
+ const [departments, setDepartments] = useState([]);
84
+ // doctor list state
85
+ const [doctorList, setDoctorList] = useState([]);
86
+
87
+ const [form] = Form.useForm();
88
+
89
+ const [body, setBody] = useState(formContent);
90
+
91
+ const [isPasswordVisible, setIsPasswordVisible] = useState(false);
92
+ const [visible, setVisible] = useState(false);
93
+
94
+ const formData = {
95
+ ...body,
96
+ /**If panel is open then takes password in body */
97
+ password: !isPasswordVisible ? '' : body.password,
98
+ };
99
+
100
+ let passwordRegex;
101
+ let passwordRegexMessage;
102
+
103
+ if (props && props?.passwordRegex && props?.passwordRegexMessage) {
104
+ passwordRegex = props.passwordRegex;
105
+ passwordRegexMessage = props.passwordRegexMessage;
106
+ } else if (process.env.REACT_APP_PASSWORD_REGEX && process.env.REACT_APP_PASSWORD_REGEX_MESSAGE) {
107
+ passwordRegex = process.env.REACT_APP_PASSWORD_REGEX;
108
+ passwordRegexMessage = process.env.REACT_APP_PASSWORD_REGEX_MESSAGE;
109
+ } else {
110
+ passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>])[A-Za-z\d!@#$%^&*(),.?":{}|<>]{8,}$/;
111
+ passwordRegexMessage =
112
+ 'Password must be at least 8 characters long and contain atleast one uppercase letter, one lowercase letter, one digit and one special character';
113
+ }
114
+
115
+ useEffect(() => {
116
+ if (!loading && formContent) {
117
+ form.resetFields(); // clear previous values
118
+ form.setFieldsValue(formContent);
103
119
  }
120
+ }, [loading, formContent]);
121
+
122
+ useEffect(() => {
123
+ if (formContent?.auth_user) {
124
+ setSelectedOption({
125
+ value: formContent.auth_user,
126
+ label: formContent.auth_user, // Add a helper function to capitalize
127
+ });
128
+ }
129
+ }, [formContent?.auth_user]);
104
130
 
131
+ useEffect(() => {
132
+ loadUsers();
133
+ setLoading(false);
105
134
 
135
+ if (firmDetails) {
136
+ /**if firmmas.otherdetails - 2FA == MND, then, 2FA option will be enabled by default and read-only */
137
+ if (firmDetails.FA == 'MND') {
138
+ setAuthentication(true);
106
139
 
140
+ setDisabled(true);
107
141
 
108
- useEffect(() => {
109
- if (formContent.auth_user) {
110
- setSelectedOption({
111
- value: formContent.auth_user,
112
- label: formContent.auth_user, // Add a helper function to capitalize
113
- });
114
- }
115
- }, [formContent.auth_user]);
116
-
117
-
118
- useEffect(() => {
119
-
120
- loadUsers()
121
- setLoading(false);
122
-
123
- if (firmDetails) {
124
-
125
- /**if firmmas.otherdetails - 2FA == MND, then, 2FA option will be enabled by default and read-only */
126
- if (firmDetails.FA == 'MND') {
127
-
128
- setAuthentication(true)
129
-
130
- setDisabled(true)
131
-
132
- /**if firmmas.otherdetails - 2FA == OPT, then, 2FA option will be enabled by default and editable */
133
- } else if (firmDetails.FA == 'USR') {
134
-
135
- setAuthentication(true)
136
-
137
- setDisabled(true)
138
-
139
- /**if firmmas.otherdetails - 2FA == NAP, then, 2FA option will be disabled by default and read-only*/
140
- } else if (firmDetails.FA == 'NAP') {
141
-
142
- setAuthentication(false)
143
-
144
- setDisabled(true)
145
- }
146
-
147
- }
148
-
149
-
150
- }, []);
142
+ /**if firmmas.otherdetails - 2FA == OPT, then, 2FA option will be enabled by default and editable */
143
+ } else if (firmDetails.FA == 'USR') {
144
+ setAuthentication(true);
151
145
 
152
- /**
153
- * Submit values
154
- */
155
- const onSubmit = (values) => {
146
+ setDisabled(true);
156
147
 
157
- /**If PanelOpen is open and edit mode then password will be existing password else new password*/
158
- if (!isPasswordVisible && mode === 'Edit') {
159
- values.password = body.password;
160
- }
148
+ /**if firmmas.otherdetails - 2FA == NAP, then, 2FA option will be disabled by default and read-only*/
149
+ } else if (firmDetails.FA == 'NAP') {
150
+ setAuthentication(false);
161
151
 
162
- values = {
163
- ...values,
164
- auth_type: 'LDAP',
165
- FA: authentication
152
+ setDisabled(true);
153
+ }
154
+ }
155
+ }, []);
156
+ /**
157
+ *Define the options dynamically
158
+ */
159
+ const getUserTypeOptions = () => [
160
+ { label: 'General', value: 'GEN' },
161
+ { label: 'Doctor', value: 'RAD' },
162
+ { label: 'Radiographer', value: 'TECH' },
163
+ ];
164
+
165
+ /**
166
+ * Get Branch List
167
+ */
168
+ const getBranches = () => {
169
+ setLoading(true);
170
+ UsersAPI.getBranches().then(async (result) => {
171
+ const details = await result.result.map((ele) => {
172
+ return {
173
+ ...ele,
174
+ ...(ele.br_otherdet1 ? JSON.parse(ele.br_otherdet1) : {}),
175
+ };
176
+ });
177
+ setBranches(details);
178
+ setLoading(false);
179
+ });
180
+ };
181
+
182
+ /** Get Designation List */
183
+ const getDesignations = () => {
184
+ setLoading(true);
185
+ UsersAPI.getDesignations()
186
+ .then((result) => {
187
+ if (result?.success && Array.isArray(result.result)) {
188
+ const details = result.result.map((ele) => ({
189
+ label: ele.dg_desc?.trim() || '',
190
+ value: ele.dg_code,
191
+ }));
192
+ setDesignations(details);
193
+ } else {
194
+ setDesignations([]);
166
195
  }
167
-
168
- setLoading(true);
169
-
170
- let id = formContent.id;
171
- if (props.ldap && selectedOption && selectedOption.value) {
172
- values = {
173
- ...values,
174
- addAllBranches: props.ldap.addAllBranches,
175
- auth_user: selectedOption.value,
176
- auth_type: 'LDAP',
177
- FA: authentication
178
- }
196
+ })
197
+ .catch((error) => {
198
+ console.error('Error fetching designations:', error);
199
+ setDesignations([]);
200
+ })
201
+ .finally(() => setLoading(false));
202
+ };
203
+
204
+ /** Get Department List */
205
+ const getDepartments = () => {
206
+ setLoading(true);
207
+ UsersAPI.getDepartments()
208
+ .then((result) => {
209
+ if (result?.success && Array.isArray(result.result)) {
210
+ const details = result.result.map((ele) => ({
211
+ label: ele.dp_desc?.trim() || '',
212
+ value: ele.dp_id,
213
+ }));
214
+ setDepartments(details);
215
+ } else {
216
+ setDepartments([]);
179
217
  }
180
-
181
- if (values.attributes && typeof values === 'object') {
182
-
183
- values = {
184
- ...values,
185
- auth_type: 'LDAP',
186
-
187
- attributes: JSON.stringify(values.attributes)
188
- }
218
+ })
219
+ .catch((error) => {
220
+ console.error('Error fetching departments:', error);
221
+ setDepartments([]);
222
+ })
223
+ .finally(() => setLoading(false));
224
+ };
225
+
226
+ /** Get Doctor List */
227
+ const getDoctors = () => {
228
+ UsersAPI.getDoctors()
229
+ .then((res) => {
230
+ if (res?.success && Array.isArray(res.result)) {
231
+ const list = res.result.map((doc) => ({
232
+ label: `${doc.do_name} (${doc.do_code})`,
233
+ value: doc.do_code,
234
+ }));
235
+ setDoctorList(list);
189
236
  }
237
+ })
238
+ .catch((err) => console.error('Doctor API Error:', err));
239
+ };
190
240
 
191
- if (id) {
192
-
193
- // Update of model
194
- UsersAPI.updateUser({ id, formBody: values }).then((result) => {
241
+ // Function to handle user type change
242
+ const handleUserTypeChange = (value) => {
243
+ setUserType(value);
195
244
 
196
- if (result.success)
197
-
198
- message.success(result.message);
199
-
200
- else
201
- message.error(result.message)
202
-
203
- setLoading(false);
204
-
205
- callback();
206
-
207
- });
208
-
209
- } else {
210
-
211
- // Append the additional queries to the object
212
- additional_queries.forEach(({ field, value }) => {
213
-
214
- values[field] = value;
215
-
216
- })
217
-
218
- // add new model
219
- UsersAPI.create(values).then((result) => {
220
-
221
- // callback();
222
- if (result.success)
223
-
224
- message.success(result.message);
225
-
226
- else
227
- message.error(result.message)
228
-
229
- setLoading(false);
230
-
231
- callback();
232
-
233
- });
234
- }
235
- };
236
-
237
- /**
238
- * Function on handle change
239
- * @param {*} selected
245
+ if (value === 'RAD') {
246
+ getDoctors(); // load doctor list
247
+ } else {
248
+ form.setFieldsValue({ default_code: undefined });
249
+ }
250
+ };
251
+
252
+ useEffect(() => {
253
+ getBranches();
254
+ getDesignations();
255
+ getDepartments();
256
+ getDoctors(); // load doctor list
257
+ }, []);
258
+
259
+ useEffect(() => {
260
+ if (formContent && formContent.user_type) {
261
+ form.setFieldsValue({ user_type: formContent.user_type });
262
+ setUserType(formContent.user_type);
263
+
264
+ if (formContent.user_type === 'RAD' && formContent.doctor_code) {
265
+ form.setFieldsValue({ default_code: formContent.doctor_code });
266
+ }
267
+ }
268
+ if (formContent?.id && formContent?.organization_details) {
269
+ try {
270
+ const org = JSON.parse(formContent.organization_details);
271
+ const branchIds = org.branch_ids?.map((b) => b.id) || [];
272
+ const defaultBranchObj = org.branch_ids?.find((b) => b.DefaultBranch === 'true');
273
+ const defaultBr = defaultBranchObj?.id || null;
274
+
275
+ setSelectedBranches(branchIds);
276
+ setDefaultBranch(defaultBr);
277
+
278
+ form.setFieldsValue({
279
+ selectedBranches: branchIds,
280
+ defaultBranch: defaultBr,
281
+ });
282
+ } catch (err) {
283
+ console.error('Invalid organization_details JSON', err);
284
+ }
285
+ }
286
+ }, [formContent]);
287
+ // Generate branch options for Select component
288
+ const branchOptions = branches.map((branch) => ({
289
+ label: branch.br_desc,
290
+ value: branch.br_code,
291
+ }));
292
+
293
+ /**
294
+ * Submit values
240
295
  */
241
- const handleCheackChange = (e) => {
296
+ const onSubmit = (values) => {
297
+ console.log('values____________', values);
298
+ /**If PanelOpen is open and edit mode then password will be existing password else new password*/
299
+ if (!isPasswordVisible && mode === 'Edit') {
300
+ values.password = body.password;
301
+ }
302
+ values.user_type = values.user_type;
242
303
 
243
- setIsPasswordVisible(e.target.checked);
304
+ if (values.user_type === 'RAD') {
305
+ values.doctor_code = values.default_code;
306
+ } else {
307
+ values.doctor_code = null;
308
+ }
309
+ values = {
310
+ ...values,
311
+ auth_type: 'LDAP',
312
+ FA: authentication,
244
313
  };
245
314
 
315
+ setLoading(true);
316
+
317
+ let id = formContent?.id;
318
+ if (props?.ldap && selectedOption && selectedOption.value) {
319
+ values = {
320
+ ...values,
321
+ addAllBranches: props.ldap.addAllBranches,
322
+ auth_user: selectedOption.value,
323
+ auth_type: 'LDAP',
324
+ FA: authentication,
325
+ };
326
+ }
246
327
 
247
- function changeView(result) {
328
+ if (values.attributes && typeof values === 'object') {
329
+ values = {
330
+ ...values,
331
+ auth_type: 'LDAP',
248
332
 
249
- setAuthentication(result);
333
+ attributes: JSON.stringify(values.attributes),
334
+ };
250
335
  }
251
336
 
252
- /**
253
- * Function to add load userrs
254
- */
255
- function loadUsers() {
337
+ if (id) {
338
+ // Update of model
256
339
 
257
- // UsersAPI.getLdapUsers().then((result) => {
340
+ UsersAPI.updateUser({ id, formBody: values }).then((result) => {
341
+ if (result.success) message.success(result.message);
342
+ else message.error(result.message);
258
343
 
259
- // setUsers(result.result);
344
+ setLoading(false);
260
345
 
261
- // });
346
+ callback();
347
+ });
348
+ } else {
349
+ // Append the additional queries to the object
350
+ // additional_queries.forEach(({ field, value }) => {
351
+ // values[field] = value;
352
+ // });
353
+ if (Array.isArray(additional_queries)) {
354
+ additional_queries.forEach(({ field, value }) => {
355
+ values[field] = value;
356
+ });
357
+ }
358
+
359
+ // add new model
360
+ UsersAPI.create(values).then((result) => {
361
+ // callback();
362
+ if (result.success) message.success(result.message);
363
+ else message.error(result.message);
262
364
 
263
- }
365
+ setLoading(false);
264
366
 
265
- // Transform array into react-select options
266
- let options = users.map(item => ({
267
- value: item.name,
268
- label: item.name// Capitalize the first letter
269
- }));
270
-
271
- /**
272
- * Function on handle change
273
- * @param {*} selected
274
- */
275
- const handleChange = (selected) => {
276
- setSelectedOption(selected);
277
- };
278
- /**
279
- *
280
- * @param {*} inputValue
281
- * @param {*} callback
282
- */
283
-
284
- const loadOptions = (inputValue, callback) => {
285
- // Filter options based on input
286
- const filteredOptions = options.filter(option =>
287
- option.label.toLowerCase().includes(inputValue.toLowerCase())
288
- );
289
- callback(filteredOptions);
290
- };
367
+ callback();
368
+ });
369
+ }
370
+ };
291
371
 
292
- return (
293
- <section className="collection-add">
294
- <Title level={4}>{mode} User</Title>
372
+ /**
373
+ * Function on handle change
374
+ * @param {*} selected
375
+ */
376
+ const handleCheackChange = (e) => {
377
+ setIsPasswordVisible(e.target.checked);
378
+ };
295
379
 
296
- {loading ? (
297
- <Skeleton />
298
- ) : (
299
- <Form initialValues={formData} form={form} layout="vertical" onFinish={onSubmit}>
380
+ function changeView(result) {
381
+ setAuthentication(result);
382
+ }
300
383
 
301
- {/* Caption */}
302
- <Form.Item name={"name"} label="Name" required>
303
- <Input placeholder="Enter name" />
304
- </Form.Item>
305
- {/* Caption Ends */}
384
+ /**
385
+ * Function to add load userrs
386
+ */
387
+ function loadUsers() {
388
+ // UsersAPI.getLdapUsers().then((result) => {
389
+ // setUsers(result.result);
390
+ // });
391
+ }
392
+
393
+ // Transform array into react-select options
394
+ let options = users.map((item) => ({
395
+ value: item.name,
396
+ label: item.name, // Capitalize the first letter
397
+ }));
398
+
399
+ /**
400
+ * Function on handle change
401
+ * @param {*} selected
402
+ */
403
+ const handleChange = (selected) => {
404
+ setSelectedOption(selected);
405
+ };
406
+ /**
407
+ *
408
+ * @param {*} inputValue
409
+ * @param {*} callback
410
+ */
306
411
 
307
- {/* Name */}
308
- <Form.Item name={"email"} label="Email" required>
309
- <Input placeholder="Enter email" />
310
- </Form.Item>
311
- {/* Name Ends */}
312
-
313
- {formContent.id ? (
314
- <>
315
- <Form.Item>
316
- <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
317
- <Checkbox onChange={handleCheackChange} />
318
- <span>Select the option if you want to change the password</span>
319
- </div>
320
- </Form.Item>
321
-
322
- {isPasswordVisible && (
323
- <Form.Item
324
- name="password"
325
- label="Password"
326
- rules={[
327
- { required: true, message: 'Please enter your password' },
328
- { pattern: passwordRegex, message: passwordRegexMessage },
329
- ]}
330
- >
331
- <Input.Password placeholder="Enter password" autoComplete="new-password" />
332
- </Form.Item>
333
- )}
334
- </>
335
- ) : (
336
- <Form.Item
337
- name="password"
338
- label="Password"
339
- rules={[
340
- {
341
- required: true,
342
- message: 'Please enter your password',
343
- },
344
- {
345
- pattern: new RegExp(passwordRegex),
346
- message: passwordRegexMessage,
347
- },
348
- ]}
412
+ const loadOptions = (inputValue, callback) => {
413
+ // Filter options based on input
414
+ const filteredOptions = options.filter((option) => option.label.toLowerCase().includes(inputValue.toLowerCase()));
415
+ callback(filteredOptions);
416
+ };
417
+
418
+ return (
419
+ <section className="collection-add">
420
+ <Title level={4}>{mode} User</Title>
421
+
422
+ {loading ? (
423
+ <Skeleton />
424
+ ) : (
425
+ <Form initialValues={formData} form={form} layout="vertical" onFinish={onSubmit}>
426
+ {/* user type */}
427
+ <Row gutter={16}>
428
+ <Col span={6}>
429
+ <Form.Item
430
+ name="user_type"
431
+ label="User Type"
432
+ allowClear
433
+ showSearch
434
+ initialValue="GEN"
435
+ rules={[{ required: true, message: 'Please select a user type' }]}
436
+ >
437
+ <Select options={getUserTypeOptions()} onChange={handleUserTypeChange} />
438
+ </Form.Item>
439
+ </Col>
440
+ <Col span={12}>
441
+ {/* username */}
442
+ <Form.Item name={'name'} label="Name" rules={[{ required: true, message: 'Please enter your user name' }]}>
443
+ <Input placeholder="Enter Name" autoFocus />
444
+ </Form.Item>
445
+ </Col>
446
+ <Col span={6}>
447
+ {' '}
448
+ {/* Show extra dropdown only if user type is Doctor */}
449
+ {userType === 'RAD' && (
450
+ <Form.Item name="default_code" label="Default Code" rules={[{ required: true, message: 'Please select a default code' }]}>
451
+ <Select
452
+ placeholder="Select Code"
453
+ options={doctorList}
454
+ showSearch
455
+ optionFilterProp="label"
456
+ dropdownRender={(menu) => (
457
+ <>
458
+ {menu}
459
+ <div
460
+ style={{
461
+ padding: '8px',
462
+ cursor: 'pointer',
463
+ borderTop: '1px solid #f0f0f0',
464
+ color: '#1890ff',
465
+ }}
466
+ onClick={() => setVisible(true)}
349
467
  >
350
- <Input.Password visibilityToggle={false} placeholder="Enter password" autoComplete="new-password" />
351
- </Form.Item>
468
+ + Add New Doctor
469
+ </div>
470
+ </>
352
471
  )}
353
-
354
- {/* </Form.Item> */}
355
-
356
-
357
- {/* Path */}
358
- {/* <Form.Item name="password" label="Password"
472
+ />
473
+ {/* Render DoctorAdd OUTSIDE the Select */}
474
+ <DoctorAdd
475
+ visible={visible}
476
+ onCancel={() => setVisible(false)}
477
+ attributes={attributes}
478
+ doctorData={selectedDoctor}
479
+ doctorId={doctorID}
480
+ onSuccess={getDoctors}
481
+ />
482
+ </Form.Item>
483
+ )}
484
+ </Col>
485
+ </Row>
486
+ <Row gutter={16}>
487
+ <Col span={8}>
488
+ {/* email */}
489
+ <Form.Item name={'email'} label="User Name / Email" rules={[{ required: true, message: 'Please enter your email' }]}>
490
+ <Input placeholder="Enter Email Address" />
491
+ </Form.Item>
492
+ </Col>
493
+ <Col span={8}>
494
+ {/* Mobile */}
495
+ <Form.Item name="mobile" label="Mobile" rules={[{ required: true, message: 'Please enter your mobile number' }]}>
496
+ <Input placeholder="Enter Mobile" />
497
+ </Form.Item>
498
+ </Col>
499
+ <Col span={8}>
500
+ {/* Designation */}
501
+ <Form.Item name="designation" label="Designation">
502
+ <Select placeholder="Select Designation" options={designations} allowClear showSearch optionFilterProp="label" />
503
+ </Form.Item>
504
+ </Col>
505
+ </Row>
506
+ <Row gutter={16}>
507
+ {' '}
508
+ <Col span={8}>
509
+ {/* Department */}
510
+ <Form.Item name="department" label="Department">
511
+ <Select placeholder="Select Department" options={departments} allowClear showSearch optionFilterProp="label" />
512
+ </Form.Item>
513
+ </Col>
514
+ <Col span={8}>
515
+ {/* Branch */}
516
+ <Form.Item label="Branches" name="selectedBranches" rules={[{ required: true, message: 'Please select at least one branch' }]}>
517
+ <Select
518
+ mode="multiple"
519
+ placeholder="Select Branches"
520
+ value={selectedBranches}
521
+ onChange={(value) => {
522
+ setSelectedBranches(value);
523
+
524
+ // ⬅NEW: remove defaultBranch if it’s not in selectedBranches
525
+ if (!value.includes(defaultBranch)) {
526
+ setDefaultBranch(undefined);
527
+ form.setFieldsValue({ defaultBranch: undefined });
528
+ }
529
+ }}
530
+ options={branchOptions}
531
+ allowClear
532
+ showSearch
533
+ optionFilterProp="label"
534
+ maxTagCount={5} // Show only 5 tags
535
+ maxTagPlaceholder={(omittedValues) => `+${omittedValues.length}`} // Show "+n"
536
+ />
537
+ </Form.Item>
538
+ </Col>
539
+ <Col span={8}>
540
+ {/* Default Branch */}
541
+ <Form.Item label="Default Branch" name="defaultBranch" rules={[{ required: true, message: 'Please select default branch' }]}>
542
+ <Select placeholder="Select Default Branch" onChange={setDefaultBranch}>
543
+ {branchOptions
544
+ .filter((opt) => selectedBranches.includes(opt.value))
545
+ .map((opt) => (
546
+ <Option key={opt.value} value={opt.value}>
547
+ {opt.label}
548
+ </Option>
549
+ ))}
550
+ </Select>
551
+ </Form.Item>
552
+ </Col>
553
+ </Row>
554
+ <Row gutter={16}>
555
+ <Col span={8}>
556
+ {formContent?.id ? (
557
+ <>
558
+ <Form.Item>
559
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
560
+ <Checkbox onChange={handleCheackChange} />
561
+ <span>Select the option if you want to change the password</span>
562
+ </div>
563
+ </Form.Item>
564
+
565
+ {isPasswordVisible && (
566
+ <Form.Item
567
+ name="password"
568
+ label="Password"
569
+ rules={[
570
+ { required: true, message: 'Please enter your password' },
571
+ { pattern: passwordRegex, message: passwordRegexMessage },
572
+ ]}
573
+ >
574
+ <Input.Password placeholder="Enter password" autoComplete="new-password" />
575
+ </Form.Item>
576
+ )}
577
+ </>
578
+ ) : (
579
+ <Form.Item
580
+ name="password"
581
+ label="Password"
582
+ rules={[
583
+ {
584
+ required: true,
585
+ message: 'Please enter your password',
586
+ },
587
+ {
588
+ pattern: new RegExp(passwordRegex),
589
+ message: passwordRegexMessage,
590
+ },
591
+ ]}
592
+ >
593
+ <Input.Password visibilityToggle={false} placeholder="Enter password" autoComplete="new-password" />
594
+ </Form.Item>
595
+ )}
596
+ </Col>
597
+ {/* </Form.Item> */}
598
+
599
+ {/* Path */}
600
+ {/* <Form.Item name="password" label="Password"
359
601
  rules={[
360
602
  {
361
603
  required: true,
@@ -368,25 +610,25 @@ const UserAdd = ({ model, callback, edit, history, formContent, match, additiona
368
610
  ]}>
369
611
  <Input.Password visibilityToggle={false} placeholder="Enter password" autoComplete='new-password' />
370
612
  </Form.Item> */}
371
- {/* Path Ends */}
372
-
373
-
374
- {/* Path */}
375
- <Form.Item name="user_group" label="User Group" required>
376
- <Input placeholder="Enter User Group" />
377
- </Form.Item>
613
+ {/* Path Ends */}
378
614
 
379
- <Form.Item name="mobile" label="Mobile" required={mobileRequired}>
380
- <Input placeholder="Enter Mobile" />
381
- </Form.Item>
615
+ {/* Path */}
616
+ <Col span={8}>
617
+ <Form.Item name="user_group" label="User Group" rules={[{ required: true, message: 'Please enter your user group' }]}>
618
+ <Input placeholder="Enter User Group" />
619
+ </Form.Item>
620
+ </Col>
382
621
 
383
- {props.ldap && (
384
- <>
385
- <Form.Item name="auth_type" label="auth_type">
386
- <Input placeholder="Enter auth_type" value={"LDAP"} disabled />
622
+ {/* <Form.Item name="mobile" label="Mobile" required={mobileRequired}>
623
+ <Input placeholder="Enter Mobile" />
624
+ </Form.Item> */}
387
625
 
626
+ {props?.ldap && (
627
+ <>
628
+ <Form.Item name="auth_type" label="auth_type">
629
+ <Input placeholder="Enter auth_type" value={'LDAP'} disabled />
388
630
 
389
- {/* <Select
631
+ {/* <Select
390
632
 
391
633
  placeholder="Auth Type"
392
634
  defaultValue={'LDAP'}
@@ -399,7 +641,7 @@ const UserAdd = ({ model, callback, edit, history, formContent, match, additiona
399
641
  </Option>
400
642
  </Select> */}
401
643
 
402
- {/* <div style={{ display: 'flex', justifyContent: 'space-between' }}>
644
+ {/* <div style={{ display: 'flex', justifyContent: 'space-between' }}>
403
645
 
404
646
  <div style={{ width: '40%' }}>
405
647
 
@@ -408,51 +650,63 @@ const UserAdd = ({ model, callback, edit, history, formContent, match, additiona
408
650
 
409
651
 
410
652
  </div> */}
411
- </Form.Item>
412
-
413
- {/* Path */}
414
- <Form.Item name="auth_user" label="User Name" required>
415
- <Input placeholder="Enter User Name" />
416
- </Form.Item>
417
- </>
418
- )}
419
-
420
-
421
- <Form.Item>
422
-
423
- <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
424
- <Switch
425
- disabled={disabled}
426
- // defaultChecked={view}
427
- onChange={changeView}
428
- checked={authentication}
429
- // disabled={disabled}
430
- defaultChecked
431
- // checkedChildren={<OrderedListOutlined />}
432
- // unCheckedChildren={<PicCenterOutlined />}
433
- />
434
- <span>Enable Two Factor Authentication</span>
435
-
436
- </div>
437
- </Form.Item>
438
- {/* Path Ends */}
439
-
440
- {/* Path */}
441
- {/* <Form.Item name="active" label="Active" required>
653
+ </Form.Item>
654
+
655
+ {/* Path */}
656
+ <Form.Item name="auth_user" label="User Name" required>
657
+ <Input placeholder="Enter User Name" />
658
+ </Form.Item>
659
+ </>
660
+ )}
661
+ </Row>
662
+ <Row gutter={16}>
663
+ <Col span={8}>
664
+ <Form.Item>
665
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
666
+ <Switch
667
+ disabled={disabled}
668
+ // defaultChecked={view}
669
+ onChange={changeView}
670
+ checked={authentication}
671
+ // disabled={disabled}
672
+ defaultChecked
673
+ // checkedChildren={<OrderedListOutlined />}
674
+ // unCheckedChildren={<PicCenterOutlined />}
675
+ />
676
+ <span>Enable Two Factor Authentication</span>
677
+ </div>
678
+ </Form.Item>
679
+ </Col>
680
+ <Col span={8}>
681
+ {/* <label>User Status</label> */}
682
+ <Form.Item
683
+ name="active"
684
+ valuePropName="checked"
685
+ getValueFromEvent={(e) => (e.target.checked ? true : false)}
686
+ getValueProps={(value) => ({ checked: value === true })}
687
+ style={{ marginBottom: 0 }}
688
+ >
689
+ <Checkbox>Active</Checkbox>
690
+ </Form.Item>
691
+ </Col>
692
+ </Row>
693
+ {/* Path Ends */}
694
+
695
+ {/* Path */}
696
+ {/* <Form.Item name="active" label="Active" required>
442
697
  <Switch />
443
698
  </Form.Item> */}
444
- {/* Path Ends */}
445
-
446
- <Form.Item>
447
- <Button loading={loading} htmlType={'submit'} type="primary">
448
- Submit
449
- </Button>
450
- </Form.Item>
451
- </Form>
452
- )
453
- }
454
- </section >
455
- );
699
+ {/* Path Ends */}
700
+
701
+ <Form.Item>
702
+ <Button loading={loading} htmlType={'submit'} type="primary">
703
+ Submit
704
+ </Button>
705
+ </Form.Item>
706
+ </Form>
707
+ )}
708
+ </section>
709
+ );
456
710
  };
457
711
 
458
712
  export default UserAdd;