@argusoft/medplat-app-shell 1.0.6 → 1.0.8

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 (264) 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/store/slices/dashboardSlice.js +14 -0
  161. package/src/utils/.gitkeep +0 -0
  162. package/src/utils/FormConstants.js +2629 -0
  163. package/src/utils/GujaratTopoChart.jsx +483 -0
  164. package/src/utils/UUIDgenerator.js +8 -0
  165. package/src/utils/appointment-utils/appointment-utils.js +123 -0
  166. package/src/utils/feature.js +42 -0
  167. package/src/utils/getThemeColor.js +12 -0
  168. package/src/utils/localStorageHelper.js +11 -0
  169. package/src/utils/notifications/enable-push-notifications.js +27 -0
  170. package/src/utils/resolveAppliedStyle.js +11 -0
  171. package/src/utils/themeConfigs.js +1483 -0
  172. package/src/views/custom-components/.gitkeep +0 -0
  173. package/src/views/custom-components/AgIconButton/RIf.jsx +14 -0
  174. package/src/views/custom-components/AgIconButton/button.jsx +108 -0
  175. package/src/views/custom-components/AgIconButton/waterDrop.jsx +95 -0
  176. package/src/views/custom-components/AgIconButton/waterDrop.scss +37 -0
  177. package/src/views/custom-components/AlertPlaceholder.jsx +32 -0
  178. package/src/views/custom-components/AllFaIconsSelector.jsx +56 -0
  179. package/src/views/custom-components/CkEditor/CkEditor.js +102 -0
  180. package/src/views/custom-components/CustomAccordion.jsx +72 -0
  181. package/src/views/custom-components/CustomActionIcons.jsx +118 -0
  182. package/src/views/custom-components/CustomAutoComplete.jsx +188 -0
  183. package/src/views/custom-components/CustomCheckBox.jsx +60 -0
  184. package/src/views/custom-components/CustomConfirmationModal.jsx +118 -0
  185. package/src/views/custom-components/CustomCountrySelect.jsx +129 -0
  186. package/src/views/custom-components/CustomDatePicker.jsx +122 -0
  187. package/src/views/custom-components/CustomDropdown.jsx +191 -0
  188. package/src/views/custom-components/CustomFileUpload.jsx +387 -0
  189. package/src/views/custom-components/CustomFullCalendar.jsx +514 -0
  190. package/src/views/custom-components/CustomInfiniteScroll.jsx +126 -0
  191. package/src/views/custom-components/CustomRadioComponent.jsx +65 -0
  192. package/src/views/custom-components/CustomStatsComponent.jsx +114 -0
  193. package/src/views/custom-components/CustomSvgUpload.jsx +170 -0
  194. package/src/views/custom-components/CustomSwitch.jsx +37 -0
  195. package/src/views/custom-components/CustomTabPanel.jsx +19 -0
  196. package/src/views/custom-components/CustomTextArea.jsx +62 -0
  197. package/src/views/custom-components/CustomTextArea.scss +27 -0
  198. package/src/views/custom-components/CustomTextField.jsx +116 -0
  199. package/src/views/custom-components/CustomToggleSwitch.jsx +138 -0
  200. package/src/views/custom-components/CustomTooltip.jsx +51 -0
  201. package/src/views/custom-components/CustomZoomImage.jsx +134 -0
  202. package/src/views/custom-components/CustomizedTable/CustomizedTableV2.jsx +1407 -0
  203. package/src/views/custom-components/CustomizedTable/VirtualizeTableBody.jsx +295 -0
  204. package/src/views/custom-components/CustomizedTable/helper.jsx +159 -0
  205. package/src/views/custom-components/CustomizedTable.jsx +532 -0
  206. package/src/views/custom-components/EditInputField.jsx +174 -0
  207. package/src/views/custom-components/FieldDescription.jsx +22 -0
  208. package/src/views/custom-components/FileDisplayComponent.jsx +138 -0
  209. package/src/views/custom-components/FormItem.jsx +53 -0
  210. package/src/views/custom-components/GenericChart.jsx +80 -0
  211. package/src/views/custom-components/InfoBadge.jsx +60 -0
  212. package/src/views/custom-components/PostgresEditor.jsx +801 -0
  213. package/src/views/custom-components/ResizableEditAutocompleteField.jsx +249 -0
  214. package/src/views/custom-components/ResizableEditInputField.jsx +215 -0
  215. package/src/views/custom-components/ResizeableEditSelectField.jsx +197 -0
  216. package/src/views/custom-components/SideOverlay.jsx +113 -0
  217. package/src/views/custom-components/SideOverlay.scss +42 -0
  218. package/src/views/custom-components/calendar.scss +571 -0
  219. package/src/views/feature-components/.gitkeep +0 -0
  220. package/src/views/feature-components/Dashboard/DashboardUI.jsx +1043 -0
  221. package/src/views/feature-components/Dashboard/DhnddModal/AshaDataQualityVerificationModal.jsx +278 -0
  222. package/src/views/feature-components/Dashboard/PinFeatureModal.jsx +143 -0
  223. package/src/views/feature-components/Dashboard/QuickLinks.jsx +163 -0
  224. package/src/views/feature-components/Dashboard/Taskbar.jsx +56 -0
  225. package/src/views/feature-components/Dashboard/WebtasksFilterForm.jsx +109 -0
  226. package/src/views/feature-components/Dashboard/WidgetCard.jsx +161 -0
  227. package/src/views/feature-components/Dashboard/actionModal.jsx +263 -0
  228. package/src/views/feature-components/Dashboard/ekavachModal/HealthWorkerIncorrectDetailsModal.jsx +332 -0
  229. package/src/views/feature-components/Dashboard/ekavachModal/MoMaternalDeathVerifcationModal.jsx +275 -0
  230. package/src/views/feature-components/Dashboard/ekavachModal/MoVerficationForChildScreeningMoadal.jsx +566 -0
  231. package/src/views/feature-components/FeatureUsageAnalytics/FeatureUsageAnalytics.jsx +989 -0
  232. package/src/views/feature-components/Features/NewServerManagement.jsx +217 -0
  233. package/src/views/feature-components/Features/ServerManagement.scss +120 -0
  234. package/src/views/feature-components/ForgotPassword/ForgotPassword.jsx +226 -0
  235. package/src/views/feature-components/LocationDirective/LocationDirective.jsx +992 -0
  236. package/src/views/feature-components/LocationDirective/LocationDirectiveV2.jsx +909 -0
  237. package/src/views/feature-components/NotFound.jsx +66 -0
  238. package/src/views/feature-components/Onboarding/Onboarding.jsx +1400 -0
  239. package/src/views/feature-components/Skeletons.js +115 -0
  240. package/src/views/feature-components/Unauthorized.jsx +48 -0
  241. package/src/views/feature-components/VerifyRoute.jsx +88 -0
  242. package/src/views/feature-components/YearlyRecap/YearlyRecap.jsx +357 -0
  243. package/src/views/feature-components/YearlyRecap/components/RecapSlide.jsx +183 -0
  244. package/src/views/feature-components/YearlyRecap/languageTranslator/TranslationContext.js +5 -0
  245. package/src/views/feature-components/YearlyRecap/languageTranslator/TranslationProvider.jsx +26 -0
  246. package/src/views/feature-components/YearlyRecap/languageTranslator/i18n.js +46 -0
  247. package/src/views/feature-components/YearlyRecap/languageTranslator/translations.json +167 -0
  248. package/src/views/feature-components/YearlyRecap/slides/IntroSlide.jsx +233 -0
  249. package/src/views/feature-components/YearlyRecap/slides/MaternalHealthSlide.jsx +146 -0
  250. package/src/views/feature-components/YearlyRecap/slides/MetricSlide.jsx +227 -0
  251. package/src/views/feature-components/YearlyRecap/slides/OutroSlide.jsx +701 -0
  252. package/src/views/feature-components/YearlyRecap/slides/ReachSlide.jsx +273 -0
  253. package/src/views/feature-components/login/Login.jsx +840 -0
  254. package/src/views/feature-components/login/Login.scss +154 -0
  255. package/src/views/feature-components/login/LoginConfigurator.jsx +1149 -0
  256. package/src/views/feature-components/login/TwoFactorSetupModal.jsx +411 -0
  257. package/src/views/feature-components/login/simplifyMenu.js +45 -0
  258. package/src/views/feature-components/system-config/ManageSystemConfigs.jsx +284 -0
  259. package/src/views/feature-components/system-config/SystemConfig.jsx +299 -0
  260. package/src/views/feature-components/users/ChangePasswordModal.jsx +243 -0
  261. package/src/views/feature-components/users/PasswordField.jsx +56 -0
  262. package/dist/index.css +0 -1
  263. package/dist/index.js +0 -32001
  264. package/dist/index.js.map +0 -1
