ui-soxo-bootstrap-core 2.6.1-dev.2 → 2.6.1-dev.21

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 (63) hide show
  1. package/core/components/extra-info/extra-info-details.js +2 -2
  2. package/core/components/index.js +2 -11
  3. package/core/components/landing-api/landing-api.js +91 -15
  4. package/core/components/landing-api/landing-api.scss +22 -0
  5. package/core/components/license-management/license-alert.js +97 -0
  6. package/core/lib/Store.js +3 -3
  7. package/core/lib/components/global-header/global-header.js +2 -2
  8. package/core/lib/components/sidemenu/sidemenu.js +19 -13
  9. package/core/lib/components/sidemenu/sidemenu.scss +1 -1
  10. package/core/lib/elements/basic/country-phone-input/country-phone-input.js +14 -9
  11. package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +1 -1
  12. package/core/lib/elements/basic/menu-tree/menu-tree.js +26 -13
  13. package/core/lib/models/forms/components/form-creator/form-creator.scss +4 -3
  14. package/core/lib/models/menus/components/menu-list/menu-list.js +424 -467
  15. package/core/lib/models/process/components/process-dashboard/process-dashboard.js +469 -3
  16. package/core/lib/models/process/components/process-dashboard/process-dashboard.scss +4 -0
  17. package/core/lib/pages/change-password/change-password.js +17 -24
  18. package/core/lib/pages/change-password/change-password.scss +45 -48
  19. package/core/lib/pages/login/commnication-mode-selection.js +2 -2
  20. package/core/lib/pages/login/login.js +53 -64
  21. package/core/lib/pages/login/login.scss +9 -0
  22. package/core/lib/pages/login/reset-password.js +17 -17
  23. package/core/lib/pages/login/reset-password.scss +10 -1
  24. package/core/lib/pages/profile/themes.json +4 -4
  25. package/core/lib/utils/api/api.utils.js +30 -18
  26. package/core/lib/utils/common/common.utils.js +49 -35
  27. package/core/lib/utils/http/http.utils.js +2 -1
  28. package/core/lib/utils/index.js +4 -1
  29. package/core/models/base/base.js +7 -3
  30. package/core/models/core-scripts/core-scripts.js +134 -126
  31. package/core/models/doctor/components/doctor-add/doctor-add.js +9 -4
  32. package/core/models/menus/components/menu-add/menu-add.js +1 -1
  33. package/core/models/menus/components/menu-lists/menu-lists.js +53 -54
  34. package/core/models/menus/menus.js +27 -2
  35. package/core/models/roles/components/role-add/role-add.js +92 -59
  36. package/core/models/roles/components/role-list/role-list.js +1 -1
  37. package/core/models/staff/components/staff-add/staff-add.js +20 -32
  38. package/core/models/users/components/assign-role/assign-role.js +145 -50
  39. package/core/models/users/components/assign-role/assign-role.scss +209 -45
  40. package/core/models/users/components/assign-role/avatar-props.js +45 -0
  41. package/core/models/users/components/user-add/user-add.js +46 -55
  42. package/core/models/users/components/user-add/user-edit.js +25 -4
  43. package/core/models/users/users.js +9 -1
  44. package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.js +1 -1
  45. package/core/modules/reporting/components/reporting-dashboard/README.md +316 -0
  46. package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js +147 -0
  47. package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.scss +76 -0
  48. package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.js +90 -0
  49. package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.test.js +74 -0
  50. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.js +252 -0
  51. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.test.js +126 -0
  52. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +326 -436
  53. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.scss +7 -0
  54. package/core/modules/steps/action-buttons.js +30 -16
  55. package/core/modules/steps/action-buttons.scss +55 -9
  56. package/core/modules/steps/chat-assistant.js +141 -0
  57. package/core/modules/steps/openai-realtime.js +275 -0
  58. package/core/modules/steps/readme.md +167 -0
  59. package/core/modules/steps/steps.js +1078 -57
  60. package/core/modules/steps/steps.scss +539 -90
  61. package/core/modules/steps/timeline.js +21 -19
  62. package/core/modules/steps/voice-navigation.js +709 -0
  63. package/package.json +2 -1
@@ -30,7 +30,7 @@ import { getAccessToken, getRefreshToken } from '../../utils/http/auth.helper';
30
30
 
31
31
  import { Location } from '../../utils';
32
32
 
