@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.
- package/package.json +139 -141
- package/src/GlobalErrorBoundary.jsx +31 -0
- package/src/SilentErrorFallback.jsx +68 -0
- package/src/TrackingProviderWrapper.jsx +40 -0
- package/src/_tests_/__mocks__/MockTranslationProvider.jsx +21 -0
- package/src/_tests_/__mocks__/ckeditor.js +45 -0
- package/src/_tests_/__mocks__/fileMock.js +1 -0
- package/src/_tests_/__mocks__/useranalytics.js +5 -0
- package/src/_tests_/views/components/Dashboard/DashboardUI.test.jsx +137 -0
- package/src/_tests_/views/components/Dashboard/DashboardUIMock.js +877 -0
- package/src/_tests_/views/components/ForgotPassword/ForgotPassword.test.jsx +314 -0
- package/src/_tests_/views/components/LocationDirective/LocationDirective.test.jsx.disable +229 -0
- package/src/_tests_/views/components/LocationDirective/mockLocationDirective.js +810 -0
- package/src/_tests_/views/components/LocationType/MockLocationType.js +42259 -0
- package/src/_tests_/views/components/LocationType/addlocationtype.test.jsx.disable +276 -0
- package/src/_tests_/views/components/LocationType/editlocationtype.test.jsx.disable +262 -0
- package/src/_tests_/views/components/LocationType/locationtype.test.jsx.disable +148 -0
- package/src/_tests_/views/components/Profile/UpdateProfileModalData.js +4396 -0
- package/src/_tests_/views/components/Profile/updateprofilemodal.test.jsx +282 -0
- package/src/_tests_/views/components/SideBar/MockSideBar.js +1379 -0
- package/src/_tests_/views/components/SideBar/SideBar.test.jsx +98 -0
- package/src/_tests_/views/components/SystemConfig/ManageSystemConfig/AddManageSystemConfig.test.jsx.disable +164 -0
- package/src/_tests_/views/components/SystemConfig/ManageSystemConfig/UpdateManageSystemConfig.test.jsx.disable +157 -0
- package/src/_tests_/views/components/SystemConfig/MockSystemConfig.js +1280 -0
- package/src/_tests_/views/components/SystemConfig/SystemConfig.test.jsx.disable +165 -0
- package/src/_tests_/views/components/login/Login.test.jsx +276 -0
- package/src/_tests_/views/components/login/MockAuthorise.js +2414 -0
- package/src/_tests_/views/components/login/ServiceResponse.js +595 -0
- package/src/_tests_/views/components/user/MockManageUser.js +7965 -0
- package/src/_tests_/views/components/user/manageuser.test.jsx.disable +989 -0
- package/src/_tests_/views/components/user/mockUsersData.js +582 -0
- package/src/assets/img/OASISLogin.png +0 -0
- package/src/assets/img/bahaarNew.png +0 -0
- package/src/assets/img/dnhdd4K.png +0 -0
- package/src/assets/img/govtofup.png +0 -0
- package/src/assets/img/sewarural4K.png +0 -0
- package/src/assets/img/techo4K.png +0 -0
- package/src/assets/img/up4K.png +0 -0
- package/src/common/HolidayList.jsx +573 -0
- package/src/common/MalaciaousInputUtil.js +23 -0
- package/src/common/SafeHtml.jsx +17 -0
- package/src/common/VersionManager.jsx +109 -0
- package/src/common/constants/PerformanceDashboard.js +514 -0
- package/src/common/constants/app.constant.js +781 -0
- package/src/common/constants/cccVerificationConstants.js +18 -0
- package/src/common/constants/fhsrConstant.js +33 -0
- package/src/common/constants/gvk-verification.constant.js +76 -0
- package/src/common/constants/search.constant.js +23 -0
- package/src/common/constants/teleconsulatationConstant.jsx +1339 -0
- package/src/common/directives/SearchTemplate.jsx +784 -0
- package/src/common/directives/SearchTemplate.scss +14 -0
- package/src/common/dynamicView/DynamicView.jsx +353 -0
- package/src/common/dynamicView/InputFieldComponent.jsx +1501 -0
- package/src/common/dynamicView/InputViewComponent.jsx +298 -0
- package/src/common/dynamicView/InputViewComponent.scss +15 -0
- package/src/common/env.js +5 -0
- package/src/common/filters/locationNameFilter.js +26 -0
- package/src/common/fontAwesomeIcons/FontAwesomeIcons.jsx +27 -0
- package/src/common/fontAwesomeIcons/FontAwesomeIconsNames.js +1968 -0
- package/src/common/fontPreferences/fontSizeProvider.jsx +34 -0
- package/src/common/fontPreferences/fontSizeSelector.jsx +116 -0
- package/src/common/getAssignedFeature/getAssignedFeature.js +32 -0
- package/src/common/interceptors/AxiosInterceptor.js +216 -0
- package/src/common/languageTranslator/TranslationContext.js +5 -0
- package/src/common/languageTranslator/TranslationProvider.jsx +24 -0
- package/src/common/languageTranslator/i18n.js +49 -0
- package/src/common/services/AuthenticateService.js +116 -0
- package/src/common/services/DownloadFile.js +35 -0
- package/src/common/services/ForgotPassword.js +18 -0
- package/src/common/services/FormConfiguratorService.js +195 -0
- package/src/common/services/GlobalApis.js +84 -0
- package/src/common/services/InterceptorNavigationService.js +17 -0
- package/src/common/services/LocationService.js +65 -0
- package/src/common/services/LocationType.js +11 -0
- package/src/common/services/QueryBuilder.js +36 -0
- package/src/common/services/Roles.js +28 -0
- package/src/common/services/SyncWithServer.js +15 -0
- package/src/common/services/SystemConfig.js +15 -0
- package/src/common/services/TranslationService.js +70 -0
- package/src/common/services/TwoFactorService.js +7 -0
- package/src/common/services/Users.js +91 -0
- package/src/common/services/Webtasks.js +27 -0
- package/src/common/services/util/Convert-pad-data-to-API-format.jsx +167 -0
- package/src/common/services/util/Convert-to-UI-format.jsx +82 -0
- package/src/common/services/util/EmptyPrescriptionPadData.jsx +11 -0
- package/src/common/services/util/GeneralUtil.js +456 -0
- package/src/common/services/util/Prescription-pad-util.js +339 -0
- package/src/common/services/util/PrescriptionPadData.js +67 -0
- package/src/common/services/util/PrescriptionpadCommonUtil.js +96 -0
- package/src/common/services/util/ReportFieldUtil.jsx +398 -0
- package/src/common/services/util/WebSocketContext.jsx +261 -0
- package/src/common/syncWithServer/SyncWithServerDialog.jsx +170 -0
- package/src/common/syncWithServer/SyncWithServerDialogSkeleton.jsx +67 -0
- package/src/common/tests/CustomWrapper.jsx +49 -0
- package/src/common/tests/TranslationWrapper.jsx +38 -0
- package/src/common/themeProvider/ColorInputs.jsx +97 -0
- package/src/common/themeProvider/EditableColorInput.jsx +128 -0
- package/src/common/themeProvider/ThemeEditor.jsx +319 -0
- package/src/common/themeProvider/ThemeProvider.jsx +210 -0
- package/src/common/themeProvider/themeConfig.js +558 -0
- package/src/common/toaster/toaster.jsx +30 -0
- package/src/firebaseConfig.js +24 -0
- package/src/global.scss +221 -0
- package/src/hooks/.gitkeep +0 -0
- package/src/hooks/useAESEncryption.js +56 -0
- package/src/hooks/useCaching.js +43 -0
- package/src/hooks/useDebounce.js +34 -0
- package/src/hooks/useDebounceFn.js +50 -0
- package/src/hooks/useDownloadPdf.js +358 -0
- package/src/hooks/useDownloadXlsx.js +55 -0
- package/src/hooks/useListValueFieldValues.js +30 -0
- package/src/hooks/useLocationHierarchies.js +63 -0
- package/src/hooks/useLocationHierarchyTranslate.js +16 -0
- package/src/hooks/useOnline.js +27 -0
- package/src/hooks/usePagination.js +63 -0
- package/src/hooks/useRefreshToken.js +87 -0
- package/src/hooks/useScript.js +25 -0
- package/src/hooks/useStopwatch.js +75 -0
- package/src/hooks/useTrackEvent.js +22 -0
- package/src/hooks/useWebAudioRecorder.js +115 -0
- package/src/layout/LoaderComponet.jsx +22 -0
- package/src/layout/LoaderContext.jsx +29 -0
- package/src/layout/mainLayout/AdaptiveZoom.jsx +27 -0
- package/src/layout/mainLayout/Chatbot.jsx +243 -0
- package/src/layout/mainLayout/Layout.jsx +445 -0
- package/src/layout/mainLayout/Profile/UpdateProfileModal.jsx +684 -0
- package/src/layout/mainLayout/header/LogoutModal.jsx +131 -0
- package/src/layout/mainLayout/header/Navbar.jsx +1677 -0
- package/src/layout/mainLayout/header/Navbar.scss +4 -0
- package/src/layout/mainLayout/header/index.js +0 -0
- package/src/layout/mainLayout/sidebar/SideBar.jsx +1402 -0
- package/src/layout/mainLayout/sidebar/Sidebar.css +159 -0
- package/src/layout/mainLayout/sidebar/index.js +0 -0
- package/src/logo.svg +1 -0
- package/src/reportWebVitals.js +13 -0
- package/src/setupFirebaseMessaging.js +28 -0
- package/src/setupTests.js +8 -0
- package/src/store/actions/AuthenticationActions.js +0 -0
- package/src/store/actions/ReportsActions.js +0 -0
- package/src/store/actions/TranslationAction.js +0 -0
- package/src/store/index.js +8 -0
- package/src/store/reducer.js +46 -0
- package/src/store/reducers/AuthenticationReducer.js +50 -0
- package/src/store/reducers/CalendarEventReducer.js +41 -0
- package/src/store/reducers/ConditionClipboardReducer.js +45 -0
- package/src/store/reducers/FeatureReducer.js +27 -0
- package/src/store/reducers/FormConfiguratorReducer.js +38 -0
- package/src/store/reducers/LoadingReducer.js +20 -0
- package/src/store/reducers/MembersAuthenticationReducer.js +28 -0
- package/src/store/reducers/PrescriptionPadReducer.js +329 -0
- package/src/store/reducers/QuestionaireReducer.js +29 -0
- package/src/store/reducers/ReportsReducer.js +24 -0
- package/src/store/reducers/SkeletonReducer.js +20 -0
- package/src/store/reducers/ThemeReducer.js +106 -0
- package/src/store/reducers/TranslationReducer.js +126 -0
- package/src/store/reducers/dashboardEditorSlice.js +77 -0
- package/src/store/reducers/districtHealthDashboardSlice.js +58 -0
- package/src/store/reducers/immunizationSlice.js +234 -0
- package/src/store/slices/dashboardPagesSlice.js +51 -0
- package/src/utils/.gitkeep +0 -0
- package/src/utils/FormConstants.js +2629 -0
- package/src/utils/GujaratTopoChart.jsx +483 -0
- package/src/utils/UUIDgenerator.js +8 -0
- package/src/utils/appointment-utils/appointment-utils.js +123 -0
- package/src/utils/feature.js +42 -0
- package/src/utils/getThemeColor.js +12 -0
- package/src/utils/localStorageHelper.js +11 -0
- package/src/utils/notifications/enable-push-notifications.js +27 -0
- package/src/utils/resolveAppliedStyle.js +11 -0
- package/src/utils/themeConfigs.js +1483 -0
- package/src/views/custom-components/.gitkeep +0 -0
- package/src/views/custom-components/AgIconButton/RIf.jsx +14 -0
- package/src/views/custom-components/AgIconButton/button.jsx +108 -0
- package/src/views/custom-components/AgIconButton/waterDrop.jsx +95 -0
- package/src/views/custom-components/AgIconButton/waterDrop.scss +37 -0
- package/src/views/custom-components/AlertPlaceholder.jsx +32 -0
- package/src/views/custom-components/AllFaIconsSelector.jsx +56 -0
- package/src/views/custom-components/CkEditor/CkEditor.js +102 -0
- package/src/views/custom-components/CustomAccordion.jsx +72 -0
- package/src/views/custom-components/CustomActionIcons.jsx +118 -0
- package/src/views/custom-components/CustomAutoComplete.jsx +188 -0
- package/src/views/custom-components/CustomCheckBox.jsx +60 -0
- package/src/views/custom-components/CustomConfirmationModal.jsx +118 -0
- package/src/views/custom-components/CustomCountrySelect.jsx +129 -0
- package/src/views/custom-components/CustomDatePicker.jsx +122 -0
- package/src/views/custom-components/CustomDropdown.jsx +191 -0
- package/src/views/custom-components/CustomFileUpload.jsx +387 -0
- package/src/views/custom-components/CustomFullCalendar.jsx +514 -0
- package/src/views/custom-components/CustomInfiniteScroll.jsx +126 -0
- package/src/views/custom-components/CustomRadioComponent.jsx +65 -0
- package/src/views/custom-components/CustomStatsComponent.jsx +114 -0
- package/src/views/custom-components/CustomSvgUpload.jsx +170 -0
- package/src/views/custom-components/CustomSwitch.jsx +37 -0
- package/src/views/custom-components/CustomTabPanel.jsx +19 -0
- package/src/views/custom-components/CustomTextArea.jsx +62 -0
- package/src/views/custom-components/CustomTextArea.scss +27 -0
- package/src/views/custom-components/CustomTextField.jsx +116 -0
- package/src/views/custom-components/CustomToggleSwitch.jsx +138 -0
- package/src/views/custom-components/CustomTooltip.jsx +51 -0
- package/src/views/custom-components/CustomZoomImage.jsx +134 -0
- package/src/views/custom-components/CustomizedTable/CustomizedTableV2.jsx +1407 -0
- package/src/views/custom-components/CustomizedTable/VirtualizeTableBody.jsx +295 -0
- package/src/views/custom-components/CustomizedTable/helper.jsx +159 -0
- package/src/views/custom-components/CustomizedTable.jsx +532 -0
- package/src/views/custom-components/EditInputField.jsx +174 -0
- package/src/views/custom-components/FieldDescription.jsx +22 -0
- package/src/views/custom-components/FileDisplayComponent.jsx +138 -0
- package/src/views/custom-components/FormItem.jsx +53 -0
- package/src/views/custom-components/GenericChart.jsx +80 -0
- package/src/views/custom-components/InfoBadge.jsx +60 -0
- package/src/views/custom-components/PostgresEditor.jsx +801 -0
- package/src/views/custom-components/ResizableEditAutocompleteField.jsx +249 -0
- package/src/views/custom-components/ResizableEditInputField.jsx +215 -0
- package/src/views/custom-components/ResizeableEditSelectField.jsx +197 -0
- package/src/views/custom-components/SideOverlay.jsx +113 -0
- package/src/views/custom-components/SideOverlay.scss +42 -0
- package/src/views/custom-components/calendar.scss +571 -0
- package/src/views/feature-components/.gitkeep +0 -0
- package/src/views/feature-components/Dashboard/DashboardUI.jsx +1043 -0
- package/src/views/feature-components/Dashboard/DhnddModal/AshaDataQualityVerificationModal.jsx +278 -0
- package/src/views/feature-components/Dashboard/PinFeatureModal.jsx +143 -0
- package/src/views/feature-components/Dashboard/QuickLinks.jsx +163 -0
- package/src/views/feature-components/Dashboard/Taskbar.jsx +56 -0
- package/src/views/feature-components/Dashboard/WebtasksFilterForm.jsx +109 -0
- package/src/views/feature-components/Dashboard/WidgetCard.jsx +161 -0
- package/src/views/feature-components/Dashboard/actionModal.jsx +263 -0
- package/src/views/feature-components/Dashboard/ekavachModal/HealthWorkerIncorrectDetailsModal.jsx +332 -0
- package/src/views/feature-components/Dashboard/ekavachModal/MoMaternalDeathVerifcationModal.jsx +275 -0
- package/src/views/feature-components/Dashboard/ekavachModal/MoVerficationForChildScreeningMoadal.jsx +566 -0
- package/src/views/feature-components/FeatureUsageAnalytics/FeatureUsageAnalytics.jsx +989 -0
- package/src/views/feature-components/Features/NewServerManagement.jsx +217 -0
- package/src/views/feature-components/Features/ServerManagement.scss +120 -0
- package/src/views/feature-components/ForgotPassword/ForgotPassword.jsx +226 -0
- package/src/views/feature-components/LocationDirective/LocationDirective.jsx +992 -0
- package/src/views/feature-components/LocationDirective/LocationDirectiveV2.jsx +909 -0
- package/src/views/feature-components/NotFound.jsx +66 -0
- package/src/views/feature-components/Onboarding/Onboarding.jsx +1400 -0
- package/src/views/feature-components/Skeletons.js +115 -0
- package/src/views/feature-components/Unauthorized.jsx +48 -0
- package/src/views/feature-components/VerifyRoute.jsx +88 -0
- package/src/views/feature-components/YearlyRecap/YearlyRecap.jsx +357 -0
- package/src/views/feature-components/YearlyRecap/components/RecapSlide.jsx +183 -0
- package/src/views/feature-components/YearlyRecap/languageTranslator/TranslationContext.js +5 -0
- package/src/views/feature-components/YearlyRecap/languageTranslator/TranslationProvider.jsx +26 -0
- package/src/views/feature-components/YearlyRecap/languageTranslator/i18n.js +46 -0
- package/src/views/feature-components/YearlyRecap/languageTranslator/translations.json +167 -0
- package/src/views/feature-components/YearlyRecap/slides/IntroSlide.jsx +233 -0
- package/src/views/feature-components/YearlyRecap/slides/MaternalHealthSlide.jsx +146 -0
- package/src/views/feature-components/YearlyRecap/slides/MetricSlide.jsx +227 -0
- package/src/views/feature-components/YearlyRecap/slides/OutroSlide.jsx +701 -0
- package/src/views/feature-components/YearlyRecap/slides/ReachSlide.jsx +273 -0
- package/src/views/feature-components/login/Login.jsx +840 -0
- package/src/views/feature-components/login/Login.scss +154 -0
- package/src/views/feature-components/login/LoginConfigurator.jsx +1149 -0
- package/src/views/feature-components/login/TwoFactorSetupModal.jsx +411 -0
- package/src/views/feature-components/login/simplifyMenu.js +45 -0
- package/src/views/feature-components/system-config/ManageSystemConfigs.jsx +284 -0
- package/src/views/feature-components/system-config/SystemConfig.jsx +299 -0
- package/src/views/feature-components/users/ChangePasswordModal.jsx +243 -0
- package/src/views/feature-components/users/PasswordField.jsx +56 -0
- package/dist/index.css +0 -1
- package/dist/index.js +0 -32001
- package/dist/index.js.map +0 -1
package/src/views/feature-components/Dashboard/DhnddModal/AshaDataQualityVerificationModal.jsx
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Modal,
|
|
4
|
+
Typography,
|
|
5
|
+
IconButton,
|
|
6
|
+
Button,
|
|
7
|
+
Divider,
|
|
8
|
+
Paper,
|
|
9
|
+
Table,
|
|
10
|
+
TableBody,
|
|
11
|
+
TableCell,
|
|
12
|
+
TableContainer,
|
|
13
|
+
TableHead,
|
|
14
|
+
TableRow,
|
|
15
|
+
Collapse,
|
|
16
|
+
Box,
|
|
17
|
+
CircularProgress,
|
|
18
|
+
} from '@mui/material';
|
|
19
|
+
import Grid from '@mui/material/Grid2';
|
|
20
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
21
|
+
import { faXmark, faPlus, faMinus } from '@fortawesome/free-solid-svg-icons';
|
|
22
|
+
import PropTypes from 'prop-types';
|
|
23
|
+
import { showToast } from '@/common/toaster/toaster';
|
|
24
|
+
import { execute, executeAll } from '@/common/services/GlobalApis';
|
|
25
|
+
import { getLoggedInUser } from '@/common/services/AuthenticateService'; // Adjust path based on your project
|
|
26
|
+
|
|
27
|
+
const AshaScreenedMembersModal = ({ open, onClose, task, onSave }) => {
|
|
28
|
+
const [members, setMembers] = useState([]);
|
|
29
|
+
const [expandedId, setExpandedId] = useState(null);
|
|
30
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
31
|
+
const [userId, setUserId] = useState(null);
|
|
32
|
+
|
|
33
|
+
// --- 1. INIT Logic: Fetch User and Members ---
|
|
34
|
+
const init = useCallback(async () => {
|
|
35
|
+
setIsLoading(true);
|
|
36
|
+
try {
|
|
37
|
+
// Get Logged In User
|
|
38
|
+
const userRes = await getLoggedInUser();
|
|
39
|
+
setUserId(userRes?.data?.id);
|
|
40
|
+
|
|
41
|
+
// Fetch Screened Members
|
|
42
|
+
const response = await execute({
|
|
43
|
+
code: 'retrieve_cbac_done_member_by_asha_id',
|
|
44
|
+
parameters: {
|
|
45
|
+
ashaName: task?.details?.UserName,
|
|
46
|
+
taskId: task?.taskId,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (response?.data?.result) {
|
|
51
|
+
const formattedMembers = response.data.result.map((m) => ({
|
|
52
|
+
...m,
|
|
53
|
+
pending: m.status === 'PENDING',
|
|
54
|
+
currentStatus: m.status, // Track changes locally
|
|
55
|
+
}));
|
|
56
|
+
setMembers(formattedMembers);
|
|
57
|
+
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error(error);
|
|
60
|
+
showToast({ message: 'Error loading initial data', type: 'error' });
|
|
61
|
+
} finally {
|
|
62
|
+
setIsLoading(false);
|
|
63
|
+
}
|
|
64
|
+
}, [task]);
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (open) init();
|
|
68
|
+
}, [open, init]);
|
|
69
|
+
|
|
70
|
+
// --- 2. Action Handlers (Local State Only) ---
|
|
71
|
+
const handleMemberAction = (memberId, newStatus) => {
|
|
72
|
+
setMembers((prev) => prev.map((m) => (m.member_id === memberId ? { ...m, currentStatus: newStatus } : m)));
|
|
73
|
+
setExpandedId(null); // Close details after action
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// --- 3. SAVE Logic: Batch Execute Queries ---
|
|
77
|
+
const saveChanges = async () => {
|
|
78
|
+
const nonPendingMembers = members.filter((m) => m.currentStatus !== 'PENDING');
|
|
79
|
+
|
|
80
|
+
if (nonPendingMembers.length === 0) {
|
|
81
|
+
onClose();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
setIsLoading(true);
|
|
86
|
+
try {
|
|
87
|
+
// Map member updates to query DTOs
|
|
88
|
+
const queryDtos = nonPendingMembers.map((member, index) => ({
|
|
89
|
+
code: 'update_member_status',
|
|
90
|
+
parameters: {
|
|
91
|
+
memberId: member.member_id,
|
|
92
|
+
status: member.currentStatus,
|
|
93
|
+
taskId: task.taskId,
|
|
94
|
+
userId: userId,
|
|
95
|
+
},
|
|
96
|
+
sequence: index + 1,
|
|
97
|
+
}));
|
|
98
|
+
|
|
99
|
+
// If all (or 5) are processed, mark notification complete
|
|
100
|
+
if (nonPendingMembers.length === members.length || nonPendingMembers.length === 5) {
|
|
101
|
+
queryDtos.push({
|
|
102
|
+
code: 'mark_techo_web_notification_as_complete',
|
|
103
|
+
parameters: {
|
|
104
|
+
notification_id: task.taskId,
|
|
105
|
+
action_by: userId,
|
|
106
|
+
},
|
|
107
|
+
sequence: queryDtos.length + 1,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await executeAll(queryDtos);
|
|
112
|
+
showToast({ message: 'Changes saved successfully', type: 'success' });
|
|
113
|
+
await onSave;
|
|
114
|
+
await onClose();
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error(error);
|
|
117
|
+
showToast({ message: 'Error saving changes', type: 'error' });
|
|
118
|
+
} finally {
|
|
119
|
+
setIsLoading(false);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<Modal open={open} onClose={onClose} className="flex items-center justify-center">
|
|
125
|
+
<Grid container className="bg-white shadow-2xl rounded-lg flex flex-col w-[95%] max-w-[1100px] outline-none">
|
|
126
|
+
{/* Header */}
|
|
127
|
+
<div className="flex justify-between items-center p-4 border-b">
|
|
128
|
+
<Typography variant="h6" className="font-bold text-customBlue">
|
|
129
|
+
List of members screened by asha
|
|
130
|
+
</Typography>
|
|
131
|
+
<IconButton onClick={onClose} size="small" disabled={isLoading}>
|
|
132
|
+
<FontAwesomeIcon icon={faXmark} className="text-gray-400" />
|
|
133
|
+
</IconButton>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
{/* Body */}
|
|
137
|
+
<div className="p-4 max-h-[70vh] overflow-y-auto relative">
|
|
138
|
+
{isLoading && members.length === 0 ? (
|
|
139
|
+
<Box className="flex justify-center p-10">
|
|
140
|
+
<CircularProgress />
|
|
141
|
+
</Box>
|
|
142
|
+
) : (
|
|
143
|
+
<TableContainer component={Paper} variant="outlined">
|
|
144
|
+
<Table stickyHeader size="small">
|
|
145
|
+
<TableHead>
|
|
146
|
+
<TableRow>
|
|
147
|
+
<TableCell className="bg-gray-50 font-bold">Sr. No.</TableCell>
|
|
148
|
+
<TableCell className="bg-gray-50 font-bold">Member ID</TableCell>
|
|
149
|
+
<TableCell className="bg-gray-50 font-bold">Name</TableCell>
|
|
150
|
+
<TableCell className="bg-gray-50 font-bold">Contact</TableCell>
|
|
151
|
+
<TableCell className="bg-gray-50 font-bold">Location</TableCell>
|
|
152
|
+
<TableCell className="bg-gray-50 font-bold">CBAC Date</TableCell>
|
|
153
|
+
<TableCell className="bg-gray-50 font-bold">Status</TableCell>
|
|
154
|
+
<TableCell className="bg-gray-50 font-bold" align="center">
|
|
155
|
+
Details
|
|
156
|
+
</TableCell>
|
|
157
|
+
</TableRow>
|
|
158
|
+
</TableHead>
|
|
159
|
+
<TableBody>
|
|
160
|
+
{members.map((member, index) => (
|
|
161
|
+
<React.Fragment key={member.member_id}>
|
|
162
|
+
<TableRow hover selected={expandedId === member.member_id}>
|
|
163
|
+
<TableCell>{index + 1}</TableCell>
|
|
164
|
+
<TableCell>{member?.unique_health_id || 'N/A'}</TableCell>
|
|
165
|
+
<TableCell>{member?.member_name || 'N/A'}</TableCell>
|
|
166
|
+
<TableCell>{member?.contact_number || 'N/A'}</TableCell>
|
|
167
|
+
<TableCell>{member?.location || 'N/A'}</TableCell>
|
|
168
|
+
<TableCell>{member?.done_on || 'N/A'}</TableCell>
|
|
169
|
+
<TableCell>
|
|
170
|
+
<Typography
|
|
171
|
+
variant="body2"
|
|
172
|
+
sx={{
|
|
173
|
+
color:
|
|
174
|
+
member?.currentStatus === 'Approved'
|
|
175
|
+
? 'success.main'
|
|
176
|
+
: member?.currentStatus === 'Disapproved'
|
|
177
|
+
? 'error.main'
|
|
178
|
+
: 'inherit',
|
|
179
|
+
fontWeight: member?.currentStatus !== 'PENDING' ? 600 : 400,
|
|
180
|
+
}}
|
|
181
|
+
>
|
|
182
|
+
{member?.currentStatus || 'N/A'}
|
|
183
|
+
</Typography>
|
|
184
|
+
</TableCell>
|
|
185
|
+
<TableCell align="center">
|
|
186
|
+
<IconButton
|
|
187
|
+
size="small"
|
|
188
|
+
onClick={() => setExpandedId(expandedId === member?.member_id ? null : member?.member_id)}
|
|
189
|
+
>
|
|
190
|
+
<FontAwesomeIcon icon={expandedId === member?.member_id ? faMinus : faPlus} />
|
|
191
|
+
</IconButton>
|
|
192
|
+
</TableCell>
|
|
193
|
+
</TableRow>
|
|
194
|
+
|
|
195
|
+
<TableRow>
|
|
196
|
+
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={8}>
|
|
197
|
+
<Collapse in={expandedId === member.member_id} timeout="auto" unmountOnExit>
|
|
198
|
+
<Box className="m-4 p-4 bg-gray-50 border border-gray-200 rounded-md">
|
|
199
|
+
<Grid container spacing={2}>
|
|
200
|
+
<Grid size={{ xs: 12, md: 6 }}>
|
|
201
|
+
<Typography variant="body2">
|
|
202
|
+
<strong>Suspected for:</strong> {member?.suspected || 'N.A.'}
|
|
203
|
+
</Typography>
|
|
204
|
+
<Typography variant="body2">
|
|
205
|
+
<strong>Smoke:</strong> {member?.smoke || 'N.A.'}
|
|
206
|
+
</Typography>
|
|
207
|
+
<Typography variant="body2">
|
|
208
|
+
<strong>Alcohol:</strong> {member?.alchohol || 'N.A.'}
|
|
209
|
+
</Typography>
|
|
210
|
+
</Grid>
|
|
211
|
+
<Grid size={{ xs: 12, md: 6 }}>
|
|
212
|
+
<Typography variant="body2">
|
|
213
|
+
<strong>Waist:</strong> {member?.waist || 'N.A.'}
|
|
214
|
+
</Typography>
|
|
215
|
+
<Typography variant="body2">
|
|
216
|
+
<strong>Score:</strong> {member?.score || 'N.A.'}
|
|
217
|
+
</Typography>
|
|
218
|
+
</Grid>
|
|
219
|
+
</Grid>
|
|
220
|
+
<Divider className="my-3" />
|
|
221
|
+
<div className="flex justify-center gap-2">
|
|
222
|
+
<Button
|
|
223
|
+
variant="contained"
|
|
224
|
+
size="small"
|
|
225
|
+
onClick={() => handleMemberAction(member?.member_id, 'Approved')}
|
|
226
|
+
disabled={!member?.pending}
|
|
227
|
+
>
|
|
228
|
+
Approve
|
|
229
|
+
</Button>
|
|
230
|
+
<Button
|
|
231
|
+
variant="contained"
|
|
232
|
+
size="small"
|
|
233
|
+
color="error"
|
|
234
|
+
onClick={() => handleMemberAction(member?.member_id, 'Disapproved')}
|
|
235
|
+
disabled={!member?.pending}
|
|
236
|
+
>
|
|
237
|
+
Disapprove
|
|
238
|
+
</Button>
|
|
239
|
+
</div>
|
|
240
|
+
</Box>
|
|
241
|
+
</Collapse>
|
|
242
|
+
</TableCell>
|
|
243
|
+
</TableRow>
|
|
244
|
+
</React.Fragment>
|
|
245
|
+
))}
|
|
246
|
+
</TableBody>
|
|
247
|
+
</Table>
|
|
248
|
+
</TableContainer>
|
|
249
|
+
)}
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
{/* Footer */}
|
|
253
|
+
<div className="p-4 px-6 bg-gray-50 border-t flex justify-end gap-3 rounded-b-lg">
|
|
254
|
+
<Button variant="contained" color="secondary" onClick={onClose} disabled={isLoading}>
|
|
255
|
+
Close
|
|
256
|
+
</Button>
|
|
257
|
+
<Button
|
|
258
|
+
variant="contained"
|
|
259
|
+
color="primary"
|
|
260
|
+
onClick={saveChanges}
|
|
261
|
+
disabled={isLoading || members.length === 0}
|
|
262
|
+
>
|
|
263
|
+
{isLoading ? <CircularProgress size={24} color="inherit" /> : 'Save Changes'}
|
|
264
|
+
</Button>
|
|
265
|
+
</div>
|
|
266
|
+
</Grid>
|
|
267
|
+
</Modal>
|
|
268
|
+
);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
AshaScreenedMembersModal.propTypes = {
|
|
272
|
+
open: PropTypes.bool,
|
|
273
|
+
onClose: PropTypes.func,
|
|
274
|
+
task: PropTypes.object,
|
|
275
|
+
onSave: PropTypes.any,
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
export default AshaScreenedMembersModal;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Dialog,
|
|
4
|
+
DialogTitle,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogActions,
|
|
7
|
+
Button,
|
|
8
|
+
List,
|
|
9
|
+
ListItem,
|
|
10
|
+
ListItemText,
|
|
11
|
+
ListItemIcon,
|
|
12
|
+
Checkbox,
|
|
13
|
+
TextField,
|
|
14
|
+
InputAdornment,
|
|
15
|
+
} from '@mui/material';
|
|
16
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
17
|
+
import { faSearch } from '@fortawesome/free-solid-svg-icons';
|
|
18
|
+
import { showToast } from '@/common/toaster/toaster';
|
|
19
|
+
|
|
20
|
+
const PinFeatureModal = ({ open, onClose, linearMenuItems, pinnedFeatures, onSave }) => {
|
|
21
|
+
const [selected, setSelected] = useState([]);
|
|
22
|
+
const [search, setSearch] = useState('');
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (open) {
|
|
26
|
+
setSelected(pinnedFeatures || []);
|
|
27
|
+
setSearch('');
|
|
28
|
+
}
|
|
29
|
+
}, [open, pinnedFeatures]);
|
|
30
|
+
|
|
31
|
+
const handleToggle = (navState) => {
|
|
32
|
+
const currentIndex = selected.indexOf(navState);
|
|
33
|
+
const newSelected = [...selected];
|
|
34
|
+
|
|
35
|
+
if (currentIndex === -1) {
|
|
36
|
+
if (selected.length >= 5) {
|
|
37
|
+
// Enforce maximum 5 pins
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
newSelected.push(navState);
|
|
41
|
+
} else {
|
|
42
|
+
newSelected.splice(currentIndex, 1);
|
|
43
|
+
}
|
|
44
|
+
setSelected(newSelected);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const handleSave = () => {
|
|
48
|
+
onSave(selected);
|
|
49
|
+
onClose();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Convert dictionary back to array and filter out nulls or parents without actual routing
|
|
53
|
+
const availableItems = Object.values(linearMenuItems || {})
|
|
54
|
+
.filter((item) => item?.displayName || item?.name)
|
|
55
|
+
.sort((a, b) => (a.displayName || a.name || '').localeCompare(b.displayName || b.name || ''));
|
|
56
|
+
|
|
57
|
+
const filteredItems = availableItems.filter((item) => {
|
|
58
|
+
const name = (item.displayName || item.name || '').toLowerCase();
|
|
59
|
+
return name.includes(search.toLowerCase());
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Dialog open={open} onClose={onClose} fullWidth maxWidth="sm">
|
|
64
|
+
<DialogTitle>
|
|
65
|
+
Pin Menu Shortcuts
|
|
66
|
+
<div className="text-sm font-normal text-slate-500 mt-1">
|
|
67
|
+
Select up to 5 quick access features for your Dashboard. ({selected.length}/5)
|
|
68
|
+
</div>
|
|
69
|
+
</DialogTitle>
|
|
70
|
+
|
|
71
|
+
<div className="px-6 pb-2">
|
|
72
|
+
<TextField
|
|
73
|
+
fullWidth
|
|
74
|
+
size="small"
|
|
75
|
+
placeholder="Search features..."
|
|
76
|
+
value={search}
|
|
77
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
78
|
+
InputProps={{
|
|
79
|
+
startAdornment: (
|
|
80
|
+
<InputAdornment position="start">
|
|
81
|
+
<FontAwesomeIcon icon={faSearch} className="text-slate-400" />
|
|
82
|
+
</InputAdornment>
|
|
83
|
+
),
|
|
84
|
+
}}
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<DialogContent dividers sx={{ p: 0, minHeight: 300 }}>
|
|
89
|
+
<List sx={{ pt: 0 }}>
|
|
90
|
+
{filteredItems.map((item) => {
|
|
91
|
+
const isChecked = selected.includes(item.navigationState);
|
|
92
|
+
const isDisabled = !isChecked && selected.length >= 5;
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<ListItem
|
|
96
|
+
className='cursor-pointer'
|
|
97
|
+
key={item.navigationState}
|
|
98
|
+
button
|
|
99
|
+
onClick={() => {
|
|
100
|
+
if (!isDisabled) {
|
|
101
|
+
handleToggle(item.navigationState);
|
|
102
|
+
} else {
|
|
103
|
+
showToast({
|
|
104
|
+
message: 'You can only pin up to 5 features.',
|
|
105
|
+
type: 'info'
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}}
|
|
109
|
+
disabled={isDisabled}
|
|
110
|
+
>
|
|
111
|
+
<ListItemIcon>
|
|
112
|
+
<Checkbox
|
|
113
|
+
edge="start"
|
|
114
|
+
checked={isChecked}
|
|
115
|
+
tabIndex={-1}
|
|
116
|
+
disableRipple
|
|
117
|
+
disabled={isDisabled}
|
|
118
|
+
/>
|
|
119
|
+
</ListItemIcon>
|
|
120
|
+
<ListItemText primary={item.displayName || item.name} secondary={item.navigationState} />
|
|
121
|
+
</ListItem>
|
|
122
|
+
);
|
|
123
|
+
})}
|
|
124
|
+
{filteredItems.length === 0 && (
|
|
125
|
+
<div className="text-center text-slate-500 py-8">
|
|
126
|
+
No matching features found.
|
|
127
|
+
</div>
|
|
128
|
+
)}
|
|
129
|
+
</List>
|
|
130
|
+
</DialogContent>
|
|
131
|
+
<DialogActions sx={{ p: '1rem 1.5rem' }}>
|
|
132
|
+
<Button onClick={onClose} color="inherit">
|
|
133
|
+
Cancel
|
|
134
|
+
</Button>
|
|
135
|
+
<Button onClick={handleSave} variant="contained" color="primary">
|
|
136
|
+
Save Pins
|
|
137
|
+
</Button>
|
|
138
|
+
</DialogActions>
|
|
139
|
+
</Dialog>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export default PinFeatureModal;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useSelector, useDispatch } from 'react-redux';
|
|
3
|
+
import { useNavigate } from 'react-router-dom';
|
|
4
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
5
|
+
import {
|
|
6
|
+
faPlus,
|
|
7
|
+
faUsers,
|
|
8
|
+
faUserTie,
|
|
9
|
+
faChartBar,
|
|
10
|
+
faHeartbeat,
|
|
11
|
+
faHome,
|
|
12
|
+
faCog,
|
|
13
|
+
faFileAlt,
|
|
14
|
+
faStar,
|
|
15
|
+
faCubes,
|
|
16
|
+
faLayerGroup,
|
|
17
|
+
faTimes,
|
|
18
|
+
} from '@fortawesome/free-solid-svg-icons';
|
|
19
|
+
import { getPinnedFeatures, setPinnedFeatures } from '@/store/reducers/AuthenticationReducer';
|
|
20
|
+
import PinFeatureModal from './PinFeatureModal';
|
|
21
|
+
import GeneralUtil from '@/common/services/util/GeneralUtil';
|
|
22
|
+
import { Tooltip, useTheme, alpha } from '@mui/material';
|
|
23
|
+
|
|
24
|
+
const QuickLinks = () => {
|
|
25
|
+
const dispatch = useDispatch();
|
|
26
|
+
const navigate = useNavigate();
|
|
27
|
+
const theme = useTheme();
|
|
28
|
+
const isDark = theme.palette.mode === 'dark';
|
|
29
|
+
const pinnedStates = useSelector(getPinnedFeatures) || [];
|
|
30
|
+
const { linearMenuItems } = useSelector((state) => state.Authenticate);
|
|
31
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
32
|
+
|
|
33
|
+
// Handler to remove a shortcut
|
|
34
|
+
const handleRemove = (navState) => {
|
|
35
|
+
const updated = pinnedStates.filter((ns) => ns !== navState);
|
|
36
|
+
dispatch(setPinnedFeatures(updated));
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Derive full objects based on navigationState matches
|
|
40
|
+
const pinnedItems = pinnedStates.map((navState) => linearMenuItems?.[navState]).filter(Boolean);
|
|
41
|
+
|
|
42
|
+
const getFeatureIcon = (name) => {
|
|
43
|
+
const n = (name || '').toLowerCase();
|
|
44
|
+
if (n.includes('user')) return faUsers;
|
|
45
|
+
if (n.includes('role')) return faUserTie;
|
|
46
|
+
if (n.includes('report')) return faChartBar;
|
|
47
|
+
if (n.includes('patient') || n.includes('health') || n.includes('disease')) return faHeartbeat;
|
|
48
|
+
if (n.includes('dashboard') || n.includes('home')) return faHome;
|
|
49
|
+
if (n.includes('setting') || n.includes('config')) return faCog;
|
|
50
|
+
if (n.includes('form') || n.includes('data')) return faFileAlt;
|
|
51
|
+
if (n.includes('location')) return faLayerGroup;
|
|
52
|
+
if (n.includes('feature') || n.includes('app')) return faCubes;
|
|
53
|
+
return faStar; // Default placeholder
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleShortcutClick = (item) => {
|
|
57
|
+
let path = GeneralUtil.naviagationFunc(item);
|
|
58
|
+
if (path) {
|
|
59
|
+
if (!path.startsWith('/ui/')) {
|
|
60
|
+
path = `/ui/${path}`;
|
|
61
|
+
}
|
|
62
|
+
// is ekavach then only open in new tab
|
|
63
|
+
if (path.includes('report/view/')) {
|
|
64
|
+
if (GeneralUtil.isEkavach) {
|
|
65
|
+
window.open(`/ui/${path}`, '_blank');
|
|
66
|
+
} else {
|
|
67
|
+
navigate(path);
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
navigate(path);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handleSavePins = (selectedNavStates) => {
|
|
76
|
+
dispatch(setPinnedFeatures(selectedNavStates));
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Skip showing anything if the component renders before menu items load
|
|
80
|
+
if (!linearMenuItems || Object.keys(linearMenuItems).length === 0) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div className="w-full mt-4 mb-2 flex justify-center">
|
|
86
|
+
<div className="flex flex-wrap items-center justify-center gap-6 max-w-4xl px-4 py-4">
|
|
87
|
+
{pinnedItems.map((item, idx) => {
|
|
88
|
+
const name = item.displayName || item.name;
|
|
89
|
+
const icon = getFeatureIcon(name);
|
|
90
|
+
return (
|
|
91
|
+
<div className="relative" key={item.navigationState || idx}>
|
|
92
|
+
<Tooltip title={name} arrow placement="bottom">
|
|
93
|
+
<button
|
|
94
|
+
onClick={() => handleShortcutClick(item)}
|
|
95
|
+
className="flex flex-col items-center group w-[100px] hover:-translate-y-1 transition-transform duration-200 focus:outline-none cursor-pointer"
|
|
96
|
+
>
|
|
97
|
+
<div
|
|
98
|
+
className={`w-[56px] h-[56px] rounded-full shadow-sm flex items-center justify-center border transition-colors mb-2 ${
|
|
99
|
+
isDark
|
|
100
|
+
? 'bg-slate-800 border-slate-700 group-hover:bg-slate-700 group-hover:border-blue-500/50'
|
|
101
|
+
: 'bg-slate-100 border-slate-200 group-hover:bg-blue-50 group-hover:border-blue-200'
|
|
102
|
+
}`}
|
|
103
|
+
>
|
|
104
|
+
<FontAwesomeIcon
|
|
105
|
+
icon={icon}
|
|
106
|
+
className={`text-xl transition-colors ${
|
|
107
|
+
isDark ? 'text-slate-300 group-hover:text-blue-400' : 'text-slate-600 group-hover:text-blue-600'
|
|
108
|
+
}`}
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
<span
|
|
112
|
+
className={`text-[13px] font-medium text-center line-clamp-1 leading-tight transition-colors ${
|
|
113
|
+
isDark ? 'text-slate-200 group-hover:text-blue-400' : 'text-slate-700 group-hover:text-blue-700'
|
|
114
|
+
}`}
|
|
115
|
+
>
|
|
116
|
+
{name}
|
|
117
|
+
</span>
|
|
118
|
+
</button>
|
|
119
|
+
</Tooltip>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
})}
|
|
123
|
+
|
|
124
|
+
<button
|
|
125
|
+
onClick={() => setModalOpen(true)}
|
|
126
|
+
className="flex flex-col items-center group w-[100px] hover:-translate-y-1 transition-transform duration-200 focus:outline-none cursor-pointer"
|
|
127
|
+
>
|
|
128
|
+
<div
|
|
129
|
+
className={`w-[56px] h-[56px] rounded-full flex items-center justify-center border border-dashed transition-colors ${
|
|
130
|
+
isDark
|
|
131
|
+
? 'bg-slate-800/40 border-slate-700 group-hover:bg-slate-800/60 group-hover:border-slate-500'
|
|
132
|
+
: 'bg-slate-50 border-slate-300 group-hover:bg-slate-100 group-hover:border-slate-400'
|
|
133
|
+
}`}
|
|
134
|
+
>
|
|
135
|
+
<FontAwesomeIcon
|
|
136
|
+
icon={faPlus}
|
|
137
|
+
className={`transition-colors ${
|
|
138
|
+
isDark ? 'text-slate-500 group-hover:text-slate-300' : 'text-slate-400 group-hover:text-slate-600'
|
|
139
|
+
}`}
|
|
140
|
+
/>
|
|
141
|
+
</div>
|
|
142
|
+
<span
|
|
143
|
+
className={`text-[13px] font-medium text-center transition-colors ${
|
|
144
|
+
isDark ? 'text-slate-400 group-hover:text-slate-200' : 'text-slate-500 group-hover:text-slate-700'
|
|
145
|
+
}`}
|
|
146
|
+
>
|
|
147
|
+
Add Shortcut
|
|
148
|
+
</span>
|
|
149
|
+
</button>
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
<PinFeatureModal
|
|
153
|
+
open={modalOpen}
|
|
154
|
+
onClose={() => setModalOpen(false)}
|
|
155
|
+
linearMenuItems={linearMenuItems}
|
|
156
|
+
pinnedFeatures={pinnedStates}
|
|
157
|
+
onSave={handleSavePins}
|
|
158
|
+
/>
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export default QuickLinks;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { lazy, Suspense } from 'react';
|
|
2
|
+
const WidgetCard = lazy(() => import('@/views/feature-components/Dashboard/WidgetCard'));
|
|
3
|
+
import { Button } from '@mui/material';
|
|
4
|
+
import Grid from '@mui/material/Grid2';
|
|
5
|
+
import { Box } from '@mui/system';
|
|
6
|
+
import PropTypes from 'prop-types';
|
|
7
|
+
|
|
8
|
+
import { useTranslateProvider } from '@/common/languageTranslator/TranslationContext';
|
|
9
|
+
const Taskbar = ({
|
|
10
|
+
hiddenWidgets,
|
|
11
|
+
handleHideTaskbar,
|
|
12
|
+
handleUnhideWidget,
|
|
13
|
+
onWidgetClick,
|
|
14
|
+
dataTestId = 'Dashboard-Taskbar',
|
|
15
|
+
}) => {
|
|
16
|
+
const { translate } = useTranslateProvider();
|
|
17
|
+
return (
|
|
18
|
+
<Box className="border border-gray-300 p-4 mt-4" data-testid={dataTestId}>
|
|
19
|
+
<Grid container spacing={2}>
|
|
20
|
+
{hiddenWidgets
|
|
21
|
+
.sort((a, b) => {
|
|
22
|
+
if (a.orderNo === null) return 1;
|
|
23
|
+
if (b.orderNo === null) return -1;
|
|
24
|
+
return a.orderNo - b.orderNo;
|
|
25
|
+
})
|
|
26
|
+
.map((widget) => {
|
|
27
|
+
return (
|
|
28
|
+
<Grid item key={widget.id} size={{ xs: 12, sm: 6 }}>
|
|
29
|
+
<Suspense>
|
|
30
|
+
<WidgetCard
|
|
31
|
+
onClick={() => onWidgetClick(widget)}
|
|
32
|
+
widgetData={widget}
|
|
33
|
+
hidden={true}
|
|
34
|
+
onArrowClick={() => handleUnhideWidget(widget)}
|
|
35
|
+
dataTestId={`${dataTestId}-Widget-Card`}
|
|
36
|
+
/>
|
|
37
|
+
</Suspense>
|
|
38
|
+
</Grid>
|
|
39
|
+
);
|
|
40
|
+
})}
|
|
41
|
+
</Grid>
|
|
42
|
+
<Button data-testid={`taskbar-hide-button`} variant="contained" className=" mt-4" onClick={handleHideTaskbar}>
|
|
43
|
+
{translate('Hide Taskbar')}
|
|
44
|
+
</Button>
|
|
45
|
+
</Box>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default Taskbar;
|
|
50
|
+
Taskbar.propTypes = {
|
|
51
|
+
hiddenWidgets: PropTypes.any,
|
|
52
|
+
handleHideTaskbar: PropTypes.any,
|
|
53
|
+
handleUnhideWidget: PropTypes.any,
|
|
54
|
+
onWidgetClick: PropTypes.any,
|
|
55
|
+
dataTestId: PropTypes.any,
|
|
56
|
+
};
|