@argusoft/medplat-app-shell 1.0.5 → 1.0.7

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 (263) hide show
  1. package/package.json +139 -141
  2. package/src/GlobalErrorBoundary.jsx +31 -0
  3. package/src/SilentErrorFallback.jsx +68 -0
  4. package/src/TrackingProviderWrapper.jsx +40 -0
  5. package/src/_tests_/__mocks__/MockTranslationProvider.jsx +21 -0
  6. package/src/_tests_/__mocks__/ckeditor.js +45 -0
  7. package/src/_tests_/__mocks__/fileMock.js +1 -0
  8. package/src/_tests_/__mocks__/useranalytics.js +5 -0
  9. package/src/_tests_/views/components/Dashboard/DashboardUI.test.jsx +137 -0
  10. package/src/_tests_/views/components/Dashboard/DashboardUIMock.js +877 -0
  11. package/src/_tests_/views/components/ForgotPassword/ForgotPassword.test.jsx +314 -0
  12. package/src/_tests_/views/components/LocationDirective/LocationDirective.test.jsx.disable +229 -0
  13. package/src/_tests_/views/components/LocationDirective/mockLocationDirective.js +810 -0
  14. package/src/_tests_/views/components/LocationType/MockLocationType.js +42259 -0
  15. package/src/_tests_/views/components/LocationType/addlocationtype.test.jsx.disable +276 -0
  16. package/src/_tests_/views/components/LocationType/editlocationtype.test.jsx.disable +262 -0
  17. package/src/_tests_/views/components/LocationType/locationtype.test.jsx.disable +148 -0
  18. package/src/_tests_/views/components/Profile/UpdateProfileModalData.js +4396 -0
  19. package/src/_tests_/views/components/Profile/updateprofilemodal.test.jsx +282 -0
  20. package/src/_tests_/views/components/SideBar/MockSideBar.js +1379 -0
  21. package/src/_tests_/views/components/SideBar/SideBar.test.jsx +98 -0
  22. package/src/_tests_/views/components/SystemConfig/ManageSystemConfig/AddManageSystemConfig.test.jsx.disable +164 -0
  23. package/src/_tests_/views/components/SystemConfig/ManageSystemConfig/UpdateManageSystemConfig.test.jsx.disable +157 -0
  24. package/src/_tests_/views/components/SystemConfig/MockSystemConfig.js +1280 -0
  25. package/src/_tests_/views/components/SystemConfig/SystemConfig.test.jsx.disable +165 -0
  26. package/src/_tests_/views/components/login/Login.test.jsx +276 -0
  27. package/src/_tests_/views/components/login/MockAuthorise.js +2414 -0
  28. package/src/_tests_/views/components/login/ServiceResponse.js +595 -0
  29. package/src/_tests_/views/components/user/MockManageUser.js +7965 -0
  30. package/src/_tests_/views/components/user/manageuser.test.jsx.disable +989 -0
  31. package/src/_tests_/views/components/user/mockUsersData.js +582 -0
  32. package/src/assets/img/OASISLogin.png +0 -0
  33. package/src/assets/img/bahaarNew.png +0 -0
  34. package/src/assets/img/dnhdd4K.png +0 -0
  35. package/src/assets/img/govtofup.png +0 -0
  36. package/src/assets/img/sewarural4K.png +0 -0
  37. package/src/assets/img/techo4K.png +0 -0
  38. package/src/assets/img/up4K.png +0 -0
  39. package/src/common/HolidayList.jsx +573 -0
  40. package/src/common/MalaciaousInputUtil.js +23 -0
  41. package/src/common/SafeHtml.jsx +17 -0
  42. package/src/common/VersionManager.jsx +109 -0
  43. package/src/common/constants/PerformanceDashboard.js +514 -0
  44. package/src/common/constants/app.constant.js +781 -0
  45. package/src/common/constants/cccVerificationConstants.js +18 -0
  46. package/src/common/constants/fhsrConstant.js +33 -0
  47. package/src/common/constants/gvk-verification.constant.js +76 -0
  48. package/src/common/constants/search.constant.js +23 -0
  49. package/src/common/constants/teleconsulatationConstant.jsx +1339 -0
  50. package/src/common/directives/SearchTemplate.jsx +784 -0
  51. package/src/common/directives/SearchTemplate.scss +14 -0
  52. package/src/common/dynamicView/DynamicView.jsx +353 -0
  53. package/src/common/dynamicView/InputFieldComponent.jsx +1501 -0
  54. package/src/common/dynamicView/InputViewComponent.jsx +298 -0
  55. package/src/common/dynamicView/InputViewComponent.scss +15 -0
  56. package/src/common/env.js +5 -0
  57. package/src/common/filters/locationNameFilter.js +26 -0
  58. package/src/common/fontAwesomeIcons/FontAwesomeIcons.jsx +27 -0
  59. package/src/common/fontAwesomeIcons/FontAwesomeIconsNames.js +1968 -0
  60. package/src/common/fontPreferences/fontSizeProvider.jsx +34 -0
  61. package/src/common/fontPreferences/fontSizeSelector.jsx +116 -0
  62. package/src/common/getAssignedFeature/getAssignedFeature.js +32 -0
  63. package/src/common/interceptors/AxiosInterceptor.js +216 -0
  64. package/src/common/languageTranslator/TranslationContext.js +5 -0
  65. package/src/common/languageTranslator/TranslationProvider.jsx +24 -0
  66. package/src/common/languageTranslator/i18n.js +49 -0
  67. package/src/common/services/AuthenticateService.js +116 -0
  68. package/src/common/services/DownloadFile.js +35 -0
  69. package/src/common/services/ForgotPassword.js +18 -0
  70. package/src/common/services/FormConfiguratorService.js +195 -0
  71. package/src/common/services/GlobalApis.js +84 -0
  72. package/src/common/services/InterceptorNavigationService.js +17 -0
  73. package/src/common/services/LocationService.js +65 -0
  74. package/src/common/services/LocationType.js +11 -0
  75. package/src/common/services/QueryBuilder.js +36 -0
  76. package/src/common/services/Roles.js +28 -0
  77. package/src/common/services/SyncWithServer.js +15 -0
  78. package/src/common/services/SystemConfig.js +15 -0
  79. package/src/common/services/TranslationService.js +70 -0
  80. package/src/common/services/TwoFactorService.js +7 -0
  81. package/src/common/services/Users.js +91 -0
  82. package/src/common/services/Webtasks.js +27 -0
  83. package/src/common/services/util/Convert-pad-data-to-API-format.jsx +167 -0
  84. package/src/common/services/util/Convert-to-UI-format.jsx +82 -0
  85. package/src/common/services/util/EmptyPrescriptionPadData.jsx +11 -0
  86. package/src/common/services/util/GeneralUtil.js +456 -0
  87. package/src/common/services/util/Prescription-pad-util.js +339 -0
  88. package/src/common/services/util/PrescriptionPadData.js +67 -0
  89. package/src/common/services/util/PrescriptionpadCommonUtil.js +96 -0
  90. package/src/common/services/util/ReportFieldUtil.jsx +398 -0
  91. package/src/common/services/util/WebSocketContext.jsx +261 -0
  92. package/src/common/syncWithServer/SyncWithServerDialog.jsx +170 -0
  93. package/src/common/syncWithServer/SyncWithServerDialogSkeleton.jsx +67 -0
  94. package/src/common/tests/CustomWrapper.jsx +49 -0
  95. package/src/common/tests/TranslationWrapper.jsx +38 -0
  96. package/src/common/themeProvider/ColorInputs.jsx +97 -0
  97. package/src/common/themeProvider/EditableColorInput.jsx +128 -0
  98. package/src/common/themeProvider/ThemeEditor.jsx +319 -0
  99. package/src/common/themeProvider/ThemeProvider.jsx +210 -0
  100. package/src/common/themeProvider/themeConfig.js +558 -0
  101. package/src/common/toaster/toaster.jsx +30 -0
  102. package/src/firebaseConfig.js +24 -0
  103. package/src/global.scss +221 -0
  104. package/src/hooks/.gitkeep +0 -0
  105. package/src/hooks/useAESEncryption.js +56 -0
  106. package/src/hooks/useCaching.js +43 -0
  107. package/src/hooks/useDebounce.js +34 -0
  108. package/src/hooks/useDebounceFn.js +50 -0
  109. package/src/hooks/useDownloadPdf.js +358 -0
  110. package/src/hooks/useDownloadXlsx.js +55 -0
  111. package/src/hooks/useListValueFieldValues.js +30 -0
  112. package/src/hooks/useLocationHierarchies.js +63 -0
  113. package/src/hooks/useLocationHierarchyTranslate.js +16 -0
  114. package/src/hooks/useOnline.js +27 -0
  115. package/src/hooks/usePagination.js +63 -0
  116. package/src/hooks/useRefreshToken.js +87 -0
  117. package/src/hooks/useScript.js +25 -0
  118. package/src/hooks/useStopwatch.js +75 -0
  119. package/src/hooks/useTrackEvent.js +22 -0
  120. package/src/hooks/useWebAudioRecorder.js +115 -0
  121. package/src/layout/LoaderComponet.jsx +22 -0
  122. package/src/layout/LoaderContext.jsx +29 -0
  123. package/src/layout/mainLayout/AdaptiveZoom.jsx +27 -0
  124. package/src/layout/mainLayout/Chatbot.jsx +243 -0
  125. package/src/layout/mainLayout/Layout.jsx +445 -0
  126. package/src/layout/mainLayout/Profile/UpdateProfileModal.jsx +684 -0
  127. package/src/layout/mainLayout/header/LogoutModal.jsx +131 -0
  128. package/src/layout/mainLayout/header/Navbar.jsx +1677 -0
  129. package/src/layout/mainLayout/header/Navbar.scss +4 -0
  130. package/src/layout/mainLayout/header/index.js +0 -0
  131. package/src/layout/mainLayout/sidebar/SideBar.jsx +1402 -0
  132. package/src/layout/mainLayout/sidebar/Sidebar.css +159 -0
  133. package/src/layout/mainLayout/sidebar/index.js +0 -0
  134. package/src/logo.svg +1 -0
  135. package/src/reportWebVitals.js +13 -0
  136. package/src/setupFirebaseMessaging.js +28 -0
  137. package/src/setupTests.js +8 -0
  138. package/src/store/actions/AuthenticationActions.js +0 -0
  139. package/src/store/actions/ReportsActions.js +0 -0
  140. package/src/store/actions/TranslationAction.js +0 -0
  141. package/src/store/index.js +8 -0
  142. package/src/store/reducer.js +46 -0
  143. package/src/store/reducers/AuthenticationReducer.js +50 -0
  144. package/src/store/reducers/CalendarEventReducer.js +41 -0
  145. package/src/store/reducers/ConditionClipboardReducer.js +45 -0
  146. package/src/store/reducers/FeatureReducer.js +27 -0
  147. package/src/store/reducers/FormConfiguratorReducer.js +38 -0
  148. package/src/store/reducers/LoadingReducer.js +20 -0
  149. package/src/store/reducers/MembersAuthenticationReducer.js +28 -0
  150. package/src/store/reducers/PrescriptionPadReducer.js +329 -0
  151. package/src/store/reducers/QuestionaireReducer.js +29 -0
  152. package/src/store/reducers/ReportsReducer.js +24 -0
  153. package/src/store/reducers/SkeletonReducer.js +20 -0
  154. package/src/store/reducers/ThemeReducer.js +106 -0
  155. package/src/store/reducers/TranslationReducer.js +126 -0
  156. package/src/store/reducers/dashboardEditorSlice.js +77 -0
  157. package/src/store/reducers/districtHealthDashboardSlice.js +58 -0
  158. package/src/store/reducers/immunizationSlice.js +234 -0
  159. package/src/store/slices/dashboardPagesSlice.js +51 -0
  160. package/src/utils/.gitkeep +0 -0
  161. package/src/utils/FormConstants.js +2629 -0
  162. package/src/utils/GujaratTopoChart.jsx +483 -0
  163. package/src/utils/UUIDgenerator.js +8 -0
  164. package/src/utils/appointment-utils/appointment-utils.js +123 -0
  165. package/src/utils/feature.js +42 -0
  166. package/src/utils/getThemeColor.js +12 -0
  167. package/src/utils/localStorageHelper.js +11 -0
  168. package/src/utils/notifications/enable-push-notifications.js +27 -0
  169. package/src/utils/resolveAppliedStyle.js +11 -0
  170. package/src/utils/themeConfigs.js +1483 -0
  171. package/src/views/custom-components/.gitkeep +0 -0
  172. package/src/views/custom-components/AgIconButton/RIf.jsx +14 -0
  173. package/src/views/custom-components/AgIconButton/button.jsx +108 -0
  174. package/src/views/custom-components/AgIconButton/waterDrop.jsx +95 -0
  175. package/src/views/custom-components/AgIconButton/waterDrop.scss +37 -0
  176. package/src/views/custom-components/AlertPlaceholder.jsx +32 -0
  177. package/src/views/custom-components/AllFaIconsSelector.jsx +56 -0
  178. package/src/views/custom-components/CkEditor/CkEditor.js +102 -0
  179. package/src/views/custom-components/CustomAccordion.jsx +72 -0
  180. package/src/views/custom-components/CustomActionIcons.jsx +118 -0
  181. package/src/views/custom-components/CustomAutoComplete.jsx +188 -0
  182. package/src/views/custom-components/CustomCheckBox.jsx +60 -0
  183. package/src/views/custom-components/CustomConfirmationModal.jsx +118 -0
  184. package/src/views/custom-components/CustomCountrySelect.jsx +129 -0
  185. package/src/views/custom-components/CustomDatePicker.jsx +122 -0
  186. package/src/views/custom-components/CustomDropdown.jsx +191 -0
  187. package/src/views/custom-components/CustomFileUpload.jsx +387 -0
  188. package/src/views/custom-components/CustomFullCalendar.jsx +514 -0
  189. package/src/views/custom-components/CustomInfiniteScroll.jsx +126 -0
  190. package/src/views/custom-components/CustomRadioComponent.jsx +65 -0
  191. package/src/views/custom-components/CustomStatsComponent.jsx +114 -0
  192. package/src/views/custom-components/CustomSvgUpload.jsx +170 -0
  193. package/src/views/custom-components/CustomSwitch.jsx +37 -0
  194. package/src/views/custom-components/CustomTabPanel.jsx +19 -0
  195. package/src/views/custom-components/CustomTextArea.jsx +62 -0
  196. package/src/views/custom-components/CustomTextArea.scss +27 -0
  197. package/src/views/custom-components/CustomTextField.jsx +116 -0
  198. package/src/views/custom-components/CustomToggleSwitch.jsx +138 -0
  199. package/src/views/custom-components/CustomTooltip.jsx +51 -0
  200. package/src/views/custom-components/CustomZoomImage.jsx +134 -0
  201. package/src/views/custom-components/CustomizedTable/CustomizedTableV2.jsx +1407 -0
  202. package/src/views/custom-components/CustomizedTable/VirtualizeTableBody.jsx +295 -0
  203. package/src/views/custom-components/CustomizedTable/helper.jsx +159 -0
  204. package/src/views/custom-components/CustomizedTable.jsx +532 -0
  205. package/src/views/custom-components/EditInputField.jsx +174 -0
  206. package/src/views/custom-components/FieldDescription.jsx +22 -0
  207. package/src/views/custom-components/FileDisplayComponent.jsx +138 -0
  208. package/src/views/custom-components/FormItem.jsx +53 -0
  209. package/src/views/custom-components/GenericChart.jsx +80 -0
  210. package/src/views/custom-components/InfoBadge.jsx +60 -0
  211. package/src/views/custom-components/PostgresEditor.jsx +801 -0
  212. package/src/views/custom-components/ResizableEditAutocompleteField.jsx +249 -0
  213. package/src/views/custom-components/ResizableEditInputField.jsx +215 -0
  214. package/src/views/custom-components/ResizeableEditSelectField.jsx +197 -0
  215. package/src/views/custom-components/SideOverlay.jsx +113 -0
  216. package/src/views/custom-components/SideOverlay.scss +42 -0
  217. package/src/views/custom-components/calendar.scss +571 -0
  218. package/src/views/feature-components/.gitkeep +0 -0
  219. package/src/views/feature-components/Dashboard/DashboardUI.jsx +1043 -0
  220. package/src/views/feature-components/Dashboard/DhnddModal/AshaDataQualityVerificationModal.jsx +278 -0
  221. package/src/views/feature-components/Dashboard/PinFeatureModal.jsx +143 -0
  222. package/src/views/feature-components/Dashboard/QuickLinks.jsx +163 -0
  223. package/src/views/feature-components/Dashboard/Taskbar.jsx +56 -0
  224. package/src/views/feature-components/Dashboard/WebtasksFilterForm.jsx +109 -0
  225. package/src/views/feature-components/Dashboard/WidgetCard.jsx +161 -0
  226. package/src/views/feature-components/Dashboard/actionModal.jsx +263 -0
  227. package/src/views/feature-components/Dashboard/ekavachModal/HealthWorkerIncorrectDetailsModal.jsx +332 -0
  228. package/src/views/feature-components/Dashboard/ekavachModal/MoMaternalDeathVerifcationModal.jsx +275 -0
  229. package/src/views/feature-components/Dashboard/ekavachModal/MoVerficationForChildScreeningMoadal.jsx +566 -0
  230. package/src/views/feature-components/FeatureUsageAnalytics/FeatureUsageAnalytics.jsx +989 -0
  231. package/src/views/feature-components/Features/NewServerManagement.jsx +217 -0
  232. package/src/views/feature-components/Features/ServerManagement.scss +120 -0
  233. package/src/views/feature-components/ForgotPassword/ForgotPassword.jsx +226 -0
  234. package/src/views/feature-components/LocationDirective/LocationDirective.jsx +992 -0
  235. package/src/views/feature-components/LocationDirective/LocationDirectiveV2.jsx +909 -0
  236. package/src/views/feature-components/NotFound.jsx +66 -0
  237. package/src/views/feature-components/Onboarding/Onboarding.jsx +1400 -0
  238. package/src/views/feature-components/Skeletons.js +115 -0
  239. package/src/views/feature-components/Unauthorized.jsx +48 -0
  240. package/src/views/feature-components/VerifyRoute.jsx +88 -0
  241. package/src/views/feature-components/YearlyRecap/YearlyRecap.jsx +357 -0
  242. package/src/views/feature-components/YearlyRecap/components/RecapSlide.jsx +183 -0
  243. package/src/views/feature-components/YearlyRecap/languageTranslator/TranslationContext.js +5 -0
  244. package/src/views/feature-components/YearlyRecap/languageTranslator/TranslationProvider.jsx +26 -0
  245. package/src/views/feature-components/YearlyRecap/languageTranslator/i18n.js +46 -0
  246. package/src/views/feature-components/YearlyRecap/languageTranslator/translations.json +167 -0
  247. package/src/views/feature-components/YearlyRecap/slides/IntroSlide.jsx +233 -0
  248. package/src/views/feature-components/YearlyRecap/slides/MaternalHealthSlide.jsx +146 -0
  249. package/src/views/feature-components/YearlyRecap/slides/MetricSlide.jsx +227 -0
  250. package/src/views/feature-components/YearlyRecap/slides/OutroSlide.jsx +701 -0
  251. package/src/views/feature-components/YearlyRecap/slides/ReachSlide.jsx +273 -0
  252. package/src/views/feature-components/login/Login.jsx +840 -0
  253. package/src/views/feature-components/login/Login.scss +154 -0
  254. package/src/views/feature-components/login/LoginConfigurator.jsx +1149 -0
  255. package/src/views/feature-components/login/TwoFactorSetupModal.jsx +411 -0
  256. package/src/views/feature-components/login/simplifyMenu.js +45 -0
  257. package/src/views/feature-components/system-config/ManageSystemConfigs.jsx +284 -0
  258. package/src/views/feature-components/system-config/SystemConfig.jsx +299 -0
  259. package/src/views/feature-components/users/ChangePasswordModal.jsx +243 -0
  260. package/src/views/feature-components/users/PasswordField.jsx +56 -0
  261. package/dist/index.css +0 -1
  262. package/dist/index.js +0 -32001
  263. package/dist/index.js.map +0 -1