@@ -0,0 +1,1407 @@
1
+ import React, { useState, useEffect, useMemo, useDeferredValue, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ Pagination,
5
+ Paper,
6
+ TablePagination,
7
+ Box,
8
+ Typography,
9
+ Checkbox,
10
+ TableContainer,
11
+ useTheme,
12
+ alpha,
13
+ } from '@mui/material';
14
+ import Grid from '@mui/material/Grid2';
15
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
16
+ import { faArrowDownShortWide, faArrowUpWideShort, faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
17
+ import Table from '@mui/material/Table';
18
+ import TableBody from '@mui/material/TableBody';
19
+ import TableHead from '@mui/material/TableHead';
20
+ import TableRow from '@mui/material/TableRow';
21
+ import CustomActionIcons from '@/views/custom-components/CustomActionIcons';
22
+ import CustomInfiniteScroll from '@/views/custom-components/CustomInfiniteScroll';
23
+ import { useTranslateProvider } from '@/common/languageTranslator/TranslationContext';
24
+ import {
25
+ createStyledTableCell,
26
+ createStyledTableContainer,
27
+ createStyledTableRow,
28
+ defaultStyles,
29
+ TooltipContent,
30
+ } from './helper.jsx';
31
+ import VirtualizedTableBody from './VirtualizeTableBody.jsx';
32
+ import { useSelector } from 'react-redux';
33
+ import { getUseSkeleton } from '@/store/reducers/SkeletonReducer';
34
+
35
+ /**
36
+ * A customizable table component that supports various features like pagination, sorting,
37
+ * row selection, infinite scrolling, and custom column rendering.
38
+ *
39
+ * @component
40
+ */
41
+ const CustomizedTable = ({
42
+ colspanData,
43
+ dataColspan,
44
+ columns, // Column configuration
45
+ tableData, // Data to display
46
+ actions, // Row actions (can be array or function returning array)
47
+ displayPageSelect = false, // Show page selection dropdown
48
+ doNotShowTableHead, // Hide table headers
49
+ handleSort, // Function to handle column sorting
50
+ disableHtml = false, // Disable HTML rendering in cells
51
+ conditionCheckObj = {}, // Conditions for showing actions
52
+ dataTestId, // For testing
53
+ styleConfig = {},
54
+ isLoading, // Loading state
55
+ strip = true, // Zebra striping for rows
56
+ paginationConfig = {},
57
+ rowSelectionConfig = {},
58
+ scrollToTop = false,
59
+ setScrollToTop = () => { },
60
+ showAllBorders = false,
61
+ showScrollArrows = false,
62
+ showFullContent = true,
63
+ ...props
64
+ }) => {
65
+ const useSkeleton = useSelector(getUseSkeleton);
66
+ const headerRow1Ref = useRef(null);
67
+ const headerRow2Ref = useRef(null);
68
+ const [headerRow1Height, setHeaderRow1Height] = useState(0);
69
+ const [headerRow2Height, setHeaderRow2Height] = useState(0);
70
+ const theme = useTheme();
71
+ // Add selection column if row selection is enabled
72
+ const {
73
+ pagination = true,
74
+ paginationType = 'client-side',
75
+ rowsPerPageInTable = 10,
76
+ currentPage: propCurrentPage,
77
+ onPageChange,
78
+ loadMore,
79
+ hasMore,
80
+ totalRows,
81
+ } = paginationConfig;
82
+ const {
83
+ setSelectedRows,
84
+ selectedRows = [],
85
+ rowSelectionEnabled = false,
86
+ selectedRowsUnique = 'id',
87
+ } = rowSelectionConfig;
88
+
89
+ const [pinnedCols, setPinnedCols] = useState([]);
90
+ const deferredPinnedCols = useDeferredValue(pinnedCols);
91
+ const tableRef = useRef(null);
92
+ const containerRef = useRef(null);
93
+ const scrollPosRef = useRef({ top: 0, left: 0 });
94
+ const [canScrollLeft, setCanScrollLeft] = useState(false);
95
+ const [canScrollRight, setCanScrollRight] = useState(false);
96
+
97
+ const checkScroll = React.useCallback((element) => {
98
+ if (!element) return;
99
+ const { scrollLeft, scrollWidth, clientWidth } = element;
100
+ setCanScrollLeft(scrollLeft > 0);
101
+ setCanScrollRight(scrollLeft < scrollWidth - clientWidth - 5); // 5px buffer
102
+ }, []);
103
+
104
+ const handleScroll = React.useCallback((e) => {
105
+ scrollPosRef.current = {
106
+ top: e.target.scrollTop,
107
+ left: e.target.scrollLeft,
108
+ };
109
+ if (showScrollArrows) {
110
+ if (!isAutoScrolling.current) {
111
+ stopScrolling();
112
+ }
113
+ checkScroll(e.target);
114
+ }
115
+ }, [showScrollArrows, checkScroll]);
116
+
117
+ const scrollIntervalRef = useRef(null);
118
+ const isAutoScrolling = useRef(false);
119
+
120
+ const stopScrolling = () => {
121
+ isAutoScrolling.current = false;
122
+ if (scrollIntervalRef.current) {
123
+ clearInterval(scrollIntervalRef.current);
124
+ scrollIntervalRef.current = null;
125
+ }
126
+ };
127
+
128
+ const startScrolling = (direction) => {
129
+ if (isAutoScrolling.current) return;
130
+ isAutoScrolling.current = true;
131
+ stopScrolling(); // Double check
132
+ isAutoScrolling.current = true; // Set again after stopScrolling set it to false
133
+ scrollIntervalRef.current = setInterval(() => {
134
+ if (containerRef.current) {
135
+ containerRef.current.scrollBy({
136
+ left: direction === 'left' ? -10 : 10,
137
+ behavior: 'auto',
138
+ });
139
+ }
140
+ }, 20);
141
+ };
142
+
143
+ useEffect(() => {
144
+ if (showScrollArrows && containerRef.current) {
145
+ checkScroll(containerRef.current);
146
+ // Also check on resize
147
+ const observer = new ResizeObserver(() => checkScroll(containerRef.current));
148
+ observer.observe(containerRef.current);
149
+ return () => {
150
+ observer.disconnect();
151
+ stopScrolling();
152
+ };
153
+ }
154
+ }, [showScrollArrows, tableData, checkScroll]);
155
+
156
+ // 6. Handle header height measurements for correct positioning and stickiness
157
+ React.useLayoutEffect(() => {
158
+ const updateHeights = () => {
159
+ if (headerRow1Ref.current) {
160
+ setHeaderRow1Height(headerRow1Ref.current.offsetHeight);
161
+ } else {
162
+ setHeaderRow1Height(0);
163
+ }
164
+ if (headerRow2Ref.current) {
165
+ setHeaderRow2Height(headerRow2Ref.current.offsetHeight);
166
+ }
167
+ };
168
+
169
+ updateHeights();
170
+
171
+ // Use ResizeObserver for more robust height tracking
172
+ const observer1 = headerRow1Ref.current ? new ResizeObserver(updateHeights) : null;
173
+ const observer2 = headerRow2Ref.current ? new ResizeObserver(updateHeights) : null;
174
+
175
+ if (observer1) observer1.observe(headerRow1Ref.current);
176
+ if (observer2) observer2.observe(headerRow2Ref.current);
177
+
178
+ return () => {
179
+ observer1?.disconnect();
180
+ observer2?.disconnect();
181
+ };
182
+ }, [tableData, columns, colspanData, showAllBorders]);
183
+
184
+ // Dynamically correct sticky offset dimensions to fix overlap caused by colspans naturally expanding CSS widths
185
+ useEffect(() => {
186
+ if (!tableRef.current || !showAllBorders || pinnedCols.length === 0) return;
187
+
188
+ let rafId;
189
+ const updateOffsets = () => {
190
+ if (!tableRef.current) return;
191
+ const leftMap = {};
192
+ let currentLeft = 0;
193
+
194
+ // 1. Calculate boundaries sequentially
195
+ const ths = Array.from(tableRef.current.querySelectorAll('.row2-sticky-cell'));
196
+ ths.forEach((th) => {
197
+ const field = th.getAttribute('data-field');
198
+ if (field) {
199
+ const roundedLeft = Math.round(currentLeft);
200
+ th.style.setProperty('left', `${roundedLeft}px`, 'important');
201
+ tableRef.current.style.setProperty(`--actual-left-${field}`, `${roundedLeft}px`);
202
+ leftMap[field] = roundedLeft;
203
+ currentLeft += th.getBoundingClientRect().width;
204
+ }
205
+ });
206
+ // 2. Adjust Group Headers
207
+ const groups = Array.from(tableRef.current.querySelectorAll('.row1-sticky-cell'));
208
+ groups.forEach((th) => {
209
+ const first = th.getAttribute('data-first-child');
210
+ if (first && leftMap[first] !== undefined) {
211
+ th.style.setProperty('left', `${leftMap[first]}px`, 'important');
212
+ }
213
+ });
214
+ // 3. Adjust Data cells
215
+ const tds = Array.from(tableRef.current.querySelectorAll('.data-sticky-cell'));
216
+ tds.forEach((td) => {
217
+ const field = td.getAttribute('data-field');
218
+ if (field && leftMap[field] !== undefined) {
219
+ td.style.setProperty('left', `${leftMap[field]}px`, 'important');
220
+ }
221
+ });
222
+ };
223
+
224
+ // Initial paint calculation
225
+ updateOffsets();
226
+ const tId = setTimeout(updateOffsets, 100);
227
+
228
+ const ro =
229
+ typeof ResizeObserver !== 'undefined'
230
+ ? new ResizeObserver(() => {
231
+ cancelAnimationFrame(rafId);
232
+ rafId = requestAnimationFrame(updateOffsets);
233
+ })
234
+ : null;
235
+
236
+ if (ro) {
237
+ ro.observe(tableRef.current);
238
+ const stickyCells = Array.from(tableRef.current.querySelectorAll('.row2-sticky-cell'));
239
+ stickyCells.forEach((cell) => ro.observe(cell));
240
+ }
241
+
242
+ return () => {
243
+ clearTimeout(tId);
244
+ cancelAnimationFrame(rafId);
245
+ if (ro) ro.disconnect();
246
+ };
247
+ }, [columns, showAllBorders, pinnedCols, colspanData]);
248
+
249
+ /**
250
+ * Toggle pinning state for a specific column
251
+ * @param {string} field
252
+ */
253
+ const handleTogglePin = React.useCallback((e, field) => {
254
+ e.preventDefault();
255
+ e.stopPropagation();
256
+ if (!showAllBorders || !field) return;
257
+ setPinnedCols((prev) => {
258
+ const isPinned = prev.includes(field);
259
+ if (isPinned) {
260
+ return prev.filter((col) => col !== field);
261
+ } else {
262
+ if (prev.length >= 5) {
263
+ return prev; // Max 5 columns limit
264
+ }
265
+ return [...prev, field];
266
+ }
267
+ });
268
+ }, []);
269
+
270
+ const { headerStyle, cellStyle, rowStyle, tableStyle } = styleConfig;
271
+ const maxLines = cellStyle?.maxLines || 1;
272
+
273
+ // Memoize styled components based on styleConfig
274
+ const StyledTableContainer = useMemo(() => createStyledTableContainer(tableStyle), [tableStyle]);
275
+
276
+ const StyledTableCell = useMemo(() => createStyledTableCell(headerStyle, cellStyle), []);
277
+
278
+ const StyledTableRow = useMemo(() => createStyledTableRow(rowStyle), []);
279
+ const infiniteScroll = paginationType === 'infinite-scroll';
280
+
281
+ useEffect(() => {
282
+ if (scrollToTop && containerRef.current) {
283
+ containerRef.current.scrollTop = 0;
284
+ scrollPosRef.current.top = 0; // Also reset saved position
285
+ setScrollToTop(false);
286
+ }
287
+ }, [scrollToTop, setScrollToTop]);
288
+
289
+ useEffect(() => {
290
+ if (containerRef.current) {
291
+ containerRef.current.scrollTop = scrollPosRef.current.top;
292
+ containerRef.current.scrollLeft = scrollPosRef.current.left;
293
+ }
294
+ }, [tableData, StyledTableContainer]);
295
+
296
+ // 1. Parse colspanData to associate EVERY visible DATA column with its intended group (skipping checkbox)
297
+ // 1. Map each physical visible DATA column to its group header
298
+ const columnToHeaderMap = useMemo(() => {
299
+ if (!colspanData) return {};
300
+ try {
301
+ const parser = new DOMParser();
302
+ const doc = parser.parseFromString(`<table><tr>${dataColspan}</tr></table>`, 'text/html');
303
+ const ths = Array.from(doc.querySelectorAll('th'));
304
+
305
+ const map = {};
306
+
307
+ // Identify visible DATA columns only
308
+ const visibleDataOriginalIndices = []; // These are indices from the original `columns` array
309
+ columns.forEach((col, idx) => {
310
+ if (!col.hide) {
311
+ visibleDataOriginalIndices.push(idx);
312
+ }
313
+ });
314
+
315
+ let dataPtr = 0;
316
+ ths.forEach((th, index) => {
317
+ const span = parseInt(th.getAttribute('colspan') || '1', 10);
318
+ const groupLabel = th.innerHTML;
319
+ const groupId = `header-${index}`;
320
+
321
+ for (let i = 0; i < span; i++) {
322
+ if (dataPtr < visibleDataOriginalIndices.length) {
323
+ // Map the header info to the `originalIndex` that the data column will have in `baseCols`
324
+ // If row selection is enabled, data columns are shifted by 1 in `baseCols`
325
+ const baseColsIndex = visibleDataOriginalIndices[dataPtr] + (rowSelectionEnabled ? 1 : 0);
326
+ map[baseColsIndex] = { label: groupLabel, id: groupId, span: span };
327
+ dataPtr++;
328
+ }
329
+ }
330
+ });
331
+ return map;
332
+ } catch {
333
+ return {};
334
+ }
335
+ }, [colspanData, dataColspan, rowSelectionEnabled, columns]);
336
+
337
+ const visibleColumns = useMemo(() => {
338
+ if (!columns) return [];
339
+
340
+ // Create base list with stable originalIndex
341
+ const baseCols = rowSelectionEnabled
342
+ ? [
343
+ { field: 'rowSelect', label: '', minWidth: 60, isSticky: true, originalIndex: 0 },
344
+ ...columns.map((c, i) => ({ ...c, originalIndex: i + 1 })),
345
+ ]
346
+ : columns.map((c, i) => ({ ...c, originalIndex: i }));
347
+
348
+ const pinnedGroup = [];
349
+ const normalGroup = [];
350
+
351
+ baseCols.forEach((col) => {
352
+ const isPinned =
353
+ showAllBorders && (col.isSticky === true || col.isSticky === 'true' || deferredPinnedCols.includes(col.field));
354
+ const headerInfo = columnToHeaderMap[col.originalIndex] || { label: '', id: 'none' };
355
+
356
+ const processedCol = {
357
+ ...col,
358
+ isSticky: isPinned,
359
+ isUserPinned: deferredPinnedCols.includes(col.field),
360
+ groupLabel: headerInfo.label,
361
+ groupId: headerInfo.id,
362
+ groupSpan: headerInfo.span || 1,
363
+ };
364
+
365
+ if (isPinned) {
366
+ pinnedGroup.push(processedCol);
367
+ } else {
368
+ normalGroup.push(processedCol);
369
+ }
370
+ });
371
+
372
+ const finalColsOrder = [...pinnedGroup, ...normalGroup];
373
+ let cumulativeStickyWidth = 0;
374
+
375
+ return finalColsOrder.map((col, index, array) => {
376
+ const width = col.width || col.minWidth || (col.field === 'rowSelect' ? 60 : 150);
377
+ let stickyLeft = 0;
378
+ if (col.isSticky) {
379
+ stickyLeft = cumulativeStickyWidth;
380
+ cumulativeStickyWidth += width;
381
+ }
382
+
383
+ // Identify group start/end for borders (Task 1) - only for meaningful groups
384
+ const gid = col.groupId;
385
+ const meaningfulGroup =
386
+ gid && gid !== 'none' && gid !== 'rowSelect-internal-group' && gid !== 'Actions-internal-group';
387
+ const isGroupStart =
388
+ !meaningfulGroup ||
389
+ index === 0 ||
390
+ array[index - 1].groupId !== gid ||
391
+ array[index - 1].isSticky !== col.isSticky;
392
+ const isGroupEnd =
393
+ !meaningfulGroup ||
394
+ index === array.length - 1 ||
395
+ array[index + 1].groupId !== gid ||
396
+ array[index + 1].isSticky !== col.isSticky;
397
+
398
+ return {
399
+ ...col,
400
+ minWidth: width,
401
+ width,
402
+ maxWidth: 'none',
403
+ stickyLeft,
404
+ isGroupStart,
405
+ isGroupEnd,
406
+ isLastSticky: col.isSticky && (index === array.length - 1 || !array[index + 1].isSticky),
407
+ hasColspanGroup: !!meaningfulGroup && col.groupSpan > 1,
408
+ };
409
+ });
410
+ }, [rowSelectionEnabled, columns, deferredPinnedCols, columnToHeaderMap]);
411
+
412
+ const hasAnyPinned = useMemo(() => pinnedCols.length > 0, [pinnedCols]);
413
+ const colspanRowRef = useRef(null);
414
+
415
+ // Synthesis: Build Row 1 by grouping adjacent columns in our PRE-ORDERED visibleColumns
416
+ const reorderedGroups = useMemo(() => {
417
+ if (!colspanData) return [];
418
+
419
+ const results = [];
420
+ let current = null;
421
+
422
+ visibleColumns.forEach((col) => {
423
+ if (col.hide) return;
424
+
425
+ let gid = col.groupId || 'none';
426
+ let glabel = col.groupLabel || '';
427
+
428
+ if (col.field === 'rowSelect') {
429
+ gid = 'rowSelect-internal-group';
430
+ glabel = '';
431
+ }
432
+
433
+ if (current && current.groupId === gid && current.isSticky === col.isSticky) {
434
+ current.span += 1;
435
+ current.width += col.width;
436
+ if (col.isLastSticky) current.isLastSticky = true;
437
+ } else {
438
+ current = {
439
+ label: glabel,
440
+ groupId: gid,
441
+ isSticky: col.isSticky,
442
+ isLastSticky: col.isLastSticky,
443
+ stickyLeft: col.stickyLeft,
444
+ span: 1,
445
+ width: col.width,
446
+ firstChild: col.field || `col-${col.originalIndex}`,
447
+ };
448
+
449
+ results.push(current);
450
+ }
451
+ });
452
+ return results;
453
+ }, [visibleColumns, colspanData, hasAnyPinned]);
454
+
455
+ const { translate } = useTranslateProvider();
456
+ const [internalSortConfig, setInternalSortConfig] = useState({ field: null, order: null });
457
+
458
+ const [internalPage, setInternalPage] = useState(1);
459
+ const [rowsPerPage, setRowsPerPage] = useState(rowsPerPageInTable);
460
+ const [rowsPerPageOptionsArray, setRowsPerPageOptionsArray] = useState(null);
461
+
462
+ const rowDataFiltered = useMemo(() => tableData || [], [tableData]);
463
+
464
+ const rowData = useMemo(() => {
465
+ if (!internalSortConfig.field) return rowDataFiltered;
466
+
467
+ const { field, order } = internalSortConfig;
468
+ return [...rowDataFiltered].sort((a, b) => {
469
+ let valA = a[field];
470
+ let valB = b[field];
471
+
472
+ const isEmpty = (val) => val === null || val === undefined || val === '' || val === ' ' || val === 'NA';
473
+
474
+ if (isEmpty(valA) && !isEmpty(valB)) return 1;
475
+ if (!isEmpty(valA) && isEmpty(valB)) return -1;
476
+ if (isEmpty(valA) && isEmpty(valB)) return 0;
477
+
478
+ const getNumeric = (val) => {
479
+ if (typeof val === 'number') return val;
480
+ if (typeof val !== 'string') return NaN;
481
+ const cleaned = val.replace(/[^0-9.-]/g, '');
482
+ return cleaned !== '' ? parseFloat(cleaned) : NaN;
483
+ };
484
+
485
+ const numA = getNumeric(valA);
486
+ const numB = getNumeric(valB);
487
+
488
+ if (!isNaN(numA) && !isNaN(numB)) {
489
+ return order === 'asc' ? numA - numB : numB - numA;
490
+ }
491
+
492
+ const strA = valA.toString().toLowerCase();
493
+ const strB = valB.toString().toLowerCase();
494
+ return order === 'asc' ? strA.localeCompare(strB) : strB.localeCompare(strA);
495
+ });
496
+ }, [rowDataFiltered, internalSortConfig]);
497
+
498
+ const selectAllChecked = useMemo(() => {
499
+ return selectedRows?.length === rowData?.length && rowData?.length > 0;
500
+ }, [selectedRows, rowData]);
501
+
502
+ // Use provided page or internal state
503
+ const page = propCurrentPage !== undefined ? propCurrentPage : internalPage;
504
+
505
+ // Calculate rows per page options based on data size
506
+ useEffect(() => {
507
+ if (pagination && rowsPerPageInTable && rowData) {
508
+ setInternalPage(1);
509
+ calculateRowsPerPageOptions();
510
+ }
511
+ if (colspanRowRef.current) {
512
+ const height = colspanRowRef.current.getBoundingClientRect().height;
513
+ setHeaderRow1Height(height);
514
+ } else {
515
+ setHeaderRow1Height(0);
516
+ }
517
+ }, [rowsPerPageInTable, rowData, pagination]);
518
+
519
+ /**
520
+ * Calculate sensible rows per page options based on data size
521
+ */
522
+ const calculateRowsPerPageOptions = () => {
523
+ const numOptions = 5;
524
+
525
+ if (rowData.length <= rowsPerPageInTable) {
526
+ setRowsPerPageOptionsArray([rowsPerPageInTable]);
527
+ } else {
528
+ const increment = Math.ceil((rowData.length - rowsPerPageInTable) / (numOptions - 1));
529
+ const options = [rowsPerPageInTable];
530
+
531
+ for (let i = 1; i < numOptions - 1; i++) {
532
+ options.push(rowsPerPageInTable + i * increment);
533
+ }
534
+
535
+ options.push(rowData.length);
536
+ setRowsPerPageOptionsArray(options);
537
+ }
538
+ };
539
+
540
+ /**
541
+ * Handle page changes (delegating to parent if provided)
542
+ */
543
+ const handlePageChange = (newPage) => {
544
+ if (onPageChange) {
545
+ onPageChange(newPage); // Parent handles API call
546
+ } else {
547
+ setInternalPage(newPage); // Internal state for client-side
548
+ }
549
+ };
550
+
551
+ /**
552
+ * Handle changing rows per page
553
+ */
554
+ const handleChangeRowsPerPage = (event) => {
555
+ setRowsPerPage(parseInt(event.target.value, 10));
556
+ setInternalPage(1);
557
+ };
558
+
559
+ /**
560
+ * Handle select all rows
561
+ */
562
+ const handleSelectAll = () => {
563
+ if (selectedRows.length === rowData.length) {
564
+ setSelectedRows([]);
565
+ } else {
566
+ setSelectedRows([...rowData]);
567
+ }
568
+ };
569
+
570
+ /**
571
+ * Handle selecting a single row
572
+ */
573
+ const handleRowSelect = (row) => {
574
+ setSelectedRows((prev) => {
575
+ const isIncluded = prev.find((item) => item[selectedRowsUnique] === row[selectedRowsUnique]);
576
+
577
+ if (isIncluded) {
578
+ return prev.filter((item) => item[selectedRowsUnique] !== row[selectedRowsUnique]);
579
+ } else {
580
+ return [...prev, row];
581
+ }
582
+ });
583
+ };
584
+
585
+ /**
586
+ * Render cell content based on column type and configuration
587
+ */
588
+ const renderCellContent = (column, row, rowIndex) => {
589
+ // Select row checkbox
590
+ if (rowSelectionEnabled && column.field === 'rowSelect') {
591
+ return (
592
+ <Checkbox
593
+ color="primary"
594
+ checked={!!selectedRows.find((item) => item[selectedRowsUnique] === row[selectedRowsUnique])}
595
+ onChange={() => handleRowSelect(row)}
596
+ />
597
+ );
598
+ }
599
+
600
+ // Actions column
601
+ if (column.field === 'Actions' && actions) {
602
+ const actionItems = typeof actions === 'function' ? actions(row) : actions;
603
+ let defaultIconColor;
604
+ let defaultBackgroundColor;
605
+ let defaultHoverBackgroundColor;
606
+ let defaultBorderColor;
607
+ let defaultHoverIconColor;
608
+ let defaultRotateIcon;
609
+ return (
610
+ <div
611
+ style={{
612
+ ...defaultStyles.actionsContainer,
613
+ textAlign: column.align || 'left',
614
+ justifyContent: column.align === 'right' ? 'flex-end' : column.align === 'center' ? 'center' : 'flex-start',
615
+ }}
616
+ className="flex items-center h-full"
617
+ >
618
+ {actionItems.map((action, actionIndex) => {
619
+ if (!action) return null;
620
+ // Check if action should be displayed
621
+ const shouldDisplay = action?.condition ? action.condition(row, conditionCheckObj) : true;
622
+ if (!shouldDisplay) {
623
+ if (actionIndex === 0) {
624
+ return <>-</>;
625
+ }
626
+ return null;
627
+ }
628
+ if (action?.icon?.props?.icon?.iconName === 'pen') {
629
+ defaultIconColor = theme.palette.secondary.main;
630
+ defaultBackgroundColor = alpha(theme.palette.secondary.main, 0.1);
631
+ defaultHoverBackgroundColor = theme.palette.secondary.main;
632
+ defaultHoverIconColor = 'white';
633
+ defaultBorderColor = theme.palette.secondary.main;
634
+ defaultRotateIcon = true;
635
+ }
636
+ if (action?.icon?.props?.icon?.iconName === 'trash') {
637
+ defaultIconColor = theme.palette.error.main;
638
+ defaultBackgroundColor = alpha(theme.palette.error.main, 0.1);
639
+ defaultHoverBackgroundColor = theme.palette.error.main;
640
+ defaultHoverIconColor = 'white';
641
+ defaultBorderColor = theme.palette.error.main;
642
+ defaultRotateIcon = true;
643
+ }
644
+ if (action?.icon?.props?.icon?.iconName === 'bars') {
645
+ defaultIconColor = theme.palette.primary.main;
646
+ defaultBackgroundColor = alpha(theme.palette.primary.main, 0.1);
647
+ defaultHoverBackgroundColor = theme.palette.primary.main;
648
+ defaultHoverIconColor = 'white';
649
+ defaultBorderColor = theme.palette.primary.main;
650
+ defaultRotateIcon = true;
651
+ }
652
+ const isDisabled = action.disabled === true ? row.state !== 'ACTIVE' :
653
+ false;
654
+
655
+ return (
656
+ <CustomActionIcons
657
+ key={actionIndex + 1}
658
+ disabled={isDisabled}
659
+ row={row}
660
+ icon={action.icon}
661
+ menuClick={action.menuClick}
662
+ menuItems={action.menuItems}
663
+ onClick={() => {
664
+ if (!isDisabled) {
665
+ action?.onClick(row, rowIndex);
666
+ }
667
+ }}
668
+ iconColor={action.iconColor || defaultIconColor || 'primary'}
669
+ backgroundColor={action.backgroundColor || defaultBackgroundColor || 'transparent'}
670
+ hoverBackgroundColor={action.hoverBackgroundColor || defaultHoverBackgroundColor || '#E6EDEF'}
671
+ borderColor={action.borderColor || defaultBorderColor || 'gray'}
672
+ hoverIconColor={action.hoverIconColor || defaultHoverIconColor || 'primary'}
673
+ rotateIcon={action.rotateIcon || defaultRotateIcon || false}
674
+ dataTestId={action?.dataTestId}
675
+ />
676
+ );
677
+ })}
678
+ </div>
679
+ );
680
+ }
681
+
682
+ // Serial number column
683
+ if (column.field === 'Sr. No.') {
684
+ if (pagination && !infiniteScroll && rowsPerPage > 0) {
685
+ const startIndex = (page - 1) * rowsPerPage;
686
+ if (pagination && !infiniteScroll && rowsPerPage > 0) {
687
+ return (
688
+ <p className="text-[0.8rem] text-slate-400 font-black tracking-tighter flex items-center h-full">
689
+ {`#${(rowIndex + 1 + startIndex).toString().padStart(3, '0')}`}
690
+ </p>
691
+ );
692
+ }
693
+ }
694
+ return (
695
+ <p className="text-[0.8rem] text-slate-400 font-black tracking-tighter flex items-center h-full">
696
+ {`#${(rowIndex + 1).toString().padStart(3, '0')}`}
697
+ </p>
698
+ );
699
+ }
700
+
701
+ // Custom rendered column
702
+ if (column.render) {
703
+ return column.render(row, rowIndex);
704
+ }
705
+
706
+ // Standard column with value from data
707
+ const value = row?.[column?.field];
708
+ if (
709
+ (value || value === 0 || typeof value === 'boolean') &&
710
+ column.field !== 'Actions' &&
711
+ column.field !== 'rowSelect'
712
+ ) {
713
+ const cellFontSize = cellStyle?.fontSize || '0.875rem';
714
+ if (!disableHtml) {
715
+ return (
716
+ <div
717
+ style={{ fontSize: cellFontSize, fontWeight: column.isBold ? 'bold' : 'normal' }}
718
+ className="flex items-center h-full"
719
+ >
720
+ {maxLines ? (
721
+ <TooltipContent content={value} maxLines={maxLines} isHtml showFullContent={showFullContent} />
722
+ ) : (
723
+ <div dangerouslySetInnerHTML={{ __html: value }} />
724
+ )}
725
+ </div>
726
+ );
727
+ } else {
728
+ return (
729
+ <span style={{ fontSize: cellFontSize, fontWeight: column.isBold ? 'bold' : 'normal' }}>
730
+ {maxLines ? (
731
+ <TooltipContent content={value} maxLines={maxLines} isHtml={false} showFullContent={showFullContent} />
732
+ ) : (
733
+ <div className="flex items-center h-full ">{value}</div>
734
+ )}
735
+ </span>
736
+ );
737
+ }
738
+ }
739
+
740
+ // Empty cell for special columns
741
+ if (
742
+ column.field !== 'Actions' &&
743
+ column.field !== 'Sr. No.' &&
744
+ column.field !== 'rowSelect' &&
745
+ column.field !== 'statusCheckbox'
746
+ ) {
747
+ return <div className="flex items-center h-full ">NA</div>;
748
+ }
749
+
750
+ return '';
751
+ };
752
+
753
+ /**
754
+ * Render the table body with all rows
755
+ */
756
+ const renderTableBody = () => {
757
+ if (isLoading && useSkeleton) {
758
+ return <div className="bg-gray-300 animate-pulse rounded-sm w-full h-100"></div>;
759
+ }
760
+
761
+ return (
762
+ <Table
763
+ ref={tableRef}
764
+ aria-label="Customized Table"
765
+ data-testid={dataTestId}
766
+ sx={{ borderCollapse: 'separate', borderSpacing: 0 }}
767
+ {...props}
768
+ >
769
+ {/* Table Header */}
770
+ {!doNotShowTableHead && (
771
+ <TableHead>
772
+ {colspanData && (
773
+ <TableRow
774
+ ref={headerRow1Ref}
775
+ className="group"
776
+ sx={{
777
+ position: 'sticky',
778
+ top: 0,
779
+ zIndex: 1010, // Higher than row 2
780
+ backgroundColor: theme.palette.mode === 'dark' ? theme.palette.background.paper : '#FBFCFD',
781
+ '& th': {
782
+ padding: '8px',
783
+ fontSize: '0.8rem',
784
+ border: 'none',
785
+ borderTop: '1px solid #d1d1d1',
786
+ borderBottom: '1px solid #d1d1d1',
787
+ backgroundColor: theme.palette.mode === 'dark' ? theme.palette.background.paper : '#FBFCFD',
788
+ zIndex: 950, // Increased z-index (Task 3)
789
+ position: 'sticky',
790
+ top: 0,
791
+ },
792
+ }}
793
+ >
794
+ {reorderedGroups.map((group, i) => (
795
+ <th
796
+ key={i}
797
+ colSpan={group.span}
798
+ className={group.isSticky ? 'row1-sticky-cell' : ''}
799
+ data-first-child={group.firstChild}
800
+ style={{
801
+ textAlign: 'center',
802
+ backgroundColor: theme.palette.mode === 'dark' ? theme.palette.background.paper : '#FBFCFD',
803
+ borderLeft: group.label && group.label !== '' ? '1px solid #d1d1d1' : 'none',
804
+ borderRight:
805
+ (group.label && group.label !== '') || group.isLastSticky ? '1px solid #d1d1d1' : 'none',
806
+ borderBottom: '1px solid #d1d1d1',
807
+ borderTop: '1px solid #d1d1d1',
808
+ ...(group.isSticky && {
809
+ position: 'sticky',
810
+ left: `${group.stickyLeft}px`,
811
+ zIndex: 1011,
812
+ }),
813
+ }}
814
+ >
815
+ <Box
816
+ sx={{
817
+ position: 'relative',
818
+ display: 'flex',
819
+ alignItems: 'center',
820
+ justifyContent: 'center',
821
+ width: '100%',
822
+ height: '100%',
823
+ }}
824
+ dangerouslySetInnerHTML={{ __html: group.label || '' }}
825
+ />
826
+ </th>
827
+ ))}
828
+ </TableRow>
829
+ )}
830
+
831
+ <TableRow
832
+ ref={headerRow2Ref}
833
+ className="group"
834
+ sx={{
835
+ position: 'sticky',
836
+ top: colspanData ? `${headerRow1Height}px` : 0,
837
+ zIndex: 1000,
838
+ backgroundColor: theme.palette.mode === 'dark' ? theme.palette.background.paper : '#FBFCFD',
839
+ }}
840
+ >
841
+ {visibleColumns?.map(
842
+ (column, index) =>
843
+ !column.hide && (
844
+ <StyledTableCell
845
+ key={index + 1}
846
+ align={column.align || 'center'}
847
+ onClick={() => {
848
+ if (!column.sortable) return;
849
+ const field = column.field;
850
+ const newOrder =
851
+ internalSortConfig.field === field
852
+ ? internalSortConfig.order === 'asc'
853
+ ? 'desc'
854
+ : 'asc'
855
+ : 'asc';
856
+ setInternalSortConfig({ field, order: newOrder });
857
+
858
+ if (handleSort) {
859
+ handleSort(column);
860
+ }
861
+ }}
862
+ className={
863
+ column.isSticky
864
+ ? 'p-4 whitespace-normal break-words sticky-cell row2-sticky-cell'
865
+ : 'p-4 whitespace-normal break-words'
866
+ }
867
+ data-field={column.field || `col-${column.originalIndex}`}
868
+ sx={{
869
+ backgroundColor: theme?.palette?.custom?.tableHeader + ' !important',
870
+ position: 'sticky',
871
+ top: colspanData ? `${headerRow1Height}px` : 0,
872
+ left: column.isSticky
873
+ ? `var(--actual-left-${column.field || `col-${column.originalIndex}`}, ${column.stickyLeft}px)`
874
+ : 'auto',
875
+ zIndex: column.isSticky ? '900 !important' : '800 !important',
876
+ boxSizing: 'border-box',
877
+ padding: showAllBorders ? '4px 6px' : '8px 16px',
878
+ fontSize: showAllBorders ? '0.75rem' : '0.875rem',
879
+ border: 'none', // Remove all generic borders
880
+ borderLeft:
881
+ showAllBorders && column.hasColspanGroup && column.isGroupStart
882
+ ? '1px solid #d1d1d1 !important'
883
+ : 'none',
884
+ borderRight:
885
+ showAllBorders && (column.isLastSticky || (column.hasColspanGroup && column.isGroupEnd))
886
+ ? '1px solid #d1d1d1 !important'
887
+ : 'none',
888
+ boxShadow:
889
+ showAllBorders && column.isSticky && column.isLastSticky
890
+ ? 'inset -1px 0px 0px #d1d1d1'
891
+ : 'none',
892
+ borderBottom: '1px solid #d1d1d1 !important', // Ensure proper visual separation for all headers
893
+ borderTop: showAllBorders && column.hasColspanGroup ? '1px solid #d1d1d1 !important' : 'none',
894
+ }}
895
+ >
896
+ <Box
897
+ sx={{
898
+ display: 'flex',
899
+ flexDirection: showAllBorders ? 'column' : 'row', // Task 2: Sub-row for pin icon in reports
900
+ alignItems: 'center',
901
+ justifyContent: showAllBorders ? 'center' : column.align || 'left',
902
+ position: 'relative',
903
+ zIndex: column.isSticky ? '9100 !important' : 'inherit',
904
+ top: 0,
905
+ }}
906
+ >
907
+ {/* Header Content (Label + Sort) */}
908
+ <Box
909
+ sx={{
910
+ display: 'flex',
911
+ alignItems: 'center',
912
+ width: 'auto',
913
+ justifyContent: showAllBorders ? 'center' : column.align || 'left',
914
+ }}
915
+ >
916
+ {rowSelectionEnabled && column.field === 'rowSelect' ? (
917
+ <Checkbox color="primary" checked={selectAllChecked} onChange={handleSelectAll} />
918
+ ) : (
919
+ <>
920
+ <Typography
921
+ variant="caption"
922
+ onClick={
923
+ showAllBorders && column.field !== 'rowSelect'
924
+ ? (e) => {
925
+ e.stopPropagation();
926
+ handleTogglePin(e, column.field);
927
+ }
928
+ : undefined
929
+ }
930
+ sx={{
931
+ ...defaultStyles.headerTypography,
932
+ position: 'relative',
933
+ zIndex: column.isSticky ? '9200 !important' : 'inherit',
934
+ lineHeight: '1 !important',
935
+ cursor: showAllBorders ? 'pointer' : 'inherit',
936
+ userSelect: 'none',
937
+ }}
938
+ >
939
+ {translate(column?.label)}
940
+ </Typography>
941
+ {column.sortable && (
942
+ <Box
943
+ sx={{
944
+ ml: 1,
945
+ zIndex: column.isSticky ? '9200 !important' : 'inherit',
946
+ cursor: 'pointer',
947
+ }}
948
+ onClick={(e) => {
949
+ e.stopPropagation();
950
+ const field = column.field;
951
+ const newOrder =
952
+ internalSortConfig.field === field
953
+ ? internalSortConfig.order === 'asc'
954
+ ? 'desc'
955
+ : 'asc'
956
+ : 'asc';
957
+ setInternalSortConfig({ field, order: newOrder });
958
+
959
+ if (handleSort) {
960
+ handleSort(column);
961
+ }
962
+ }}
963
+ >
964
+ {(() => {
965
+ const currentOrder =
966
+ column.sortOrder ||
967
+ (internalSortConfig.field === column.field ? internalSortConfig.order : null);
968
+ return currentOrder === 'asc' ? (
969
+ <FontAwesomeIcon icon={faArrowUpWideShort} />
970
+ ) : (
971
+ <FontAwesomeIcon icon={faArrowDownShortWide} />
972
+ );
973
+ })()}
974
+ </Box>
975
+ )}
976
+ </>
977
+ )}
978
+ </Box>
979
+ </Box>
980
+ </StyledTableCell>
981
+ )
982
+ )}
983
+ </TableRow>
984
+ </TableHead>
985
+ )}
986
+
987
+ {/* Table Body */}
988
+ <TableBody>
989
+ {rowData && rowData.length ? (
990
+ // Determine which rows to display based on pagination settings
991
+ (() => {
992
+ let displayedRows = rowData;
993
+ if (pagination && !infiniteScroll && rowsPerPage > 0 && !onPageChange) {
994
+ const startIndex = (page - 1) * rowsPerPage;
995
+ displayedRows = rowData.slice(startIndex, startIndex + rowsPerPage);
996
+ }
997
+
998
+ return displayedRows.map((row, rowIndex) => {
999
+ const rowKey = props.rowUniqueKey ? row[props.rowUniqueKey] : row?.id || rowIndex + 1;
1000
+ return (
1001
+ <StyledTableRow
1002
+ className="group"
1003
+ key={rowKey}
1004
+ sx={(theme) => ({
1005
+ backgroundColor:
1006
+ theme.palette.mode === 'dark'
1007
+ ? theme.palette.background.paper
1008
+ : strip && rowIndex % 2 !== 0
1009
+ ? theme?.palette?.custom?.gray4
1010
+ : 'inherit',
1011
+ })}
1012
+ >
1013
+ {visibleColumns.map((column, colIndex) => {
1014
+ let disabledRow = false;
1015
+ try {
1016
+ disabledRow = typeof column.disabled === 'function' ? column.disabled(row) : false;
1017
+ } catch (error) {
1018
+ console.error('Error evaluating disabled function for column:', column, error);
1019
+ }
1020
+
1021
+ const rowBg =
1022
+ theme.palette.mode === 'dark'
1023
+ ? theme.palette.background.paper
1024
+ : strip && rowIndex % 2 !== 0
1025
+ ? theme?.palette?.custom?.gray4
1026
+ : theme.palette.background.paper;
1027
+
1028
+ return (
1029
+ !column.hide && (
1030
+ <StyledTableCell
1031
+ key={`${column.field || 'field'}-${colIndex}`}
1032
+ className={column.isSticky ? 'sticky-cell data-sticky-cell' : ''}
1033
+ data-field={column.field || `col-${column.originalIndex}`}
1034
+ sx={() => ({
1035
+ textAlign: column.align || 'left',
1036
+ cursor: column.onClick && !disabledRow ? 'pointer' : 'default',
1037
+ color: column.onClick && !disabledRow ? 'blue' : 'inherit',
1038
+ textDecoration: column.onClick && !disabledRow ? 'underline' : 'none',
1039
+ width: column.field === 'Sr. No.' ? '0.2rem' : column.width,
1040
+ minWidth: column.field === 'Sr. No.' ? '0.2rem' : column.minWidth,
1041
+ maxWidth: 'none',
1042
+ padding: colspanData ? '4px 6px' : '5px 16px',
1043
+ fontSize: colspanData ? '0.75rem' : '0.8125rem',
1044
+ ...(column.isSticky && {
1045
+ position: 'sticky',
1046
+ left: `var(--actual-left-${column.field || `col-${column.originalIndex}`}, ${column.stickyLeft}px)`,
1047
+ zIndex: 500, // Below filter (1200)
1048
+ backgroundColor: `${rowBg} !important`,
1049
+ boxSizing: 'border-box',
1050
+ borderLeft: showAllBorders || column.isSticky ? '1px solid #d1d1d1' : 'none',
1051
+ borderRight:
1052
+ showAllBorders || column.isSticky || column.isLastSticky
1053
+ ? '1px solid #d1d1d1'
1054
+ : 'none',
1055
+ boxShadow:
1056
+ showAllBorders && column.isSticky && column.isLastSticky
1057
+ ? 'inset -1px 0px 0px #d1d1d1'
1058
+ : 'none',
1059
+ }),
1060
+ ...(!column.isSticky &&
1061
+ showAllBorders && {
1062
+ borderLeft: '1px solid #d1d1d1',
1063
+ borderRight: '1px solid #d1d1d1',
1064
+ boxSizing: 'border-box',
1065
+ }),
1066
+ })}
1067
+ data-testid={`tableData-row-${rowIndex}-column-${colIndex}`}
1068
+ onClick={column.onClick && !disabledRow ? () => column.onClick(row) : undefined}
1069
+ >
1070
+ <p className="h-full">{renderCellContent(column, row, rowIndex)}</p>
1071
+ {/* {renderCellContent(column, row, rowIndex)} */}
1072
+ </StyledTableCell>
1073
+ )
1074
+ );
1075
+ })}
1076
+ </StyledTableRow>
1077
+ );
1078
+ });
1079
+ })()
1080
+ ) : (
1081
+ <StyledTableRow>
1082
+ <StyledTableCell className={`border-b-0 border-r-0`} colSpan={visibleColumns.length}>
1083
+ {isLoading && useSkeleton ? (
1084
+ <div className="animate-pulse bg-gray-300 w-full h-100"></div>
1085
+ ) : (
1086
+ translate(props.emptyMessage || 'No Records Available')
1087
+ )}
1088
+ </StyledTableCell>
1089
+ </StyledTableRow>
1090
+ )}
1091
+ </TableBody>
1092
+ </Table>
1093
+ );
1094
+ };
1095
+
1096
+ /**
1097
+ * Get total count for pagination
1098
+ */
1099
+ const getTotalCount = () => {
1100
+ if (totalRows !== undefined) {
1101
+ return totalRows;
1102
+ }
1103
+ renderTableBody;
1104
+ return rowData ? rowData.length : 0;
1105
+ };
1106
+
1107
+ /**
1108
+ * Get total pages for pagination
1109
+ */
1110
+ const getTotalPages = () => {
1111
+ const count = getTotalCount();
1112
+ return Math.ceil(count / rowsPerPage);
1113
+ };
1114
+
1115
+ return (
1116
+ <>
1117
+ <TableContainer
1118
+ component={'div'}
1119
+ className="rounded-[1rem] shadow-sm border overflow-hidden"
1120
+ sx={{
1121
+ backgroundColor: theme.palette.background.paper,
1122
+ borderColor: theme.palette.mode === 'dark' ? "#1f2937" : "#E5E7EB",
1123
+ '& ::-webkit-scrollbar': {
1124
+ width: '8px !important',
1125
+ height: '8px !important',
1126
+ },
1127
+ '& ::-webkit-scrollbar-track': {
1128
+ backgroundColor: `${theme.palette.mode === 'dark' ? '#1e1e1e' : '#f1f1f1'} !important`,
1129
+ },
1130
+ '& ::-webkit-scrollbar-thumb': {
1131
+ backgroundColor: `${theme.palette.mode === 'dark' ? '#555' : '#ccc'} !important`,
1132
+ borderRadius: '4px !important',
1133
+ },
1134
+ '& ::-webkit-scrollbar-thumb:hover': {
1135
+ backgroundColor: `${theme.palette.mode === 'dark' ? '#777' : '#999'} !important`,
1136
+ },
1137
+ scrollbarColor: theme.palette.mode === 'dark' ? '#555 #1e1e1e !important' : '#ccc #f1f1f1 !important',
1138
+ scrollbarWidth: 'thin !important',
1139
+ }}
1140
+ >
1141
+ {pagination && infiniteScroll ? (
1142
+ <CustomInfiniteScroll
1143
+ loadMore={loadMore}
1144
+ hasMore={hasMore}
1145
+ renderTableBody={renderTableBody}
1146
+ customHeight={tableStyle?.maxHeight}
1147
+ useWindow={false}
1148
+ scrollToTop={scrollToTop}
1149
+ setScrollToTop={setScrollToTop}
1150
+ />
1151
+ ) : (
1152
+ <div style={{ position: 'relative' }}>
1153
+ <StyledTableContainer
1154
+ ref={containerRef}
1155
+ component={Paper}
1156
+ style={{ position: 'relative', overflow: 'auto' }}
1157
+ sx={{
1158
+ '&::-webkit-scrollbar': {
1159
+ width: '8px',
1160
+ height: '8px',
1161
+ },
1162
+ '&::-webkit-scrollbar-track': {
1163
+ backgroundColor: theme.palette.mode === 'dark' ? '#1e1e1e' : '#f1f1f1',
1164
+ },
1165
+ '&::-webkit-scrollbar-thumb': {
1166
+ backgroundColor: theme.palette.mode === 'dark' ? '#555' : '#ccc',
1167
+ borderRadius: '4px',
1168
+ },
1169
+ '&::-webkit-scrollbar-thumb:hover': {
1170
+ backgroundColor: theme.palette.mode === 'dark' ? '#777' : '#999',
1171
+ },
1172
+ scrollbarColor: theme.palette.mode === 'dark' ? '#555 #1e1e1e' : '#ccc #f1f1f1',
1173
+ scrollbarWidth: 'thin',
1174
+ }}
1175
+ onScroll={handleScroll}
1176
+ >
1177
+ {paginationType === 'virtual-scroll' ? (
1178
+ <VirtualizedTableBody
1179
+ rows={rowData}
1180
+ visibleColumns={visibleColumns}
1181
+ StyledTableCell={StyledTableCell}
1182
+ StyledTableRow={StyledTableRow}
1183
+ renderCellContent={renderCellContent}
1184
+ rowSelectionEnabled={rowSelectionEnabled}
1185
+ selectAllChecked={selectAllChecked}
1186
+ handleSelectAll={handleSelectAll}
1187
+ styleConfig={styleConfig}
1188
+ tableHeight={tableStyle?.maxHeight || 100}
1189
+ rowSelectionConfig={rowSelectionConfig}
1190
+ showAllBorders={showAllBorders}
1191
+ onTogglePin={handleTogglePin}
1192
+ handleSort={handleSort}
1193
+ reorderedGroups={reorderedGroups}
1194
+ colspanData={colspanData}
1195
+ />
1196
+ ) : (
1197
+ renderTableBody()
1198
+ )}
1199
+ </StyledTableContainer>
1200
+
1201
+ {showScrollArrows && (
1202
+ <>
1203
+ {canScrollLeft && (
1204
+ <Box
1205
+ onMouseEnter={() => startScrolling('left')}
1206
+ onMouseLeave={stopScrolling}
1207
+ sx={{
1208
+ position: 'absolute',
1209
+ left: 0,
1210
+ top: headerRow1Height + (headerRow2Height / 2) || 25,
1211
+ transform: 'translateY(-50%)',
1212
+ zIndex: 1000,
1213
+ backgroundColor: 'rgba(151, 155, 156, 0.7)',
1214
+ color: 'white',
1215
+ width: 100,
1216
+ height: headerRow2Height || 115,
1217
+ display: 'flex',
1218
+ alignItems: 'center',
1219
+ justifyContent: 'center',
1220
+ borderRadius: '0 8px 8px 0',
1221
+ cursor: 'pointer',
1222
+ boxShadow: '2px 0 5px rgba(0,0,0,0.2)',
1223
+ }}
1224
+ >
1225
+ <FontAwesomeIcon
1226
+ style={{ marginTop: '0px' }}
1227
+ size='3x'
1228
+ icon={faChevronLeft} />
1229
+ </Box>
1230
+ )}
1231
+ {canScrollRight && (
1232
+ <Box
1233
+ onMouseEnter={() => startScrolling('right')}
1234
+ onMouseLeave={stopScrolling}
1235
+ sx={{
1236
+ position: 'absolute',
1237
+ right: 0,
1238
+ top: headerRow1Height + (headerRow2Height / 2) || 25,
1239
+ transform: 'translateY(-50%)',
1240
+ zIndex: 1000,
1241
+ backgroundColor: 'rgba(151, 155, 156, 0.7)',
1242
+ color: 'white',
1243
+ width: 100,
1244
+ height: headerRow2Height || 115,
1245
+ display: 'flex',
1246
+ alignItems: 'center',
1247
+ justifyContent: 'center',
1248
+ borderRadius: '8px 0 0 8px',
1249
+ cursor: 'pointer',
1250
+ boxShadow: '-2px 0 5px rgba(0,0,0,0.2)',
1251
+ }}
1252
+ >
1253
+ <FontAwesomeIcon
1254
+ style={{ marginTop: '0px' }}
1255
+ size="3x"
1256
+ icon={faChevronRight} />
1257
+ </Box>
1258
+ )}
1259
+ </>
1260
+ )}
1261
+ </div>
1262
+ )}
1263
+
1264
+ {/* Pagination Controls */}
1265
+ {pagination && !infiniteScroll && !isLoading && (
1266
+ <Grid
1267
+ container
1268
+ sx={{
1269
+ width: '100%',
1270
+ position: 'relative', // Needed for absolute centering
1271
+ alignItems: 'center',
1272
+ minHeight: 64, // Ensures enough height for vertical centering
1273
+ backgroundColor: theme.palette.background.paper,
1274
+
1275
+ // THEME-BASED TEXT COLOR:
1276
+ color: theme.palette.text.primary,
1277
+
1278
+ // OPTIONAL: Add a subtle border that also respects the theme
1279
+ borderTop: `1px solid ${theme.palette.divider}`,
1280
+ }}
1281
+ >
1282
+ <Grid item>
1283
+ {rowsPerPageOptionsArray && rowsPerPageOptionsArray.length > 0 && (
1284
+ <TablePagination
1285
+ component="div"
1286
+ count={getTotalCount()}
1287
+ page={page}
1288
+ onPageChange={(_event, newPage) => handlePageChange(newPage)}
1289
+ sx={{
1290
+ '& .MuiTablePagination-actions': {
1291
+ visibility: 'hidden',
1292
+ },
1293
+ '& .MuiSelect-select': {
1294
+ padding: '6px 32px 6px 16px',
1295
+ },
1296
+ '& .MuiTablePagination-input, & .MuiTablePagination-selectLabel': {
1297
+ display: displayPageSelect ? undefined : 'none',
1298
+ },
1299
+ }}
1300
+ labelRowsPerPage="Items per page"
1301
+ // only show if screen size is md or lg
1302
+ labelDisplayedRows={({ count }) => {
1303
+ if (window.innerWidth < 768) {
1304
+ return '';
1305
+ }
1306
+ // Adjust from/to for 0-based indexing
1307
+ let adjustedFrom;
1308
+ let adjustedTo;
1309
+ if (count === 0) {
1310
+ adjustedFrom = 0;
1311
+ adjustedTo = 0;
1312
+ } else {
1313
+ adjustedFrom = (page - 1) * rowsPerPage + 1;
1314
+ adjustedTo = Math.min(count, page * rowsPerPage);
1315
+ }
1316
+ return `${adjustedFrom}-${adjustedTo} of ${count} items`;
1317
+ }}
1318
+ rowsPerPage={rowsPerPage}
1319
+ onRowsPerPageChange={handleChangeRowsPerPage}
1320
+ rowsPerPageOptions={rowsPerPageOptionsArray}
1321
+ />
1322
+ )}
1323
+ </Grid>
1324
+ <Grid
1325
+ item
1326
+ sx={{
1327
+ position: 'absolute',
1328
+ left: { sm: '35%', xs: '35%', md: '50%', lg: '50%' },
1329
+ transform: 'translateX(-50%)',
1330
+ }}
1331
+ >
1332
+ <Pagination
1333
+ count={getTotalPages()}
1334
+ page={page}
1335
+ onChange={(event, newPage) => handlePageChange(newPage)}
1336
+ /* showFirstButton
1337
+ showLastButton */
1338
+ sx={{
1339
+ '& .MuiPaginationItem-root.Mui-selected': {
1340
+ backgroundColor: '#004C70',
1341
+ color: '#FFFFFF',
1342
+ },
1343
+ '& .MuiPaginationItem-root.Mui-selected:hover': {
1344
+ backgroundColor: '#678ea0',
1345
+ },
1346
+ }}
1347
+ />
1348
+ </Grid>
1349
+ </Grid>
1350
+ )}
1351
+
1352
+ {/* Loading State for Pagination */}
1353
+ {pagination && isLoading && useSkeleton && (
1354
+ <div className="w-full justify-between flex-wrap flex flex-row mt-4">
1355
+ <div className="flex-wrap flex flex-row">
1356
+ <div className="bg-gray-300 animate-pulse rounded-sm h-[36px] w-[100px] mr-2 mb-2"></div>
1357
+ </div>
1358
+
1359
+ <div className="flex">
1360
+ <div className="bg-gray-300 animate-pulse rounded-sm h-[32px] w-[180px] m-0.5"></div>
1361
+ </div>
1362
+ </div>
1363
+ )}
1364
+ </TableContainer>
1365
+ </>
1366
+ );
1367
+ };
1368
+
1369
+ CustomizedTable.propTypes = {
1370
+ colspanData: PropTypes.any,
1371
+ dataColspan: PropTypes.any,
1372
+ columns: PropTypes.any,
1373
+ tableData: PropTypes.any,
1374
+ actions: PropTypes.any,
1375
+ rowsPerPageInTable: PropTypes.any,
1376
+ displayPageSelect: PropTypes.any,
1377
+ noPagination: PropTypes.any,
1378
+ doNotShowTableHead: PropTypes.any,
1379
+ fontSize: PropTypes.any,
1380
+ loadMore: PropTypes.any,
1381
+ hasMore: PropTypes.any,
1382
+ handleSort: PropTypes.any,
1383
+ sortOrder: PropTypes.any,
1384
+ conditionCheckObj: PropTypes.any,
1385
+ disableHtml: PropTypes.any,
1386
+ dataTestId: PropTypes.any,
1387
+ customHeight: PropTypes.any,
1388
+ totalRows: PropTypes.any,
1389
+ currentPage: PropTypes.any,
1390
+ onPageChange: PropTypes.any,
1391
+ selectedRowsUnique: PropTypes.any,
1392
+ isLoading: PropTypes.any,
1393
+ strip: PropTypes.any,
1394
+ styleConfig: PropTypes.any,
1395
+ paginationConfig: PropTypes.any,
1396
+ handleToggleStatus: PropTypes.any,
1397
+ rowSelectionConfig: PropTypes.any,
1398
+ scrollToTop: PropTypes.any,
1399
+ setScrollToTop: PropTypes.any,
1400
+ emptyMessage: PropTypes.string,
1401
+ rowUniqueKey: PropTypes.string,
1402
+ showFullContent: PropTypes.any,
1403
+ showAllBorders: PropTypes.any,
1404
+ showScrollArrows: PropTypes.any,
1405
+ };
1406
+
1407
+ export default CustomizedTable;