33
- import { checkLicenseStatus, formatMobile, safeJSON ,checkExpiryStatus} from '../../utils/common/common.utils';
33
+ import { checkLicenseStatus, formatMobile, safeJSON } from '../../utils/common/common.utils';
34
34
 
35
35
  import { MailOutlined, MessageOutlined, WhatsAppOutlined } from '@ant-design/icons';
36
36
 
@@ -50,11 +50,10 @@ const tailLayout = {
50
50
 
51
51
  const LICENSE_EXPIRY = '2026-12-12';
52
52
 
53
+
53
54
  const headers = {
54
55
  db_ptr: 'nuraho',
55
56
  };
56
- //password valdity expire
57
- const PASSWORD_VALIDITY_DAYS = 90;
58
57
 
59
58
  /**
60
59
  *
@@ -114,46 +113,32 @@ function LoginPhone({ history, appSettings }) {
114
113
  *
115
114
  * - Parses `last_password_change` from user.other_details.
116
115
  * - Calculates expiry using PASSWORD_VALIDITY_DAYS.
117
- * - Uses `checkExpiryStatus()` to determine status.
118
116
  * - Shows Ant Design warning message if expired or within warning period.
119
117
  * - Warning message includes navigation to `/change-password`.
120
118
  *
121
119
  * Requires:
122
120
  * - PASSWORD_VALIDITY_DAYS constant
123
- * - checkExpiryStatus utility
124
121
  * - React Router history
125
122
  * - antd message component
126
123
  */
127
- const handlePasswordExpiryCheck = (user) => {
128
- const otherDetails = user?.other_details ? JSON.parse(user.other_details) : null;
129
-
130
- const lastPasswordChange = otherDetails?.last_password_change;
131
-
132
- if (lastPasswordChange) {
133
- const passwordExpiryDate = new Date(lastPasswordChange);
134
- passwordExpiryDate.setDate(passwordExpiryDate.getDate() + PASSWORD_VALIDITY_DAYS);
135
-
136
- const passwordStatus = checkExpiryStatus({
137
- expiryDate: passwordExpiryDate,
138
- warningDays: 2,
139
- expiredMessage: 'Your password has expired. Please reset it.',
140
- warningMessage: (d) => (
141
- <span>
142
- Your password will expire in {d} day(s).{' '}
143
- <a
144
- onClick={() => {
145
- history.push('/change-password');
146
- }}
147
- >
148
- Click here to update.
149
- </a>
150
- </span>
151
- ),
152
- });
124
+ const handlePasswordExpiryCheck = (expiryDays) => {
125
+ if (expiryDays == null) return;
153
126
 
154
- if (passwordStatus.message) {
155
- message.warning(passwordStatus.message);
156
- }
127
+ if (expiryDays <= 0) {
128
+ message.error('Your password has expired. Please reset it.');
129
+
130
+ setExpiredPassword(true);
131
+ setShowResetpassword(true);
132
+
133
+ return;
134
+ }
135
+
136
+ if (expiryDays <= 2) {
137
+ message.warning(
138
+ <span>
139
+ Your password will expire in {expiryDays} day(s). <a onClick={() => history.push('/change-password')}>Click here to update.</a>
140
+ </span>
141
+ );
157
142
  }
158
143
  };
159
144
 
@@ -194,7 +179,7 @@ function LoginPhone({ history, appSettings }) {
194
179
  if (insider_token) localStorage.insider_token = insider_token;
195
180
 
196
181
  if (result.success) {
197
- handlePasswordExpiryCheck(user);
182
+ handlePasswordExpiryCheck(result.expiry_in_days);
198
183
 
199
184
  //two_factor_authentication variable is present then proceed Two factor authentication
200
185
  if (result.data && result.data.two_factor_authentication) {
@@ -321,6 +306,8 @@ function LoginPhone({ history, appSettings }) {
321
306
  *
322
307
  */
323
308
  const sendAuthenticationOtp = () => {
309
+ if (loading) return;
310
+
324
311
  // Reset previous error
325
312
  setModeError(false);
326
313
 
@@ -349,10 +336,10 @@ function LoginPhone({ history, appSettings }) {
349
336
  if (result.success) {
350
337
  // for expiry_time
351
338
  startFromExpiry(result?.expiry_time);
352
- // if the api is sucess then go for otpverification step
353
- setotpVerification(true);
354
339
  // set button loading false
355
340
  setLoading(false);
341
+ // if the api is sucess then go for otpverification step
342
+ setotpVerification(true);
356
343
  } else {
357
344
  setLoading(false);
358
345
  message.error(result.message);
@@ -409,7 +396,7 @@ function LoginPhone({ history, appSettings }) {
409
396
  if (result?.user?.organization_details) {
410
397
  const data = safeJSON(result?.user?.organization_details);
411
398
 
412
- const defaultBranch = data.branch.find((b) => b.defaultBranch === 'true');
399
+ const defaultBranch = data.branch.find((b) => b.defaultBranch === true);
413
400
  const defaultDbptr = defaultBranch?.dbPtr;
414
401
 
415
402
  localStorage.setItem('db_ptr', defaultDbptr);
@@ -419,7 +406,7 @@ function LoginPhone({ history, appSettings }) {
419
406
  // set user info into local storage
420
407
  localStorage.setItem('userInfo', JSON.stringify(userInfo));
421
408
 
422
- handlePasswordExpiryCheck(result.user);
409
+ handlePasswordExpiryCheck(result.expiry_in_days);
423
410
 
424
411
  setTimeout(() => history.push('/'), 500);
425
412
  } else {
@@ -460,6 +447,8 @@ function LoginPhone({ history, appSettings }) {
460
447
  * Otp resend Logic
461
448
  */
462
449
  const handleResendOTP = () => {
450
+ if (loading) return;
451
+
463
452
  setOtpValue('');
464
453
  setModeError(false);
465
454
  setOtpError(false);
@@ -622,28 +611,28 @@ function LoginPhone({ history, appSettings }) {
622
611
  return user.username;
623
612
  };
624
613
 
625
- const { globalCustomerHeader = () => {} } = appSettings;
614
+ const { globalCustomerHeader = () => { } } = appSettings;
626
615
 
627
616
  const themeName = process.env.REACT_APP_THEME; // e.g., 'purple'
628
617
  const isPurple = themeName === 'purple';
629
618
 
630
619
  const sectionStyle = isPurple
631
620
  ? {
632
- width: '100%',
633
- height: '100vh',
634
- backgroundImage: `${state.theme.colors.loginPageBackground}`,
635
- backgroundPosition: 'center bottom, center',
636
- backgroundRepeat: 'no-repeat, no-repeat',
637
- backgroundSize: 'cover, cover',
638
- }
621
+ width: '100%',
622
+ height: '100vh',
623
+ backgroundImage: `${state.theme.colors.loginPageBackground}`,
624
+ backgroundPosition: 'center bottom, center',
625
+ backgroundRepeat: 'no-repeat, no-repeat',
626
+ backgroundSize: 'cover, cover',
627
+ }
639
628
  : {
640
- width: '100%',
641
- height: '100vh',
642
- background: 'linear-gradient(to bottom, #F7F6E3 0%, #EEF1DE 20%, #D5E4DA 45%, #9DBFC8 75%, #4F89A6 100%)',
643
- backgroundPosition: 'center bottom, center',
644
- backgroundRepeat: 'no-repeat, no-repeat',
645
- backgroundSize: 'cover, cover',
646
- };
629
+ width: '100%',
630
+ height: '100vh',
631
+ background: 'linear-gradient(to bottom, #F7F6E3 0%, #EEF1DE 20%, #D5E4DA 45%, #9DBFC8 75%, #4F89A6 100%)',
632
+ backgroundPosition: 'center bottom, center',
633
+ backgroundRepeat: 'no-repeat, no-repeat',
634
+ backgroundSize: 'cover, cover',
635
+ };
647
636
 
648
637
  return (
649
638
  <section className="full-page" style={sectionStyle}>
@@ -729,7 +718,7 @@ function LoginPhone({ history, appSettings }) {
729
718
 
730
719
  {!otpVerification ? (
731
720
  <div className="otp-container">
732
- <Button type="primary" onClick={sendAuthenticationOtp} style={{ marginTop: '6px' }}>
721
+ <Button loading={loading} type="primary" onClick={sendAuthenticationOtp} style={{ marginTop: '6px' }}>
733
722
  Send OTP
734
723
  </Button>
735
724
  </div>
@@ -775,7 +764,7 @@ function LoginPhone({ history, appSettings }) {
775
764
  </div>
776
765
  </div>
777
766
  {!otpSuccess && (
778
- <Button type="primary" disabled={otpExpired} onClick={verifyOtp} style={{ marginTop: 16 }}>
767
+ <Button loading={loading} type="primary" disabled={otpExpired} onClick={verifyOtp} style={{ marginTop: 16 }}>
779
768
  Verify OTP
780
769
  </Button>
781
770
  )}
@@ -811,7 +800,7 @@ function LoginPhone({ history, appSettings }) {
811
800
  <Button loading={loading} type="primary" htmlType="submit" className="SubmitBtn">
812
801
  &nbsp;&nbsp; Submit
813
802
  </Button>
814
- <div className="forgot-password" style={{ marginTop: '8px', textAlign: 'center' }}>
803
+ <div className="forgot-password">
815
804
  <Link onClick={() => setShowResetpassword(true)}>Forgot Password?</Link>
816
805
  </div>
817
806
  </Form.Item>
@@ -827,13 +816,13 @@ function LoginPhone({ history, appSettings }) {
827
816
  setShowResetpassword(false);
828
817
  setExpiredPassword(false);
829
818
  }}
830
- title={expiredPassword ? 'Password Expired' : 'Forgot Password'}
831
- subtitle={
832
- expiredPassword
833
- ? 'Enter your username and choose your preferred OTP method to receive a reset link.'
834
- : 'Enter your username to reset your password and select your preferred OTP method.'
835
- }
836
- buttonText={expiredPassword ? 'Send Reset Link' : 'Reset Password'}
819
+ title={expiredPassword ? 'Password Expired!' : 'Forgot Password?'}
820
+ // subtitle={
821
+ // expiredPassword
822
+ // ? 'Your password has expired. Select a preferred communication method to receive the One-Time Password (OTP) to continue.'
823
+ // : 'Enter your username and Select a preferred communication method to receive the One-Time Password (OTP) to continue..'
824
+ // }
825
+ buttonText={expiredPassword ? 'Send Reset Link' : 'Send Reset Link'}
837
826
  />
838
827
  )}
839
828
  </div>
@@ -228,6 +228,15 @@ body {
228
228
  text-transform: capitalize;
229
229
  }
230
230
  }
231
+
232
+ .forgot-password {
233
+ margin-top: 8px;
234
+ text-align: center;
235
+
236
+ a {
237
+ color: #204b7e;
238
+ }
239
+ }
231
240
  }
232
241
  }
233
242
 
@@ -17,7 +17,7 @@
17
17
  * @param {boolean} disabledUserName - Disable username field
18
18
  */
19
19
 
20
- import React, { useState, useEffect } from 'react';
20
+ import React, { useState, useEffect, useRef } from 'react';
21
21
  import { Divider, Form, Input, message } from 'antd';
22
22
  import { Button } from '../../elements';
23
23
  import CommunicationModeSelection from './commnication-mode-selection';
@@ -36,6 +36,9 @@ function ResetPassword({ onBack, title, subtitle, buttonText, defaultUsername, d
36
36
 
37
37
  const [form] = Form.useForm();
38
38
 
39
+ // Ref to username input auto focus
40
+ const inputRef = useRef(null);
41
+
39
42
  // Pre-fills username if provided and disabled.
40
43
  useEffect(() => {
41
44
  if (disabledUserName && defaultUsername) {
@@ -43,6 +46,10 @@ function ResetPassword({ onBack, title, subtitle, buttonText, defaultUsername, d
43
46
  }
44
47
  }, [disabledUserName, defaultUsername]);
45
48
 
49
+ useEffect(() => {
50
+ inputRef.current?.focus();
51
+ }, []);
52
+
46
53
  /**
47
54
  * Sends forgot password request to backend.
48
55
  * Payload: { mode, username, user_type: 'staff' }
@@ -83,26 +90,20 @@ function ResetPassword({ onBack, title, subtitle, buttonText, defaultUsername, d
83
90
  return (
84
91
  <motion.div
85
92
  className="forgot-password-container"
86
- initial={{ opacity: 0, y: 70 }}
93
+ initial={{ opacity: 0, y: 30 }}
87
94
  animate={{ opacity: 1, y: 0 }}
88
- exit={{ opacity: 0, y: -50 }}
95
+ exit={{ opacity: 0, y: -20 }}
89
96
  transition={{
90
- y: {
91
- duration: 1,
92
- ease: [0.22, 0.08, 0.26, 1],
93
- },
94
- opacity: {
95
- duration: 0.45,
96
- ease: 'easeOut',
97
- },
97
+ duration: 0.30,
98
+ ease: 'easeOut',
98
99
  }}
99
100
  >
100
101
  <h3 className="password-title">{title}</h3>
101
- <p className="password-subtitle">{subtitle}</p>
102
- <Divider />
102
+ {/* <p className="password-subtitle">{subtitle}</p>
103
+ <Divider /> */}
103
104
  <Form layout="vertical" form={form} onFinish={handleSendForgetPassword}>
104
105
  <Form.Item label="Username" name="username" rules={[{ required: true, message: 'Please input your username' }]}>
105
- <Input placeholder="Enter your username" disabled={disabledUserName} />
106
+ <Input placeholder="Enter your username" disabled={disabledUserName} ref={inputRef}/>
106
107
  </Form.Item>
107
108
 
108
109
  <CommunicationModeSelection communicationMode={communicationMode} setCommunicationMode={setCommunicationMode} modeError={modeError} />
@@ -110,9 +111,8 @@ function ResetPassword({ onBack, title, subtitle, buttonText, defaultUsername, d
110
111
  <Button type="primary" htmlType="submit" loading={loading}>
111
112
  {buttonText}
112
113
  </Button>
113
-
114
- <div style={{ marginTop: '10px', textAlign: 'center' }}>
115
- <a style={{ cursor: 'pointer' }} onClick={handleBackToLogin}>
114
+ <div className="back-to-login">
115
+ <a onClick={handleBackToLogin}>
116
116
  Back to Login
117
117
  </a>
118
118
  </div>
@@ -18,5 +18,14 @@
18
18
  margin: 0;
19
19
  border-top: 1px solid #e5e7eb;
20
20
  }
21
- }
22
21
 
22
+ .back-to-login {
23
+ margin-top: 10px;
24
+ text-align: center;
25
+
26
+ a {
27
+ cursor: pointer;
28
+ color: #204b7e;
29
+ }
30
+ }
31
+ }
@@ -88,10 +88,10 @@
88
88
  "loginPageBackground": "linear-gradient(#D5F1FB, #24AEB8)",
89
89
  "bodyBackground": "#F0F6FF",
90
90
  "progressBar": "#24AEB8",
91
- "primaryButtonBg": "#446AA9",
91
+ "primaryButtonBg": "#204b7e",
92
92
  "primaryButtonHoverBg": "#2E4873",
93
93
  "primaryButtonText": "#FFFFFF",
94
- "primaryButtonActiveBg": "#446AA9",
94
+ "primaryButtonActiveBg": "#204b7e",
95
95
  "primaryButtonDisabledBg": "#C4C6CC",
96
96
  "primaryButtonDisabledText": "#6B7280",
97
97
 
@@ -104,14 +104,14 @@
104
104
 
105
105
  "dashedButtonBg": "#FFFFFF",
106
106
  "dashedButtonHoverBg": "#D1E3FF",
107
- "dashedButtonText": "#446AA9",
107
+ "dashedButtonText": "#204b7e",
108
108
  "dashedButtonActiveBg": "#B8C7FF",
109
109
  "dashedButtonDisabledBg": "#F0F6FF",
110
110
  "dashedButtonDisabledText": "#A9BCC6",
111
111
 
112
112
  "linkButtonBg": "transparent",
113
113
  "linkButtonHoverBg": "#F5F5F5",
114
- "linkButtonText": "#446AA9",
114
+ "linkButtonText": "#204b7e",
115
115
  "linkButtonActiveBg": "#D1E3FF",
116
116
  "linkButtonDisabledText": "#A9BCC6",
117
117
 
@@ -24,15 +24,15 @@ export default class ApiUtils {
24
24
  };
25
25
 
26
26
  static get = async ({ url, config = { queries: [], order: {} }, headers: customHeaders = {}, ...props }) => {
27
- const { headers: defaultHeaders } = settings;
27
+ const dbPtr = localStorage.getItem('db_ptr');
28
28
 
29
29
  try {
30
30
  return await GetData({
31
31
  url: createUrlParams(url, config),
32
32
  settings,
33
33
  headers: {
34
- ...defaultHeaders,
35
- // override here
34
+ ...(settings.headers || {}),
35
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
36
36
  ...customHeaders,
37
37
  },
38
38
  ...props,
@@ -43,15 +43,15 @@ export default class ApiUtils {
43
43
  };
44
44
 
45
45
  static getRecordDetail = async ({ url, config = { queries: [] }, headers: customHeaders = {}, ...props }) => {
46
- const { headers: defaultHeaders } = settings;
46
+ const dbPtr = localStorage.getItem('db_ptr');
47
47
 
48
48
  try {
49
49
  return await GetData({
50
50
  url: createUrlParams(url, config),
51
51
  settings,
52
52
  headers: {
53
- ...defaultHeaders,
54
- // override here
53
+ ...(settings.headers || {}),
54
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
55
55
  ...customHeaders,
56
56
  },
57
57
  ...props,
@@ -62,52 +62,64 @@ export default class ApiUtils {
62
62
  };
63
63
 
64
64
  static post = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
65
- const { headers: defaultHeaders } = settings;
65
+ const dbPtr = localStorage.getItem('db_ptr');
66
66
 
67
67
  return PostData({
68
68
  url,
69
69
  formBody,
70
70
  settings,
71
71
  headers: {
72
- ...defaultHeaders,
73
- // override here
72
+ ...(settings.headers || {}),
73
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
74
74
  ...customHeaders,
75
75
  },
76
76
  ...props,
77
77
  });
78
78
  };
79
79
 
80
- static put = ({ url, formBody, ...props }) => {
81
- const { headers } = settings;
80
+ static put = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
81
+ const dbPtr = localStorage.getItem('db_ptr');
82
82
 
83
83
  return PutData({
84
84
  url,
85
85
  settings,
86
86
  formBody,
87
- headers,
87
+ headers: {
88
+ ...(settings.headers || {}),
89
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
90
+ ...customHeaders,
91
+ },
88
92
  ...props,
89
93
  });
90
94
  };
91
95
 
92
- static patch = ({ url, formBody, ...props }) => {
93
- const { headers } = settings;
96
+ static patch = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
97
+ const dbPtr = localStorage.getItem('db_ptr');
94
98
 
95
99
  return PatchData({
96
100
  url,
97
101
  settings,
98
102
  formBody,
99
- headers,
103
+ headers: {
104
+ ...(settings.headers || {}),
105
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
106
+ ...customHeaders,
107
+ },
100
108
  ...props,
101
109
  });
102
110
  };
103
111
 
104
- static delete = ({ url, formBody, ...props }) => {
105
- const { headers } = settings;
112
+ static delete = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
113
+ const dbPtr = localStorage.getItem('db_ptr');
106
114
 
107
115
  return DeleteData({
108
116
  url,
109
117
  settings,
110
- headers,
118
+ headers: {
119
+ ...(settings.headers || {}),
120
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
121
+ ...customHeaders,
122
+ },
111
123
  ...props,
112
124
  });
113
125
  };
@@ -4,6 +4,7 @@ Implements utility functions to be used across project
4
4
 
5
5
  /*eslint no-useless-escape:"off",eqeqeq: "off"*/
6
6
  import moment from 'moment';
7
+ import { parsePhoneNumberFromString, isValidPhoneNumber } from 'libphonenumber-js';
7
8
 
8
9
  export function IsObjectHaveKeys(obj) {
9
10
  return obj && typeof obj == 'object' && Object.keys(obj).length;
@@ -122,41 +123,6 @@ export const checkLicenseStatus = (expiryDate) => {
122
123
  return { valid: true, daysLeft, message: null, level: null };
123
124
  };
124
125
 
125
- /**
126
- * Checks password expiry status.
127
- *
128
- * @param {string|Date} expiryDate
129
- * @param {number} warningDays
130
- * @param {string} expiredMessage
131
- * @param {(daysLeft: number) => string} warningMessage
132
- *
133
- * @returns {{ valid: boolean, daysLeft: number, message: string|null, level: "error"|"warning"|null }}
134
- */
135
-
136
- export const checkExpiryStatus = ({ expiryDate, warningDays, expiredMessage, warningMessage }) => {
137
- const expiry = new Date(expiryDate);
138
-
139
- if (isNaN(expiry)) {
140
- return { valid: false, daysLeft: 0, message: 'Invalid date', level: 'error' };
141
- }
142
-
143
- expiry.setHours(0, 0, 0, 0);
144
- const today = new Date();
145
- today.setHours(0, 0, 0, 0);
146
-
147
- const msDiff = expiry.getTime() - today.getTime();
148
- const daysLeft = Math.ceil(msDiff / (1000 * 60 * 60 * 24));
149
-
150
- if (daysLeft < 0) {
151
- return { valid: false, daysLeft, message: expiredMessage, level: 'error' };
152
- }
153
-
154
- if (daysLeft <= warningDays) {
155
- return { valid: true, daysLeft, message: warningMessage(daysLeft), level: 'warning' };
156
- }
157
-
158
- return { valid: true, daysLeft, message: null, level: null };
159
- };
160
126
 
161
127
  /**
162
128
  * Masks a mobile number by hiding all but the last `visibleDigits`.
@@ -221,3 +187,51 @@ export function safeJSON(value) {
221
187
  return null;
222
188
  }
223
189
  }
190
+
191
+ /**
192
+ * Convert +countrycode phone into form compatible structure
193
+ * @param {string} phone
194
+ * @returns {object|null}
195
+ */
196
+ export const formatPhoneForForm = (phone) => {
197
+ if (!phone) return null;
198
+
199
+ const parsed = parsePhoneNumberFromString(phone);
200
+
201
+ if (!parsed) return null;
202
+
203
+ return {
204
+ value: parsed.nationalNumber,
205
+ code: {
206
+ dialCode: parsed.countryCallingCode,
207
+ countryCode: parsed.country?.toLowerCase(),
208
+ },
209
+ valid: true,
210
+ };
211
+ };
212
+
213
+ /**
214
+ * Validates a phone number from CountryPhoneInput.
215
+ * Builds full number using country dial code and checks validity.
216
+ *
217
+ * @param {Object} _ - Ant Design rule parameter (unused)
218
+ * @param {Object} val - Phone value object from form
219
+ * @returns {Promise<void>}
220
+ */
221
+ export const phoneValidator = (_, val) => {
222
+ if (!val || !val.value || !val?.code?.dialCode) {
223
+ return Promise.resolve();
224
+ }
225
+
226
+ const fullPhone = `+${val.code.dialCode}${val.value}`;
227
+
228
+ return isValidPhoneNumber(fullPhone) ? Promise.resolve() : Promise.reject('Invalid mobile number');
229
+ };
230
+
231
+ // Returns phone number with country code (e.g., +919876543210)
232
+ export const formatPhoneWithCountryCode = (phone) => {
233
+ if (phone && typeof phone === 'object' && phone.code) {
234
+ return `+${phone.code.dialCode}${phone.value}`;
235
+ }
236
+ return phone;
237
+ };
@@ -82,7 +82,7 @@ export async function ApiCall({ url, formBody, method, settings, ...props }) {
82
82
  ...settings.headers,
83
83
  ...headers,
84
84
  ...(props.headers || {}),
85
- Authorization: `Bearer ${token}`,
85
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
86
86
  'Content-Type': 'application/json',
87
87
  },
88
88
  body: formBody ? JSON.stringify(formBody) : null,
@@ -153,5 +153,6 @@ export async function ApiCall({ url, formBody, method, settings, ...props }) {
153
153
  return result;
154
154
  } catch (err) {
155
155
  console.error('Login error -->', err?.message);
156
+ throw err;
156
157
  }
157
158
  }
@@ -14,7 +14,7 @@ import { GetData, PostData, PutData, DeleteData } from './http/http.utils';
14
14
 
15
15
  import { getExportData } from './generic/generic.utils';
16
16
 
17
- import { ConvertBytesToArray, safeJSON } from './common/common.utils';
17
+ import { ConvertBytesToArray, safeJSON, formatPhoneForForm, phoneValidator, formatPhoneWithCountryCode } from './common/common.utils';
18
18
 
19
19
  import SettingsUtil from './setting.utils';
20
20
 
@@ -37,4 +37,7 @@ export {
37
37
  SettingsUtil,
38
38
  FormUtils,
39
39
  safeJSON,
40
+ formatPhoneForForm,
41
+ phoneValidator,
42
+ formatPhoneWithCountryCode,
40
43
  };
@@ -88,9 +88,13 @@ class BaseAPI {
88
88
  * Get the data from the table
89
89
  */
90
90
  get(config = {}) {
91
- // Get the records from firebase
92
-
93
- return ApiUtils.get({ url: config.url || this.endpoint, config });
91
+ const { url, headers, ...rest } = config;
92
+ return ApiUtils.get({
93
+ url: url || this.endpoint,
94
+ headers,
95
+ config: rest,
96
+ ...rest,
97
+ });
94
98
  }
95
99
 
96
100
  getRelations(id) {