@@ -0,0 +1,34 @@
1
+ import PropTypes from 'prop-types';
2
+ import { createContext, useContext, useEffect, useMemo, useState } from 'react';
3
+
4
+ const FontSizeContext = createContext();
5
+
6
+ export const FontSizeProvider = ({ children }) => {
7
+ const storedFontSize = Number(localStorage.getItem('fontSize')) || 2; // Default to "Medium"
8
+ const [fontSize, setFontSize] = useState(storedFontSize);
9
+
10
+ useEffect(() => {
11
+ let root = document.documentElement;
12
+
13
+ const fontSizeValues = {
14
+ 1: 14, // px
15
+ 2: 16,
16
+ 3: 18,
17
+ 4: 20,
18
+ };
19
+ const baseSize = fontSizeValues[fontSize];
20
+ root.style.setProperty('--base-font-size', `${baseSize}px`);
21
+
22
+ localStorage.setItem('fontSize', fontSize.toString());
23
+ }, [fontSize]);
24
+
25
+ const contextValue = useMemo(() => ({ fontSize, setFontSize }), [fontSize]);
26
+
27
+ return <FontSizeContext.Provider value={contextValue}>{children}</FontSizeContext.Provider>;
28
+ };
29
+
30
+ FontSizeProvider.propTypes = {
31
+ children: PropTypes.node,
32
+ };
33
+
34
+ export const useFontSize = () => useContext(FontSizeContext);
@@ -0,0 +1,116 @@
1
+ import { Box, Typography } from '@mui/material';
2
+ import { alpha, useTheme } from '@mui/material/styles';
3
+ import { useFontSize } from './fontSizeProvider';
4
+
5
+ const FontSizeSelectorWrapper = () => {
6
+ const { fontSize, setFontSize } = useFontSize();
7
+ const theme = useTheme();
8
+ const isDark = theme.palette.mode === 'dark';
9
+
10
+ const fontSizeArray = [
11
+ { id: 1, label: 'Small', size: 'text-[12px]' },
12
+ { id: 2, label: 'Medium', size: 'text-[14px]' },
13
+ { id: 3, label: 'Large', size: 'text-[16px]' },
14
+ { id: 4, label: 'Extra Large', size: 'text-[18px]' },
15
+ ];
16
+
17
+ const activeFont = fontSizeArray[fontSize - 1] || fontSizeArray[1];
18
+
19
+ return (
20
+ <Box
21
+ sx={{
22
+ mx: 2,
23
+ mb: 1.2,
24
+ p: 1.35,
25
+ borderRadius: '16px',
26
+ border: `1px solid ${theme.palette.custom?.shellBorder}`,
27
+ background: isDark ? alpha('#fff', 0.03) : alpha('#0f172a', 0.025),
28
+ }}
29
+ >
30
+ <Box className="flex items-start justify-between gap-3">
31
+ <Box>
32
+ <Typography variant="body2" sx={{ fontWeight: 700, color: theme.palette.text.primary }}>
33
+ Font Size
34
+ </Typography>
35
+ </Box>
36
+ <Box
37
+ sx={{
38
+ px: 0.95,
39
+ py: 0.35,
40
+ borderRadius: '999px',
41
+ background: isDark
42
+ ? alpha(theme.palette.custom?.shellAccent || '#4da8da', 0.18)
43
+ : alpha(theme.palette.custom?.shellAccent || '#1c6fb7', 0.1),
44
+ color: theme.palette.text.primary,
45
+ fontSize: '0.68rem',
46
+ fontWeight: 700,
47
+ }}
48
+ >
49
+ {activeFont.label}
50
+ </Box>
51
+ </Box>
52
+
53
+ <Box
54
+ sx={{
55
+ mt: 1,
56
+ display: 'grid',
57
+ gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
58
+ gap: 0.8,
59
+ }}
60
+ >
61
+ {fontSizeArray.map((option) => {
62
+ const isActive = option.id === fontSize;
63
+
64
+ return (
65
+ <Box
66
+ key={option.id}
67
+ component="button"
68
+ type="button"
69
+ onClick={() => setFontSize(option.id)}
70
+ sx={{
71
+ border: 'none',
72
+ textAlign: 'left',
73
+ p: 1,
74
+ borderRadius: '12px',
75
+ cursor: 'pointer',
76
+ transition: 'all 180ms ease',
77
+ background: isActive
78
+ ? isDark
79
+ ? alpha(theme.palette.custom?.shellAccent || '#4da8da', 0.2)
80
+ : alpha(theme.palette.custom?.shellAccent || '#1c6fb7', 0.12)
81
+ : isDark
82
+ ? alpha('#fff', 0.04)
83
+ : alpha('#0f172a', 0.03),
84
+ color: theme.palette.text.primary,
85
+ boxShadow: isActive
86
+ ? isDark
87
+ ? '0 10px 22px rgba(2, 8, 23, 0.22)'
88
+ : '0 10px 22px rgba(148, 163, 184, 0.16)'
89
+ : 'none',
90
+ '&:hover': {
91
+ background: isDark
92
+ ? alpha(theme.palette.custom?.shellAccent || '#4da8da', isActive ? 0.24 : 0.12)
93
+ : alpha(theme.palette.custom?.shellAccent || '#1c6fb7', isActive ? 0.14 : 0.08),
94
+ },
95
+ }}
96
+ >
97
+ <Typography
98
+ sx={{
99
+ fontWeight: 700,
100
+ fontSize: '0.8rem',
101
+ }}
102
+ >
103
+ {option.label}
104
+ </Typography>
105
+ <Typography variant="caption" sx={{ color: theme.palette.custom?.shellMuted, fontSize: '0.68rem' }}>
106
+ {12 + (option.id - 1) * 2}px
107
+ </Typography>
108
+ </Box>
109
+ );
110
+ })}
111
+ </Box>
112
+ </Box>
113
+ );
114
+ };
115
+
116
+ export default FontSizeSelectorWrapper;
@@ -0,0 +1,32 @@
1
+ import { showToast } from '@/common/toaster/toaster';
2
+ export const getAssignedFeature = async (state, linearMenuItems) => {
3
+ try {
4
+ if (linearMenuItems[state] != null && !linearMenuItems[state].systemConstraintConfigs) {
5
+ // const [config, webTemplateConfigResponse] = await Promise.all([
6
+ // systemConstraintConfigs(linearMenuItems[state].id),
7
+ // webTemplateConfig(linearMenuItems[state].id),
8
+ // ]);
9
+
10
+ const assignedFeature = {
11
+ ...linearMenuItems[state],
12
+ // systemConstraintConfigs: config.data,
13
+ // webTemplateConfigs: webTemplateConfigResponse.data,
14
+ };
15
+ return assignedFeature;
16
+ } else {
17
+ const newState = state.replace(/^techo(?=\.)/, 'medplat');
18
+ if (linearMenuItems[newState] != null && !linearMenuItems[newState].systemConstraintConfigs) {
19
+ const assignedFeature = {
20
+ ...linearMenuItems[newState],
21
+ };
22
+ return assignedFeature;
23
+ }
24
+ }
25
+ } catch (error) {
26
+ console.error(error);
27
+ showToast({
28
+ message: 'Not able to fetch Assigned Features',
29
+ type: 'error',
30
+ });
31
+ }
32
+ };
@@ -0,0 +1,216 @@
1
+ import axios from 'axios';
2
+ import { useState, useEffect, useCallback, useRef } from 'react';
3
+ import { useLoader } from '@/layout/LoaderContext';
4
+ import useRefreshToken from '@/hooks/useRefreshToken';
5
+ import PropTypes from 'prop-types';
6
+ import APP_CONFIG from '@/common/constants/app.constant';
7
+ import { showToast } from '@/common/toaster/toaster';
8
+ import { v4 as uuidv4 } from 'uuid';
9
+ import GeneralUtil from '@/common/services/util/GeneralUtil';
10
+
11
+ const api = axios.create({
12
+ baseURL: APP_CONFIG.apiPath,
13
+ });
14
+
15
+ let loaderDisabled = false;
16
+ export const setGlobalLoaderDisabled = (value) => {
17
+ loaderDisabled = value;
18
+ };
19
+
20
+ const isLoaderDisabledRoute = () => loaderDisabled;
21
+
22
+ const AxiosInterceptor = ({ children }) => {
23
+ const [isLoaded, setIsLoaded] = useState(false);
24
+ const { showLoader, hideLoader } = useLoader();
25
+ const [pendingApiCalls, setPendingApiCalls] = useState(0);
26
+ const [loaderStartTime, setLoaderStartTime] = useState(null);
27
+ const { manualRefresh, refreshToken } = useRefreshToken({});
28
+
29
+ const showLoaderRef = useRef(showLoader);
30
+ const hideLoaderRef = useRef(hideLoader);
31
+ const manualRefreshRef = useRef(manualRefresh);
32
+ const refreshTokenRef = useRef(refreshToken);
33
+
34
+ // Use Refs for synchronous access inside interceptors to avoid race conditions
35
+ const pendingApiCallsRef = useRef(0);
36
+ const loaderStartTimeRef = useRef(null);
37
+
38
+ useEffect(() => {
39
+ showLoaderRef.current = showLoader;
40
+ hideLoaderRef.current = hideLoader;
41
+ manualRefreshRef.current = manualRefresh;
42
+ refreshTokenRef.current = refreshToken;
43
+ }, [showLoader, hideLoader, manualRefresh, refreshToken]);
44
+
45
+ useEffect(() => {
46
+ if (pendingApiCalls === 0 && loaderStartTime) {
47
+ const elapsed = new Date().getTime() - loaderStartTime;
48
+ const remainingTime = Math.max(0, 500 - elapsed);
49
+ const t = setTimeout(() => {
50
+ hideLoaderRef.current();
51
+ setLoaderStartTime(null);
52
+ loaderStartTimeRef.current = null;
53
+ }, remainingTime);
54
+ return () => clearTimeout(t);
55
+ }
56
+ }, [pendingApiCalls, loaderStartTime]);
57
+
58
+ const safeParse = (val) => {
59
+ if (!val) return null;
60
+ try {
61
+ return JSON.parse(val);
62
+ } catch (e) {
63
+ console.error('Invalid token JSON in localStorage:', val, e);
64
+ return null;
65
+ }
66
+ };
67
+
68
+ const reqInterceptor = useCallback(
69
+ async (config) => {
70
+ config.headers = config.headers || {};
71
+
72
+ const tokenString = localStorage.getItem('token');
73
+ let token = safeParse(tokenString);
74
+ const pathname = window.location.pathname;
75
+ const disableLoaderForRoute = isLoaderDisabledRoute(pathname);
76
+
77
+ if (token) {
78
+ try {
79
+ // Proactively refresh the token if it's been 10 minutes or is close to expiring
80
+ await manualRefreshRef.current(token);
81
+ const updatedTokenString = localStorage.getItem('token');
82
+ token = safeParse(updatedTokenString) || token;
83
+ } catch (e) {
84
+ console.error('Proactive refresh failed', e);
85
+ }
86
+ }
87
+
88
+ config.headers['X-Client-Date-Time'] = GeneralUtil.formatLocalDateTime();
89
+
90
+ pendingApiCallsRef.current += 1;
91
+ setPendingApiCalls(pendingApiCallsRef.current);
92
+
93
+ if (config?.showLoader !== false && !disableLoaderForRoute) {
94
+ if (!loaderStartTimeRef.current) {
95
+ const now = new Date().getTime();
96
+ loaderStartTimeRef.current = now;
97
+ setLoaderStartTime(now);
98
+ }
99
+ showLoaderRef.current();
100
+ }
101
+ if (token?.access_token) {
102
+ config.headers['Authorization'] = `Bearer ${token.access_token}`;
103
+ config.headers['Pageid'] = config.headers['Pageid'] || uuidv4();
104
+ if (!config.headers['Content-Type']) {
105
+ config.type === 'fileUpload'
106
+ ? (config.headers['Content-Type'] = 'multipart/form-data')
107
+ : (config.headers['Content-Type'] = 'application/json');
108
+ }
109
+ }
110
+ return config;
111
+ },
112
+ [] // Stable dependencies
113
+ );
114
+
115
+ const reqErrInterceptor = useCallback((error) => {
116
+ pendingApiCallsRef.current = Math.max(0, pendingApiCallsRef.current - 1);
117
+ setPendingApiCalls(pendingApiCallsRef.current);
118
+ return Promise.reject(error.config || error);
119
+ }, []);
120
+
121
+ const resInterceptor = useCallback((response) => {
122
+ pendingApiCallsRef.current = Math.max(0, pendingApiCallsRef.current - 1);
123
+ setPendingApiCalls(pendingApiCallsRef.current);
124
+ return response;
125
+ }, []);
126
+
127
+ const resErrInterceptor = useCallback(
128
+ async (error) => {
129
+ const originalRequest = error?.config;
130
+ const response = error?.response;
131
+ const status = response?.status;
132
+
133
+ // Decrement pending calls as this specific request attempt has completed (even if with error)
134
+ pendingApiCallsRef.current = Math.max(0, pendingApiCallsRef.current - 1);
135
+ setPendingApiCalls(pendingApiCallsRef.current);
136
+
137
+ if (originalRequest) {
138
+ originalRequest.headers = originalRequest.headers || {};
139
+ }
140
+
141
+ // Handle 401 Unauthorized - trigger token refresh and retry
142
+ if (status === 401 && !originalRequest?._retry) {
143
+ originalRequest._retry = true;
144
+ try {
145
+ const tokenString = localStorage.getItem('token');
146
+ const token = safeParse(tokenString);
147
+
148
+ if (token) {
149
+ // Wait for the token refresh (singleton logic is handled in the hook)
150
+ await refreshTokenRef.current(token);
151
+
152
+ // Get the updated token after refresh
153
+ const updatedTokenString = localStorage.getItem('token');
154
+ const newAccessToken = safeParse(updatedTokenString);
155
+
156
+ if (newAccessToken?.access_token) {
157
+ originalRequest.headers['Authorization'] = `Bearer ${newAccessToken.access_token}`;
158
+ // Re-issue the request. api(originalRequest) will increment pendingApiCalls again in reqInterceptor.
159
+ return api(originalRequest);
160
+ }
161
+ }
162
+ } catch (refreshError) {
163
+ console.error('Refresh token failed in interceptor', refreshError);
164
+ // If refresh fails, useRefreshToken already handles logout/redirect
165
+ return Promise.reject(refreshError);
166
+ }
167
+ } else if (status === 400) {
168
+ if (
169
+ response?.data?.error === 'invalid_grant' &&
170
+ response?.data?.error_description?.indexOf('Invalid refresh token') >= 0
171
+ ) {
172
+ showToast({ message: 'Session Expired', type: 'error' });
173
+ }
174
+ } else if (status === -1) {
175
+ if (error.response) {
176
+ error.response.data = {
177
+ error: 'server_unreachable',
178
+ error_description: 'Server unreachable, please try after some time.',
179
+ message: 'Server unreachable, please try after some time.',
180
+ };
181
+ }
182
+ } else if (!status) {
183
+ error.response = {
184
+ data: {
185
+ error: 'reason_unknown',
186
+ error_description: 'Something went wrong, please try after some time or refresh.',
187
+ message: 'Something went wrong, please try after some time or refresh.',
188
+ },
189
+ };
190
+ }
191
+
192
+ return Promise.reject(error);
193
+ },
194
+ [] // Stable dependencies
195
+ );
196
+
197
+ useEffect(() => {
198
+ const reqInterceptorEject = api.interceptors.request.use(reqInterceptor, reqErrInterceptor);
199
+ const resInterceptorEject = api.interceptors.response.use(resInterceptor, resErrInterceptor);
200
+
201
+ setIsLoaded(true);
202
+
203
+ return () => {
204
+ api.interceptors.request.eject(reqInterceptorEject);
205
+ api.interceptors.response.eject(resInterceptorEject);
206
+ };
207
+ }, [reqInterceptor, reqErrInterceptor, resInterceptor, resErrInterceptor]);
208
+
209
+ return isLoaded ? children : null;
210
+ };
211
+
212
+ AxiosInterceptor.propTypes = {
213
+ children: PropTypes.any,
214
+ };
215
+
216
+ export { AxiosInterceptor, api };
@@ -0,0 +1,5 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ export const TranslationContext = createContext();
4
+
5
+ export const useTranslateProvider = () => useContext(TranslationContext);
@@ -0,0 +1,24 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { TranslationContext } from './TranslationContext';
5
+
6
+ const TranslationProvider = ({ children }) => {
7
+ const { t } = useTranslation();
8
+
9
+ const translate = (value) => {
10
+ const key = typeof value === "string" ? value?.replace(/\s+/g, '') : value;
11
+ const translatedValue = t(key);
12
+ return translatedValue !== key ? translatedValue : value;
13
+ };
14
+
15
+ const contextValue = React.useMemo(() => ({ translate }), [translate]);
16
+
17
+ return <TranslationContext.Provider value={contextValue}>{children}</TranslationContext.Provider>;
18
+ };
19
+
20
+ TranslationProvider.propTypes = {
21
+ children: PropTypes.node,
22
+ };
23
+
24
+ export default TranslationProvider;
@@ -0,0 +1,49 @@
1
+ // i18n.js
2
+ import i18n from 'i18next';
3
+ import { initReactI18next } from 'react-i18next';
4
+
5
+ const buildResources = (translations = {}) => {
6
+ const resources = {};
7
+
8
+ Object.entries(translations || {}).forEach(([langKey, namespaces]) => {
9
+ resources[langKey] = {
10
+ translation: Object.values(namespaces || {}).reduce((acc, obj) => ({ ...acc, ...obj }), {}),
11
+ };
12
+ });
13
+
14
+ if (!resources.en) {
15
+ resources.en = { translation: {} };
16
+ }
17
+
18
+ return resources;
19
+ };
20
+
21
+ export const initializeI18n = (translations, preferredLanguage) => {
22
+ const resources = buildResources(translations);
23
+ const language = preferredLanguage || 'en';
24
+
25
+ if (i18n.isInitialized) {
26
+ Object.entries(resources).forEach(([langKey, namespaces]) => {
27
+ i18n.removeResourceBundle(langKey, 'translation');
28
+ i18n.addResourceBundle(langKey, 'translation', namespaces.translation, true, true);
29
+ });
30
+
31
+ // Always call changeLanguage so react-i18next re-evaluates translations
32
+ // after resource bundles are updated — even if the language key hasn't changed.
33
+ i18n.changeLanguage(language);
34
+
35
+ return i18n;
36
+ }
37
+
38
+ i18n.use(initReactI18next).init({
39
+ resources,
40
+ lng: language,
41
+ fallbackLng: 'en',
42
+ interpolation: {
43
+ escapeValue: false, // React already escapes strings
44
+ },
45
+ nsSeparator: false,
46
+ });
47
+
48
+ return i18n;
49
+ };
@@ -0,0 +1,116 @@
1
+ import APP_CONFIG from '@/common/constants/app.constant';
2
+ import { api as API } from '@/common/interceptors/AxiosInterceptor';
3
+ import axios from 'axios';
4
+
5
+ import GeneralUtil from '@/common/services/util/GeneralUtil';
6
+
7
+ let clientId = 'imtecho-ui';
8
+ let clientSecret = 'imtecho-ui-secret';
9
+ let basePath = APP_CONFIG.serverPath;
10
+ let encryptionKey;
11
+ let initVector;
12
+
13
+ const encodedClienSecret = btoa(clientId + ':' + clientSecret);
14
+ const encrypt = async (data) => {
15
+ try {
16
+ return await GeneralUtil.getEncodedData(encryptionKey, initVector, data);
17
+ } catch (error) {
18
+ console.error(error);
19
+ return null;
20
+ }
21
+ };
22
+
23
+ export const getSystemNotice = async () => {
24
+ return await API.get('/mobile/systemNotice');
25
+ };
26
+
27
+ export const getApkInfo = async () => {
28
+ return await API.get('/mobile/apkInfo');
29
+ };
30
+
31
+ export const getKeyAndIV = async () => {
32
+ try {
33
+ const response = await API.get('/login/get-key-and-iv', {
34
+ withCredentials: true, // Important!
35
+ });
36
+ encryptionKey = response.data.key;
37
+ initVector = response.data.initVector;
38
+ return;
39
+ } catch (error) {
40
+ console.error(error);
41
+ return null;
42
+ }
43
+ };
44
+
45
+ export const loginService = async (userName, password, loginAs, totpCode) => {
46
+ await getKeyAndIV();
47
+ const data = new URLSearchParams({
48
+ grant_type: 'password',
49
+ username: await encrypt(userName),
50
+ password: await encrypt(password),
51
+ loginas: loginAs,
52
+ client_id: clientId,
53
+ });
54
+ // Two-factor authentication code (Google Authenticator). Sent on the second login attempt
55
+ // when the backend has signalled that 2FA is required for this user.
56
+ if (totpCode) {
57
+ data.append('totp_code', totpCode);
58
+ }
59
+ const config = {
60
+ headers: {
61
+ Authorization: 'Basic ' + encodedClienSecret,
62
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
63
+ 'X-Client-Date-Time': GeneralUtil.formatLocalDateTime(),
64
+ },
65
+ withCredentials: true,
66
+ };
67
+ return await axios.post(basePath + '/oauth/token', data, config);
68
+ };
69
+
70
+ export const getLoggedInUser = async () => {
71
+ let reqForUser = {
72
+ method: 'GET',
73
+ url: '/login/principle',
74
+ };
75
+ return await API(reqForUser);
76
+ };
77
+
78
+ export const getFeatures = async () => {
79
+ return await API.get('/login/menu');
80
+ };
81
+
82
+ export const getFeaturesV2 = async () => {
83
+ return await API.get('/login/menuV2');
84
+ };
85
+
86
+ export const refreshAccessToken = async (token) => {
87
+ if (token) {
88
+ let data = new URLSearchParams({
89
+ grant_type: 'refresh_token',
90
+ refresh_token: token.refresh_token,
91
+ });
92
+
93
+ const config = {
94
+ headers: {
95
+ Authorization: 'Basic ' + encodedClienSecret,
96
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
97
+ 'X-Client-Date-Time': GeneralUtil.formatLocalDateTime(),
98
+ },
99
+ };
100
+ const response = await axios.post(basePath + '/oauth/token', data, config);
101
+
102
+ return response.data;
103
+ }
104
+ return null;
105
+ };
106
+
107
+ export const logout = async (data) => {
108
+ const doNotsendUserName =
109
+ GeneralUtil.isBahaar || GeneralUtil.isSewaRural || GeneralUtil.isMedplat || GeneralUtil.isPhmp;
110
+
111
+ if (doNotsendUserName) {
112
+ return API.post(`/user/logout?clientId=${data?.clientId}`);
113
+ } else {
114
+ return API.get(`/user/logout?clientId=${data?.clientId}&userName=${data?.userName}`);
115
+ }
116
+ };
@@ -0,0 +1,35 @@
1
+ import { fileTypeFromBlob } from 'file-type';
2
+ import { FormConfiguratorService } from '@/common/services/FormConfiguratorService';
3
+
4
+ const downloadFile = async (versionReferenceUUID, mediaUUID) => {
5
+ try {
6
+ const response = (await FormConfiguratorService.getFile(versionReferenceUUID, mediaUUID)).data;
7
+ let fileType = await fileTypeFromBlob(response);
8
+ const dataUrl = URL.createObjectURL(response);
9
+
10
+ let image = null;
11
+ if (!fileType) {
12
+ fileType = {};
13
+ console.warn('File type is undefined. Defaulting to base64 encoding.');
14
+ fileType.mime = 'application/xml';
15
+ }
16
+
17
+ if (fileType.mime === 'application/xml') {
18
+ image = await blobToBase64(response);
19
+ }
20
+ return { fileType, dataUrl, image };
21
+ } catch (error) {
22
+ console.error('Error:', error);
23
+ }
24
+ };
25
+
26
+ const blobToBase64 = (blob) => {
27
+ return new Promise((resolve, reject) => {
28
+ const reader = new FileReader();
29
+ reader.onloadend = () => resolve(reader.result); // Base64 string
30
+ reader.onerror = reject;
31
+ reader.readAsDataURL(blob); // Converts blob to Base64
32
+ });
33
+ };
34
+
35
+ export default downloadFile;
@@ -0,0 +1,18 @@
1
+ import { api } from '@/common/interceptors/AxiosInterceptor';
2
+ import GeneralUtil from './util/GeneralUtil';
3
+
4
+ export const forgotPasswordGenerateOTP = (params) => {
5
+ if (GeneralUtil.isTecho) {
6
+ return api.put('auth/forgotpassword/generateotp', params);
7
+ } else {
8
+ return api.post('auth/forgotpassword/generateotp', params);
9
+ }
10
+ }
11
+
12
+ export const forgotPasswordVerifyOTP = (params) => {
13
+ if (GeneralUtil.isTecho) {
14
+ return api.put('auth/forgotpassword/verifyotp', params);
15
+ } else {
16
+ return api.post('auth/forgotpassword/verifyotp', params);
17
+ }
18
+ }