@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,992 @@
1
+ import { useTranslateProvider } from '@/common/languageTranslator/TranslationContext';
2
+ import { getParent, retrieveNextLevel } from '@/common/services/LocationService';
3
+ import { retriveLocationType } from '@/common/services/LocationType';
4
+ import { showToast } from '@/common/toaster/toaster';
5
+ import CustomDropdown from '@/views/custom-components/CustomDropdown';
6
+ import { InputLabel } from '@mui/material';
7
+ import Grid from '@mui/material/Grid2';
8
+ import PropTypes from 'prop-types';
9
+ import React, { useEffect, useRef, useState } from 'react';
10
+ import { useForm, useFormContext } from 'react-hook-form';
11
+ import { useSelector } from 'react-redux';
12
+ import { getUseSkeleton } from '@/store/reducers/SkeletonReducer';
13
+
14
+ /**
15
+ * A component that handles the location selection directive.
16
+ *
17
+ * @module LocationDirective
18
+ * @param {Object} props - The props object.
19
+ * @param {Function} props.setSelectedLocation - Callback function to set the selected location.
20
+ * @param {Object} props.selectedLocationRef - A reference to the currently selected location.
21
+ * @param {string} [props.templateType='inline'] - The type of template for rendering (default is 'inline').
22
+ * @param {Function} props.fetchAccordingToUserAoi - Function to fetch data according to the user's AOI.
23
+ * @param {boolean} props.demographicFilterRequired - Determines if demographic filtering is required.
24
+ * @param {number} props.requiredUptoLevel - The level up to which data is required.
25
+ * @param {number} props.fetchUptoLevel - The level up to which data should be fetched.
26
+ * @param {boolean} props.multipleOnLevel - Flag indicating if multiple selections are allowed on a specific level.
27
+ * @param {boolean} props.allDistrictReq - Flag indicating if all districts are required.
28
+ * @param {boolean} props.allBlockReq - Flag indicating if all blocks are required.
29
+ * @param {any} props.resetKey - When this value changes, LocationDirective will reset all its fields and state. Use a unique value (e.g., Date.now()) to trigger a reset from parent.
30
+ *
31
+ * @returns {JSX.Element} The rendered location directive component.
32
+ */
33
+
34
+ const LocationDirective = ({
35
+ childForm = false,
36
+ selectedLocation,
37
+ setSelectedLocation, //Send Setter Method of state variable (selectedLocation) for two-way binding
38
+ selectedLocationRef, //Send Ref Variable instead of (selectedLocation in older versions)
39
+ templateType = 'inline',
40
+ fetchAccordingToUserAoi = false,
41
+ demographicFilterRequired,
42
+ requiredUptoLevel = 1,
43
+ fetchUptoLevel,
44
+ multipleOnLevel,
45
+ allDistrictReq,
46
+ allBlockReq,
47
+ selectedIdRef, //Send Ref Variable instead of (ngModel in older versions)
48
+ setSelectedId,
49
+ size, //Send Setter method of state variable (selectedId) for two-way binding
50
+ isLoading,
51
+ onChange,
52
+ resetKey,
53
+ }) => {
54
+ const [showDirective, setShowDirective] = useState(false);
55
+ const [locationTypes, setLocationTypes] = useState([]);
56
+ const [locations, setLocations] = useState([]);
57
+ const [areaOfIntervention, setAreaOfIntervention] = useState([]);
58
+ const locationsRef = useRef(locations);
59
+ const { translate } = useTranslateProvider();
60
+
61
+ const [onFirstRunTemp, setOnFirstRunTemp] = useState(false);
62
+ const [minLevel, setMinLevel] = useState(1);
63
+ const [levelAoi, setLevelAoi] = useState(true);
64
+
65
+ const allRegion = {
66
+ id: -1,
67
+ locType: 'Region',
68
+ name: 'All District',
69
+ type: 'R',
70
+ };
71
+ const allBlocks = {
72
+ id: -2,
73
+ locType: 'District',
74
+ name: 'All Block',
75
+ type: 'D',
76
+ };
77
+ const allowedEnv = ['medplat'];
78
+ const demographicOptions = [
79
+ { value: '', key: 'Both' },
80
+ { value: 'U', key: 'Urban' },
81
+ { value: 'R', key: 'Rural' },
82
+ ];
83
+ const presentEnv = import.meta.env.ENVIRONMENT;
84
+ let noLocationInHierarchyMessage = null;
85
+ const { user: loggedInUser } = useSelector((state) => state.Authenticate);
86
+
87
+ /**
88
+ * Retrieves active location types from the server and updates the state.
89
+ * @async
90
+ * @function retrieveLocationTypes
91
+ * @returns {Promise<void>} Resolves when location types are successfully retrieved and state is updated.
92
+ */
93
+
94
+ const retrieveLocationTypes = async () => {
95
+ try {
96
+ const response = await retriveLocationType({}, { showLoader: false });
97
+ const data = response.data.filter((r) => r.isActive);
98
+ setLocationTypes(() => data);
99
+ } catch (error) {
100
+ console.error(error);
101
+ showToast({ message: 'Error in loading Location Types', type: 'error' });
102
+ }
103
+ };
104
+
105
+ /**
106
+ * Clears the selected locations for levels lower than the specified `selectedLocationLevel`.
107
+ * @function clearLowerLevelSelection
108
+ * @param {number} selectedLocationLevel - The level at which the selection is cleared for all lower levels.
109
+ * @returns {void}
110
+ */
111
+
112
+ const clearLowerLevelSelection = (selectedLocationLevel) => {
113
+ if (
114
+ selectedLocationRef.current.finalSelected &&
115
+ selectedLocationRef.current.finalSelected.level > selectedLocationLevel
116
+ ) {
117
+ locationsRef.current = locationsRef.current.filter((location) => {
118
+ if (selectedLocationRef.current['level' + location.level] && location.level > selectedLocationLevel) {
119
+ const updatedSelectedLocation = { ...selectedLocationRef.current };
120
+ delete updatedSelectedLocation['level' + location.level];
121
+ setValue(`level${location.level}`);
122
+ selectedLocationRef.current = updatedSelectedLocation;
123
+ setSelectedLocation(() => updatedSelectedLocation);
124
+ }
125
+ return location.level <= selectedLocationLevel;
126
+ });
127
+ setLocations(() => locationsRef.current);
128
+ }
129
+ locationsRef.current = locationsRef.current.filter((location) => location.level <= selectedLocationLevel);
130
+ setLocations(() => locationsRef.current);
131
+ };
132
+
133
+ /**
134
+ * Handles the selection of a location from a dropdown or input event.
135
+ * @function handleLocationSelect
136
+ * @param {Object} e - The event object from the input or dropdown selection.
137
+ * @param {string} e.target.name - The name attribute representing the level of the location.
138
+ * @param {(string|string[])} e.target.value - The ID or array of IDs for the selected location(s).
139
+ * @returns {void}
140
+ */
141
+
142
+ const handleLocationUpadte = (name, locationId) => {
143
+ const fetchedLevel = parseInt(name.split('')[name.length - 1]);
144
+ const locationInput = locationsRef.current.find((location) => location.level === fetchedLevel);
145
+ const selectedLocationObject =
146
+ fetchedLevel === multipleOnLevel
147
+ ? locationId.map((id) => locationInput.locationDetails.find((location) => location.id === id))
148
+ : locationInput.locationDetails.find((location) => location.id === locationId);
149
+ selectedLocationRef.current = {
150
+ ...selectedLocationRef.current,
151
+ [name]: selectedLocationObject,
152
+ };
153
+ setSelectedLocation(() => selectedLocationRef.current);
154
+ setValue(name, locationId);
155
+ onLocationChange(locationInput);
156
+ };
157
+
158
+ const handleLocationSelect = (e) => {
159
+ const { name, value: locationId } = e.target;
160
+ const fetchedLevel = parseInt(name.split('')[name.length - 1]);
161
+ const locationInput = locationsRef.current.find((location) => location.level === fetchedLevel);
162
+ const selectedLocationObject =
163
+ fetchedLevel === multipleOnLevel
164
+ ? locationId.map((id) => locationInput.locationDetails.find((location) => location.id === id))
165
+ : locationInput.locationDetails.find((location) => location.id === locationId);
166
+ selectedLocationRef.current = {
167
+ ...selectedLocationRef.current,
168
+ [name]: selectedLocationObject,
169
+ };
170
+ setSelectedLocation(() => selectedLocationRef.current);
171
+ onLocationChange(locationInput);
172
+ };
173
+
174
+ const handleAreaOfIntervention = (e) => {
175
+ setOnFirstRunTemp(false);
176
+ const selectedLocationObject = areaOfIntervention?.find((location) => location.id === e.target.value);
177
+ selectedLocationRef.current = {
178
+ [`level${selectedLocationObject?.level}`]: selectedLocationObject,
179
+ };
180
+ setSelectedLocation(() => selectedLocationRef.current);
181
+ locationsRef.current = [];
182
+ onLocationChange({
183
+ level: selectedLocationObject?.level,
184
+ locationLabel: selectedLocationObject?.locationLabel,
185
+ locationDetails: selectedLocationObject,
186
+ });
187
+ };
188
+ /**
189
+ * Handles changes to the demographic selection.
190
+ * @function handleDemographicChange
191
+ * @param {Object} e - The event object from the input or selection change.
192
+ * @param {string} e.target.value - The value of the selected demographic.
193
+ * @returns {void}
194
+ */
195
+
196
+ const handleDemographicChange = (e) => {
197
+ const { value: selectedDemographic } = e.target;
198
+ selectedLocationRef.current = {
199
+ ...selectedLocationRef.current,
200
+ selectedDemographic,
201
+ };
202
+ setSelectedLocation(() => selectedLocationRef.current);
203
+ };
204
+
205
+ const updateAreaOfIntervention = (index, newValue) => {
206
+ setAreaOfIntervention((prev) => {
207
+ const updated = [...prev]; // copy the array
208
+ updated[index] = newValue; // update at the specific index
209
+ return updated;
210
+ });
211
+ };
212
+ const fetchMoreLevels = async (locationIds, level, index) => {
213
+ try {
214
+ const response = await retrieveNextLevel(
215
+ locationIds,
216
+ level,
217
+ fetchAccordingToUserAoi,
218
+ loggedInUser.languagePreference
219
+ );
220
+
221
+ if (fetchAccordingToUserAoi && response[0]?.locationDetails?.length === 1) {
222
+ response[0]?.locationDetails?.forEach((location) => {
223
+ fetchMoreLevels(location?.id, response[0].level + 1, index);
224
+ // updateAreaOfIntervention(index, [{ locationDetails: [location], level: response[0].level }]);
225
+ updateAreaOfIntervention(index, {
226
+ ...location,
227
+ level: response[0].level,
228
+ locationLabel: response[0].locationLabel,
229
+ });
230
+ });
231
+ }
232
+ } catch (error) {
233
+ console.error(error);
234
+ }
235
+ };
236
+
237
+ /**
238
+ * Adds location hierarchy by retrieving the next level of location details.
239
+ *
240
+ * @async
241
+ * @function addLocationHierarchy
242
+ * @param {Array} locationIds - Array of location IDs to fetch the next level of hierarchy.
243
+ * @param {number} level - The current level of location hierarchy being processed.
244
+ * @param {boolean} loadInit - Flag indicating whether this is the initial load of the location hierarchy.
245
+ * @returns {Promise<void>} - A Promise that resolves once the hierarchy has been added or updated.
246
+ * @throws {Error} Will throw an error if there is an issue retrieving the next level of locations.
247
+ */
248
+ const addLocationHierarchy = async (locationIds, level, loadInit) => {
249
+ try {
250
+ setLevelAoi(false);
251
+ const response = await retrieveNextLevel(
252
+ locationIds,
253
+ level,
254
+ fetchAccordingToUserAoi,
255
+ loggedInUser.languagePreference
256
+ );
257
+ if (fetchAccordingToUserAoi && response[0]?.locationDetails?.length > 1 && levelAoi) {
258
+ response[0].locationDetails?.forEach((location, index) => {
259
+ fetchMoreLevels(location?.id, response[0].level + 1, index);
260
+ updateAreaOfIntervention(index, {
261
+ ...location,
262
+ level: response[0].level,
263
+ locationLabel: response[0].locationLabel,
264
+ });
265
+ });
266
+ } else {
267
+ if (response && response.length > 0) {
268
+ if (allDistrictReq && level === 2 && allowedEnv.includes(presentEnv)) {
269
+ response[0].locationDetails.unshift(allRegion);
270
+ } else if (allBlockReq && level === 3 && allowedEnv.includes(presentEnv)) {
271
+ response[0].locationDetails.unshift(allBlocks);
272
+ }
273
+ const filteredLocations = response[0]?.locationDetails?.filter((loc) => loc.name !== null);
274
+ locationsRef.current = [...locationsRef.current, { ...response[0], locationDetails: filteredLocations }];
275
+ setLocations(() => locationsRef.current);
276
+ if (loadInit) {
277
+ setMinLevel(() => response[0].level);
278
+ if (requiredUptoLevel === 1) {
279
+ requiredUptoLevel = response[0].level;
280
+ }
281
+ }
282
+ } else if (requiredUptoLevel >= level) {
283
+ let nextLevelNames =
284
+ Array.isArray(locationTypes) && locationTypes.length
285
+ ? locationTypes.filter((type) => type.level === level).map((type) => type.name)
286
+ : [];
287
+ noLocationInHierarchyMessage =
288
+ Array.isArray(nextLevelNames) && nextLevelNames.length ? nextLevelNames.join('/') : null;
289
+ }
290
+ const previousLevel = level - 1;
291
+ if (
292
+ multipleOnLevel !== 2 &&
293
+ previousLevel === 2 &&
294
+ selectedLocationRef.current['level' + previousLevel] &&
295
+ selectedLocationRef.current['level' + level]
296
+ ) {
297
+ const previousSelected = selectedLocationRef.current['level' + previousLevel];
298
+ setValue(`level${previousLevel}`, previousSelected?.id);
299
+ }
300
+
301
+ let updatedSelectedLocation = {
302
+ ...selectedLocationRef.current,
303
+ optionsList: [],
304
+ };
305
+ locationsRef.current.forEach((location) => {
306
+ updatedSelectedLocation.optionsList['level' + location.level] = location.locationDetails;
307
+ });
308
+ selectedLocationRef.current = updatedSelectedLocation;
309
+ setSelectedLocation(() => updatedSelectedLocation);
310
+ }
311
+ } catch (error) {
312
+ console.error(error);
313
+ showToast({ message: 'Error adding hierarchy', type: 'error' });
314
+ }
315
+ };
316
+
317
+ /**
318
+ * Handles the location change event, updating the selected location hierarchy and fetching the next level if necessary.
319
+ *
320
+ * @async
321
+ * @function onLocationChange
322
+ * @param {Object} location - The currently selected location object.
323
+ * @param {boolean} loadInit - A flag to determine if this is the initial load.
324
+ * @returns {Promise<void>} - A Promise that resolves when the location hierarchy has been updated.
325
+ */
326
+
327
+ const onLocationChange = async (location, loadInit) => {
328
+ let locationIds = [];
329
+ let level;
330
+ if (
331
+ location ||
332
+ (selectedLocationRef.current.finalSelected && !selectedLocationRef.current?.finalSelected?.optionSelected?.id)
333
+ ) {
334
+ clearLowerLevelSelection(location?.level);
335
+ level = location.level + 1;
336
+ }
337
+
338
+ if (selectedLocationRef.current && location && selectedLocationRef.current['level' + location.level]) {
339
+ if (multipleOnLevel === location.level) {
340
+ locationIds = selectedLocationRef.current['level' + location.level].map((selected) => selected.id);
341
+ } else {
342
+ locationIds.push(selectedLocationRef.current['level' + location.level].id);
343
+ }
344
+ }
345
+ const locationSelected = JSON.parse(JSON.stringify(location));
346
+ if (location) {
347
+ locationSelected.optionSelected = selectedLocationRef.current['level' + location.level];
348
+ locationSelected['level' + location.level + 'options'] =
349
+ locationsRef.current[locationsRef.current.length - 1]?.locationDetails;
350
+ }
351
+ const updatedSelectedLocation = {
352
+ ...selectedLocationRef.current,
353
+ finalSelected: locationSelected,
354
+ };
355
+ selectedLocationRef.current = updatedSelectedLocation;
356
+ setSelectedLocation(() => updatedSelectedLocation);
357
+ if (
358
+ (((fetchUptoLevel && location && location.level + 1 <= fetchUptoLevel) || loadInit || !fetchUptoLevel) &&
359
+ selectedLocationRef.current.finalSelected &&
360
+ ((multipleOnLevel !== location.level && selectedLocationRef.current?.finalSelected?.optionSelected) ||
361
+ (multipleOnLevel === location.level &&
362
+ selectedLocationRef.current?.finalSelected?.optionSelected.length > 0))) ||
363
+ loadInit
364
+ ) {
365
+ // when selected location is not all blocks set relative parent
366
+ let level3Id;
367
+ if (level === 4 && multipleOnLevel === location.level) {
368
+ level3Id =
369
+ selectedLocationRef.current.level3 && selectedLocationRef.current.level3.length > 0
370
+ ? selectedLocationRef.current.level3[0].id
371
+ : -2;
372
+ } else if (level === 4) {
373
+ level3Id = selectedLocationRef.current.level3.id;
374
+ }
375
+ if (level === 4 && level3Id !== -2) {
376
+ getParent(level3Id, loggedInUser.languagePreference)
377
+ .then((res) => {
378
+ const updatedSelectedLocation = {
379
+ ...selectedLocationRef.current,
380
+ level2: res,
381
+ };
382
+ selectedLocationRef.current = updatedSelectedLocation;
383
+ setSelectedLocation(() => updatedSelectedLocation);
384
+ const newLocations = [...locationsRef.current];
385
+ newLocations.pop();
386
+ locationsRef.current = newLocations;
387
+ setLocations(() => locationsRef.current);
388
+ // setValue(`level2`, res.id);
389
+
390
+ addLocationHierarchy([res.id], 3, loadInit).then(function () {
391
+ addLocationHierarchy(locationIds, level, loadInit);
392
+ });
393
+ })
394
+ .catch((error) => {
395
+ console.error('API Call Error', error);
396
+ });
397
+ } else if (level === 4 && level3Id === -2 && allowedEnv.includes(presentEnv)) {
398
+ const updatedSelectedLocation = {
399
+ ...selectedLocationRef.current,
400
+ level2: allRegion,
401
+ };
402
+ selectedLocationRef.current = updatedSelectedLocation;
403
+ setSelectedLocation(() => updatedSelectedLocation);
404
+ const newLocations = [...locationsRef.current];
405
+ newLocations.pop();
406
+ locationsRef.current = newLocations;
407
+ setLocations(() => locationsRef.current);
408
+ addLocationHierarchy([-1], 3, loadInit).then(function () {
409
+ addLocationHierarchy(locationIds, level, loadInit);
410
+ });
411
+ } else if (level === 2 && fetchUptoLevel !== level) {
412
+ addLocationHierarchy(locationIds, level, loadInit).then(function () {
413
+ addLocationHierarchy(locationIds, level + 1, loadInit);
414
+ });
415
+ } else {
416
+ await addLocationHierarchy(locationIds, level, loadInit);
417
+ }
418
+ } else if (
419
+ selectedLocationRef.current?.finalSelected?.optionSelected &&
420
+ fetchUptoLevel &&
421
+ location &&
422
+ location.level === 3 &&
423
+ location.level === fetchUptoLevel
424
+ ) {
425
+ let level3Id;
426
+ if (multipleOnLevel) {
427
+ level3Id =
428
+ selectedLocationRef.current.level3 && selectedLocationRef.current.level3.length > 0
429
+ ? selectedLocationRef.current.level3[0].id
430
+ : -2;
431
+ } else {
432
+ level3Id = selectedLocationRef.current.level3.id;
433
+ }
434
+ getParent(level3Id, loggedInUser.languagePreference)
435
+ .then(function (res) {
436
+ const updatedSelectedLocation = {
437
+ ...selectedLocationRef.current,
438
+ level2: res,
439
+ };
440
+ selectedLocationRef.current = updatedSelectedLocation;
441
+ setSelectedLocation(() => updatedSelectedLocation);
442
+ const newLocations = [...locationsRef.current];
443
+ newLocations.pop();
444
+ locationsRef.current = newLocations;
445
+ setLocations(() => locationsRef.current);
446
+ setValue(`level2`, res.id);
447
+ addLocationHierarchy([res.id], 3, loadInit);
448
+ })
449
+ .catch((error) => {
450
+ showToast({ message: `Api Call Failure ${error}`, type: 'error' });
451
+ });
452
+ }
453
+
454
+ // to get previous level details when option is unselected;
455
+ else if (
456
+ (multipleOnLevel !== location.level && !selectedLocationRef.current?.finalSelected?.optionSelected) ||
457
+ (multipleOnLevel === location.level && selectedLocationRef.current?.finalSelected?.optionSelected.length === 0)
458
+ ) {
459
+ level = location.level - 1;
460
+ if (level === 1) {
461
+ addLocationHierarchy([2], 3, loadInit);
462
+ }
463
+
464
+ let previousLevel = locationsRef.current.find((location) => location.level === level);
465
+
466
+ if (previousLevel) {
467
+ const updatedSelectedLocation = {
468
+ ...selectedLocationRef.current,
469
+ finalSelected: {
470
+ ...selectedLocationRef.current.finalSelected,
471
+ previousLevelLabel: previousLevel.locationLabel,
472
+ previousLevelOptions: previousLevel.locationDetails,
473
+ },
474
+ };
475
+ selectedLocationRef.current = updatedSelectedLocation;
476
+ setSelectedLocation(() => updatedSelectedLocation);
477
+ }
478
+ if (selectedLocationRef.current['level' + level]) {
479
+ if (multipleOnLevel === level) {
480
+ selectedIdRef.current = selectedLocationRef.current['level' + level].map((selected) => selected.id);
481
+ setSelectedId(() => selectedIdRef.current);
482
+ } else {
483
+ if (multipleOnLevel) {
484
+ let ids = [];
485
+ ids.push(selectedLocationRef.current['level' + level].id);
486
+ selectedIdRef.current = ids;
487
+ setSelectedId(() => selectedIdRef.current);
488
+ } else {
489
+ selectedIdRef.current = selectedLocationRef.current['level' + level].id;
490
+ setSelectedId(() => selectedIdRef.current);
491
+ }
492
+ }
493
+ } else {
494
+ selectedIdRef.current = null;
495
+ setSelectedId(() => selectedIdRef.current);
496
+ }
497
+ }
498
+
499
+ if (
500
+ !loadInit &&
501
+ selectedLocationRef.current &&
502
+ ((multipleOnLevel !== location.level && selectedLocationRef.current?.finalSelected?.optionSelected) ||
503
+ (multipleOnLevel === location.level && selectedLocationRef.current?.finalSelected?.optionSelected.length > 0))
504
+ ) {
505
+ if (multipleOnLevel) {
506
+ let finalLocationIds = [];
507
+ if (Array.isArray(selectedLocationRef.current?.finalSelected?.optionSelected)) {
508
+ finalLocationIds = selectedLocationRef.current.finalSelected.optionSelected.map((selected) => selected.id);
509
+ } else {
510
+ finalLocationIds.push(selectedLocationRef.current.finalSelected.optionSelected.id);
511
+ }
512
+ selectedIdRef.current = finalLocationIds;
513
+ setSelectedId(() => selectedIdRef.current);
514
+ } else {
515
+ selectedIdRef.current = selectedLocationRef.current.finalSelected.optionSelected.id;
516
+ setSelectedId(() => selectedIdRef.current);
517
+ }
518
+ }
519
+ onChange && onChange(selectedLocationRef.current);
520
+ };
521
+
522
+ /**
523
+ * Handles the first run logic for location selection, setting the initial location details if only one option is available.
524
+ *
525
+ * @function onFirstRun
526
+ * @param {Object} location - The location object containing location details and level.
527
+ * @param {Array} location.locationDetails - Array of location details at the current level.
528
+ * @param {number} location.level - The current level of the location hierarchy.
529
+ */
530
+
531
+ const onFirstRun = (location) => {
532
+ if (onFirstRunTemp && location.locationDetails.length === 1) {
533
+ const updatedLocations = {
534
+ ...selectedLocationRef.current,
535
+ [`level${location.level}`]: location.locationDetails[0],
536
+ level: location.level,
537
+ };
538
+ selectedLocationRef.current = updatedLocations;
539
+ setSelectedLocation(() => updatedLocations);
540
+ onLocationChange(selectedLocationRef.current, false);
541
+ setOnFirstRunTemp(() => false);
542
+
543
+ setValue(`level${location.level}`, updatedLocations[`level${location.level}`]?.id);
544
+ }
545
+ };
546
+
547
+ // Initialization logic for first dropdown
548
+ const initializeLocationDirective = () => {
549
+ retrieveLocationTypes();
550
+ demographicFilterRequired = demographicFilterRequired === 'true' && fetchAccordingToUserAoi !== 'false';
551
+
552
+ if (!allDistrictReq || allDistrictReq === 'false') {
553
+ allDistrictReq = false;
554
+ } else if (demographicFilterRequired === 'true') {
555
+ allDistrictReq = true;
556
+ }
557
+
558
+ if (!allBlockReq || allBlockReq === 'false') {
559
+ allBlockReq = false;
560
+ } else if (demographicFilterRequired === 'true') {
561
+ allBlockReq = true;
562
+ }
563
+
564
+ fetchAccordingToUserAoi = fetchAccordingToUserAoi && fetchAccordingToUserAoi !== 'false';
565
+ if (selectedLocation && selectedLocation.finalSelected) {
566
+ let prevSelectedLocation = JSON.parse(JSON.stringify(selectedLocation));
567
+ onLocationChange(null, true);
568
+ setOnFirstRunTemp(() => true);
569
+ for (let i = 1; i <= prevSelectedLocation?.finalSelected?.level; i++) {
570
+ let name = 'level' + i;
571
+ setTimeout(() => {
572
+ handleLocationUpadte(name, prevSelectedLocation[name]?.id);
573
+ if (i === prevSelectedLocation?.finalSelected?.level) {
574
+ setShowDirective(true);
575
+ }
576
+ }, 500 * i);
577
+ }
578
+ } else {
579
+ onLocationChange(null, true);
580
+ setOnFirstRunTemp(true);
581
+ setShowDirective(true);
582
+ }
583
+ };
584
+
585
+ // Initial mount effect: only run if resetKey is undefined (first mount)
586
+ useEffect(() => {
587
+ if (resetKey === undefined) {
588
+ initializeLocationDirective();
589
+ }
590
+ }, [resetKey]);
591
+
592
+ /**
593
+ * useEffect hook to handle the first run logic for location hierarchy based on the locations in `locationsRef`.
594
+ *
595
+ * @function useEffect
596
+ * @param {Array} locationsRef.current - The current array of location objects.
597
+ */
598
+
599
+ useEffect(() => {
600
+ if (onFirstRunTemp) {
601
+ locationsRef.current.forEach((location) => {
602
+ onFirstRun(location);
603
+ });
604
+ }
605
+ }, [locationsRef.current]);
606
+
607
+ /**
608
+ * useEffect hook to clear lower-level selections and reset messages based on changes to `selectedLocationRef.current`.
609
+ *
610
+ * @function useEffect
611
+ * @param {Object} selectedLocationRef.current - The current state of selected location details.
612
+ */
613
+
614
+ useEffect(() => {
615
+ noLocationInHierarchyMessage = null;
616
+ if (Object.keys(selectedLocationRef.current).length === 0) {
617
+ clearLowerLevelSelection(minLevel);
618
+ }
619
+ }, [selectedLocationRef.current]);
620
+
621
+ let methods;
622
+ if (childForm) {
623
+ methods = useFormContext();
624
+ } else {
625
+ methods = useForm({ mode: 'all' });
626
+ }
627
+
628
+ const {
629
+ control,
630
+ setValue,
631
+ formState: { errors },
632
+ } = methods;
633
+
634
+ // Reset logic when resetKey changes
635
+ useEffect(() => {
636
+ if (resetKey !== undefined) {
637
+ setLocations([]);
638
+ setAreaOfIntervention([]);
639
+ locationsRef.current = [];
640
+ setShowDirective(false);
641
+ setOnFirstRunTemp(false);
642
+ setMinLevel(1);
643
+ setLevelAoi(true);
644
+ if (selectedLocationRef && typeof selectedLocationRef === 'object') {
645
+ selectedLocationRef.current = {};
646
+ }
647
+ if (setSelectedLocation) setSelectedLocation({});
648
+ if (selectedIdRef && typeof selectedIdRef === 'object') {
649
+ selectedIdRef.current = '';
650
+ }
651
+ if (setSelectedId) setSelectedId('');
652
+ // Reset all form fields related to location
653
+ if (methods && methods.resetField) {
654
+ const fieldsToReset = ['level1', 'level2', 'level3', 'level4', 'AOI', 'selectedDemographic'];
655
+ fieldsToReset.forEach((field) => methods.resetField(field));
656
+ } else if (methods && methods.setValue) {
657
+ const fieldsToReset = ['level1', 'level2', 'level3', 'level4', 'AOI', 'selectedDemographic'];
658
+ fieldsToReset.forEach((field) => methods.setValue(field, undefined));
659
+ }
660
+ // Trigger initial dropdown rendering after reset
661
+ initializeLocationDirective();
662
+ }
663
+ }, [resetKey]);
664
+
665
+ if (noLocationInHierarchyMessage) {
666
+ return (
667
+ <div data-testid="locationdirective-error-message" className="text-red-500">
668
+ Could not retrieve {noLocationInHierarchyMessage}. Please add it first
669
+ </div>
670
+ );
671
+ }
672
+
673
+ if (showDirective && templateType === 'inline') {
674
+ return (
675
+ <LocationDirectiveSkeleton isLoading={isLoading}>
676
+ <Grid container component="form" direction="column">
677
+ {fetchAccordingToUserAoi && areaOfIntervention?.length > 1 && (
678
+ <Grid
679
+ size={{ xs: 12, sm: 12, md: 12, lg: 12 }}
680
+ data-testid={`locationdirective-inline-location-area-of-intervention`}
681
+ >
682
+ <InputLabel
683
+ // required={location.level <= requiredUptoLevel}
684
+ data-testid={`locationdirective-inline-location-label-area-of-intervention`}
685
+ >
686
+ {translate('Area of Intervention')}
687
+ </InputLabel>
688
+ <CustomDropdown
689
+ control={control}
690
+ id={`AOI`}
691
+ name={`AOI`}
692
+ size={size}
693
+ options={areaOfIntervention}
694
+ displayName="name"
695
+ optionValue="id"
696
+ multiple={3 === multipleOnLevel}
697
+ errors={errors}
698
+ onChange={handleAreaOfIntervention}
699
+ // rules={{
700
+ // required: {
701
+ // value: areaOfIntervention[0].level <= requiredUptoLevel,
702
+ // message: `Please Select Location Level ${areaOfIntervention[0].level}`,
703
+ // },
704
+ // }}
705
+ // dataTestId={`areaOfIntervention[0]directive-inline-dropdown-${areaOfIntervention[0].level}`}
706
+ className="mb-4"
707
+ />
708
+ </Grid>
709
+ )}
710
+ {locationsRef.current.length > 0 &&
711
+ locationsRef.current.map((location, index) => (
712
+ <Grid
713
+ size={{ xs: 12, sm: 12, md: 12, lg: 12 }}
714
+ key={location.id || index}
715
+ data-testid={`locationdirective-inline-location-${location.id || index}`}
716
+ >
717
+ <InputLabel
718
+ required={location.level <= requiredUptoLevel}
719
+ data-testid={`locationdirective-inline-location-label-${location.id || index}`}
720
+ >
721
+ {translate(location.locationLabel)}
722
+ </InputLabel>
723
+ <CustomDropdown
724
+ control={control}
725
+ id={`location${location.level}`}
726
+ name={`level${location.level}`}
727
+ size={size}
728
+ options={location.locationDetails}
729
+ displayName="name"
730
+ optionValue="id"
731
+ errors={errors}
732
+ onChange={handleLocationSelect}
733
+ multiple={location.level === multipleOnLevel}
734
+ rules={{
735
+ required: {
736
+ value: location.level <= requiredUptoLevel,
737
+ message: `Please Select ${location.locationLabel}`,
738
+ },
739
+ }}
740
+ dataTestId={`locationdirective-inline-dropdown-${location.level}`}
741
+ className="mb-4"
742
+ />
743
+ </Grid>
744
+ ))}
745
+ {demographicFilterRequired && (
746
+ <Grid size={{ xs: 12, sm: 12, md: 12, lg: 12 }} className="mb-[5px]">
747
+ <InputLabel className="text-[14px]">{translate('Demographic')}</InputLabel>
748
+ <CustomDropdown
749
+ control={control}
750
+ id="demographic-filter"
751
+ name="selectedDemographic"
752
+ size={size}
753
+ options={demographicOptions}
754
+ optionValue="value"
755
+ displayName="key"
756
+ onChange={handleDemographicChange}
757
+ dataTestId="locationdirective-inline-demographic-dropdown"
758
+ />
759
+ </Grid>
760
+ )}
761
+ </Grid>
762
+ </LocationDirectiveSkeleton>
763
+ );
764
+ } else if (showDirective && templateType === 'twoPart') {
765
+ return (
766
+ <LocationDirectiveSkeleton isLoading={isLoading}>
767
+ <Grid container spacing={2} component="form" className="pb-[1.5rem]" direction="row" width="100%">
768
+ {fetchAccordingToUserAoi && areaOfIntervention?.length > 1 && (
769
+ <Grid
770
+ size={{ xs: 12, sm: 12, md: 12, lg: 12 }}
771
+ data-testid={`locationdirective-inline-location-area-of-intervention`}
772
+ >
773
+ <InputLabel
774
+ // required={location.level <= requiredUptoLevel}
775
+ data-testid={`locationdirective-inline-location-label-area-of-intervention`}
776
+ >
777
+ {translate('Area of Intervention')}
778
+ </InputLabel>
779
+ <CustomDropdown
780
+ control={control}
781
+ id={`AOI`}
782
+ name={`AOI`}
783
+ size={size}
784
+ options={areaOfIntervention}
785
+ displayName="name"
786
+ optionValue="id"
787
+ multiple={3 === multipleOnLevel}
788
+ errors={errors}
789
+ onChange={handleAreaOfIntervention}
790
+ // rules={{
791
+ // required: {
792
+ // value: areaOfIntervention[0].level <= requiredUptoLevel,
793
+ // message: `Please Select Location Level ${areaOfIntervention[0].level}`,
794
+ // },
795
+ // }}
796
+ // dataTestId={`areaOfIntervention[0]directive-inline-dropdown-${areaOfIntervention[0].level}`}
797
+ className="mb-4"
798
+ />
799
+ </Grid>
800
+ )}
801
+ {locationsRef.current.length > 0 &&
802
+ locationsRef.current.map((location, index) => (
803
+ <Grid
804
+ size={{ xs: 12, sm: 6, md: 6 }}
805
+ key={location.id || index}
806
+ data-testid={`locationdirective-two-part-location-${location.id || index}`}
807
+ >
808
+ <InputLabel
809
+ className="text-[14px]"
810
+ required={location.level <= requiredUptoLevel}
811
+ data-testid={`locationdirective-two-part-location-label-${location.id || index}`}
812
+ >
813
+ {translate(location.locationLabel)}
814
+ </InputLabel>
815
+ <CustomDropdown
816
+ control={control}
817
+ id={`location${location.level}`}
818
+ name={`level${location.level}`}
819
+ size={size}
820
+ options={location.locationDetails}
821
+ displayName="name"
822
+ optionValue="id"
823
+ errors={errors}
824
+ onChange={handleLocationSelect}
825
+ rules={{
826
+ required: {
827
+ value: location.level <= requiredUptoLevel,
828
+ message: `Please Select ${location.locationLabel}`,
829
+ },
830
+ }}
831
+ dataTestId={`locationdirective-two-part-dropdown-${location.level}`}
832
+ />
833
+ </Grid>
834
+ ))}
835
+ </Grid>
836
+ </LocationDirectiveSkeleton>
837
+ );
838
+ } else if (showDirective && templateType === 'linear') {
839
+ return (
840
+ <LocationDirectiveSkeleton isLoading={isLoading}>
841
+ <Grid container component="form" direction="column">
842
+ {fetchAccordingToUserAoi && areaOfIntervention?.length > 1 && (
843
+ <Grid
844
+ size={{ xs: 12, sm: 12, md: 12, lg: 12 }}
845
+ data-testid={`locationdirective-inline-location-area-of-intervention`}
846
+ >
847
+ <InputLabel
848
+ // required={location.level <= requiredUptoLevel}
849
+ data-testid={`locationdirective-inline-location-label-area-of-intervention`}
850
+ >
851
+ {translate('Area of Intervention')}
852
+ </InputLabel>
853
+ <CustomDropdown
854
+ control={control}
855
+ id={`AOI`}
856
+ name={`AOI`}
857
+ size={size}
858
+ options={areaOfIntervention}
859
+ displayName="name"
860
+ optionValue="id"
861
+ multiple={3 === multipleOnLevel}
862
+ errors={errors}
863
+ onChange={handleAreaOfIntervention}
864
+ // rules={{
865
+ // required: {
866
+ // value: areaOfIntervention[0].level <= requiredUptoLevel,
867
+ // message: `Please Select Location Level ${areaOfIntervention[0].level}`,
868
+ // },
869
+ // }}
870
+ // dataTestId={`areaOfIntervention[0]directive-inline-dropdown-${areaOfIntervention[0].level}`}
871
+ className="mb-4"
872
+ />
873
+ </Grid>
874
+ )}
875
+ {locationsRef.current.length > 0 &&
876
+ locationsRef.current.map((location, index) => (
877
+ <Grid
878
+ size={{ xs: 12, sm: 12, md: 12, lg: 12 }}
879
+ className="m-2 flex flex-row justify-between items-center"
880
+ key={location.id || index}
881
+ data-testid={`locationdirective-inline-location-${location.id || index}`}
882
+ >
883
+ <Grid size={{ xs: 3 }}>
884
+ <InputLabel
885
+ className="text-sm break-words whitespace-pre-wrap text-black"
886
+ required={location.level <= requiredUptoLevel}
887
+ data-testid={`locationdirective-inline-location-label-${location.id || index}`}
888
+ >
889
+ {translate(location.locationLabel)}
890
+ </InputLabel>
891
+ </Grid>
892
+ <Grid size={{ xs: 8 }}>
893
+ <CustomDropdown
894
+ control={control}
895
+ id={`location${location.level}`}
896
+ name={`level${location.level}`}
897
+ size={size}
898
+ options={location.locationDetails}
899
+ displayName="name"
900
+ optionValue="id"
901
+ errors={errors}
902
+ onChange={handleLocationSelect}
903
+ rules={{
904
+ required: {
905
+ value: location.level <= requiredUptoLevel,
906
+ message: `Please Select ${location.locationLabel}`,
907
+ },
908
+ }}
909
+ multiple={location.level === multipleOnLevel}
910
+ dataTestId={`locationdirective-inline-dropdown-${location.level}`}
911
+ />
912
+ </Grid>
913
+ </Grid>
914
+ ))}
915
+ {demographicFilterRequired && (
916
+ <Grid size={{ xs: 12, sm: 12, md: 12, lg: 12 }} className="mb-[5px]">
917
+ <InputLabel className="text-[14px]">{translate('Demographic')}</InputLabel>
918
+ <CustomDropdown
919
+ control={control}
920
+ id="demographic-filter"
921
+ name="selectedDemographic"
922
+ size={size}
923
+ options={demographicOptions}
924
+ optionValue="value"
925
+ displayName="key"
926
+ onChange={handleDemographicChange}
927
+ dataTestId="locationdirective-inline-demographic-dropdown"
928
+ />
929
+ </Grid>
930
+ )}
931
+ </Grid>
932
+ </LocationDirectiveSkeleton>
933
+ );
934
+ }
935
+ };
936
+
937
+ export default LocationDirective;
938
+
939
+ LocationDirective.propTypes = {
940
+ childForm: PropTypes.any,
941
+ setSelectedLocation: PropTypes.any,
942
+ selectedLocationRef: PropTypes.any,
943
+ templateType: PropTypes.any,
944
+ fetchAccordingToUserAoi: PropTypes.any,
945
+ demographicFilterRequired: PropTypes.any,
946
+ requiredUptoLevel: PropTypes.any,
947
+ fetchUptoLevel: PropTypes.any,
948
+ multipleOnLevel: PropTypes.any,
949
+ allDistrictReq: PropTypes.any,
950
+ allBlockReq: PropTypes.any,
951
+ setSelectedId: PropTypes.any,
952
+ selectedIdRef: PropTypes.any,
953
+ size: PropTypes.any,
954
+ selectedLocation: PropTypes.any,
955
+ isLoading: PropTypes.any,
956
+ onChange: PropTypes.any,
957
+ resetKey: PropTypes.any,
958
+ };
959
+
960
+ const LocationDirectiveSkeleton = ({ children, isLoading }) => {
961
+ const useSkeleton = useSelector(getUseSkeleton);
962
+ if (!useSkeleton) {
963
+ return children;
964
+ }
965
+ if (!isLoading) {
966
+ return children;
967
+ }
968
+
969
+ return (
970
+ <div className=" p-3">
971
+ <div className="flex flex-col space-y-4">
972
+ <div className="flex flex-row ">
973
+ <button className="bg-gray-300 animate-pulse mr-[50px] rounded-sm w-[70px] h-[30px]"></button>
974
+ <button className="bg-gray-300 animate-pulse rounded-sm w-60 h-[30px]"></button>
975
+ </div>
976
+ <div className="flex flex-row ">
977
+ <button className="bg-gray-300 animate-pulse mr-[50px] rounded-sm w-[70px] h-[30px]"></button>
978
+ <button className="bg-gray-300 animate-pulse rounded-sm w-60 h-[30px]"></button>
979
+ </div>
980
+ <div className="flex flex-row ">
981
+ <button className="bg-gray-300 animate-pulse mr-[50px] rounded-sm w-[70px] h-[30px]"></button>
982
+ <button className="bg-gray-300 animate-pulse rounded-sm w-60 h-[30px]"></button>
983
+ </div>
984
+ </div>
985
+ </div>
986
+ );
987
+ };
988
+
989
+ LocationDirectiveSkeleton.propTypes = {
990
+ children: PropTypes.any,
991
+ isLoading: PropTypes.any,
992
+ };