From ac0edefce516996aabf7f9e0c4f8cec52b1fd211 Mon Sep 17 00:00:00 2001 From: Piyush Raj Date: Tue, 4 Feb 2025 12:35:04 +0530 Subject: [PATCH 1/2] Add react-components and svg-components in webpack for publish --- .github/workflows/publishComponents.yml | 38 + webpack/libraries/package.json | 8 +- webpack/react-components/.babelrc | 5 + webpack/react-components/.storybook/main.js | 4 + .../react-components/.storybook/preview.js | 9 + webpack/react-components/CHANGELOG.md | 171 ++ webpack/react-components/README.md | 161 ++ webpack/react-components/docker/Dockerfile | 21 + webpack/react-components/docker/nginx.conf | 12 + webpack/react-components/envs.js | 0 webpack/react-components/package.json | 96 + webpack/react-components/public/index.html | 28 + .../react-components/src/atoms/ActionBar.js | 11 + .../react-components/src/atoms/ActionLinks.js | 5 + webpack/react-components/src/atoms/Amount.js | 12 + .../src/atoms/AppContainer.js | 13 + .../src/atoms/ApplyFilterBar.js | 16 + .../react-components/src/atoms/BackButton.js | 16 + webpack/react-components/src/atoms/Banner.js | 82 + .../src/atoms/Banner.stories.js | 23 + webpack/react-components/src/atoms/Body.js | 7 + .../react-components/src/atoms/BreadCrumb.js | 53 + .../react-components/src/atoms/BreakLine.js | 7 + webpack/react-components/src/atoms/Button.js | 76 + .../src/atoms/ButtonSelector.js | 55 + .../src/atoms/ButtonSelector.stories.js | 24 + webpack/react-components/src/atoms/Card.js | 24 + .../src/atoms/CardBasedOptions.js | 28 + .../react-components/src/atoms/CardCaption.js | 11 + .../react-components/src/atoms/CardHeader.js | 7 + .../react-components/src/atoms/CardLabel.js | 11 + .../src/atoms/CardLabelDesc.js | 11 + .../src/atoms/CardLabelError.js | 11 + .../src/atoms/CardSectionHeader.js | 11 + .../src/atoms/CardSectionSubText.js | 11 + .../src/atoms/CardSubHeader.js | 16 + .../react-components/src/atoms/CardText.js | 11 + .../src/atoms/CardTextButton.js | 7 + .../react-components/src/atoms/CheckBox.js | 89 + .../src/atoms/CheckBox.stories.js | 16 + .../src/atoms/CitizenConsentForm.js | 71 + .../src/atoms/CitizenHomeCard.js | 26 + .../src/atoms/CitizenInfoLabel.js | 22 + .../react-components/src/atoms/CloseButton.js | 12 + .../src/atoms/CollapseAndExpandGroups.js | 46 + .../src/atoms/ConnectingCheckPoints.js | 59 + .../atoms/ConnectingCheckPoints.stories.js | 19 + .../src/atoms/CustomButton.js | 13 + .../react-components/src/atoms/DatePicker.js | 72 + .../react-components/src/atoms/DateWrap.js | 25 + .../src/atoms/DateWrap.stories.js | 19 + .../src/atoms/DescriptionText.js | 23 + .../src/atoms/DescriptionText.stories.js | 16 + .../src/atoms/DisplayPhotos.js | 43 + .../src/atoms/DisplayPhotos.stories.js | 20 + .../react-components/src/atoms/Dropdown.js | 293 +++ .../src/atoms/Dropdown.stories.js | 18 + .../src/atoms/EllipsisMenu.js | 33 + .../src/atoms/EmployeeAppContainer.js | 7 + .../src/atoms/EmployeeModuleCard.js | 124 + .../src/atoms/ErrorMessage.js | 25 + .../src/atoms/EventCalendarView.js | 14 + .../react-components/src/atoms/GreyOutText.js | 5 + .../react-components/src/atoms/Hamburger.js | 10 + webpack/react-components/src/atoms/Header.js | 11 + .../react-components/src/atoms/HeaderBar.js | 26 + .../src/atoms/HeaderBar.stories.js | 18 + .../react-components/src/atoms/HomeLink.js | 21 + .../src/atoms/HomeLink.stories.js | 22 + .../src/atoms/HorizontalNav.js | 42 + .../src/atoms/HorizontalNavV2.js | 56 + .../src/atoms/ImageUploadHandler.js | 113 + .../react-components/src/atoms/ImageViewer.js | 24 + .../src/atoms/ImageViewer.stories.js | 21 + .../react-components/src/atoms/InboxLinks.js | 33 + .../src/atoms/InboxSearchLinks.js | 69 + .../react-components/src/atoms/InfoBanner.js | 16 + .../src/atoms/InputTextAmount.js | 408 ++++ webpack/react-components/src/atoms/KeyNote.js | 38 + .../src/atoms/KeyNote.stories.js | 17 + webpack/react-components/src/atoms/Label.js | 7 + .../src/atoms/LabelFieldPair.js | 11 + .../react-components/src/atoms/LinkButton.js | 25 + .../src/atoms/LinkButton.stories.js | 16 + .../react-components/src/atoms/LinkLabel.js | 11 + webpack/react-components/src/atoms/Loader.js | 23 + .../src/atoms/Loader.stories.js | 20 + .../src/atoms/LoaderWithGap.js | 28 + .../src/atoms/LocationSearch.js | 394 ++++ webpack/react-components/src/atoms/Menu.js | 30 + .../src/atoms/Menu.stories.js | 15 + .../src/atoms/MobileNumber.js | 67 + .../src/atoms/Modals/WorkflowPopup.js | 112 + .../Modals/config/configEstimateModal.js | 400 ++++ .../src/atoms/Modals/index.js | 13 + .../react-components/src/atoms/MultiLink.js | 45 + .../src/atoms/MultiSelectDropdown.js | 142 ++ webpack/react-components/src/atoms/NavBar.js | 194 ++ .../src/atoms/NoResultsFound.js | 15 + .../react-components/src/atoms/OTPInput.js | 101 + .../src/atoms/OTPInput.stories.js | 16 + .../src/atoms/OpenLinkContainer.js | 29 + .../react-components/src/atoms/Paragraph.js | 11 + webpack/react-components/src/atoms/PopUp.js | 7 + .../src/atoms/PopupHeadingLabel.js | 20 + .../src/atoms/PrivateRoute.js | 29 + .../src/atoms/RadioButtons.js | 91 + .../src/atoms/RadioButtons.stories.js | 19 + webpack/react-components/src/atoms/Rating.js | 45 + .../src/atoms/Rating.stories.js | 18 + webpack/react-components/src/atoms/Reason.js | 29 + .../src/atoms/RemovableTagNew.js | 14 + .../src/atoms/RemoveableTag.js | 13 + .../src/atoms/RoundedLabel.js | 5 + webpack/react-components/src/atoms/SVG.js | 1581 +++++++++++++ .../src/atoms/SearchComponent.js | 266 +++ .../src/atoms/SearchableDropdown.js | 312 +++ .../src/atoms/SectionalDropdown.js | 90 + .../src/atoms/StandaloneSearchBar.js | 10 + .../react-components/src/atoms/StatusTable.js | 108 + webpack/react-components/src/atoms/SubMenu.js | 105 + .../react-components/src/atoms/SubmitBar.js | 46 + .../src/atoms/SubmitBar.stories.js | 28 + .../react-components/src/atoms/TLCaption.js | 40 + webpack/react-components/src/atoms/Table.js | 281 +++ .../react-components/src/atoms/TelePhone.js | 27 + .../src/atoms/TelePhone.stories.js | 16 + .../react-components/src/atoms/TextArea.js | 45 + .../src/atoms/TextArea.stories.js | 18 + .../react-components/src/atoms/TextInput.js | 152 ++ .../src/atoms/TextInput.stories.js | 19 + webpack/react-components/src/atoms/Toast.js | 64 + .../src/atoms/Toast.stories.js | 16 + .../src/atoms/ToggleSwitch.js | 37 + webpack/react-components/src/atoms/TopBar.js | 72 + .../src/atoms/TopBar.stories.js | 16 + .../react-components/src/atoms/ULBHomeCard.js | 38 + .../src/atoms/UnMaskComponent.js | 52 + .../react-components/src/atoms/UploadFile.js | 258 +++ .../src/atoms/UploadImages.js | 50 + .../src/atoms/UploadImages.stories.js | 21 + .../src/atoms/ViewDetailsCard.js | 31 + .../react-components/src/atoms/ViewImages.js | 53 + .../react-components/src/atoms/WeekPicker.js | 12 + .../src/atoms/WhatsNewCard.js | 20 + .../src/atoms/WorkflowActions.js | 212 ++ .../src/atoms/WorkflowTimeline.js | 133 ++ .../react-components/src/atoms/XlsPreview.js | 106 + .../src/atoms/amtUtils/index.js | 414 ++++ .../react-components/src/atoms/contants.js | 1 + .../react-components/src/atoms/svgindex.js | 1993 +++++++++++++++++ webpack/react-components/src/context/index.js | 1 + .../src/hoc/FileUploadModal.js | 78 + .../react-components/src/hoc/FormComposer.js | 646 ++++++ .../src/hoc/FormComposerV2.js | 894 ++++++++ .../InboxComposer/MobileComponentDirectory.js | 59 + .../src/hoc/InboxComposer/index.js | 298 +++ .../src/hoc/InboxSearchComposer.js | 335 +++ .../src/hoc/InboxSearchComposerContext.js | 4 + .../src/hoc/InboxSearchComposerReducer.js | 103 + .../src/hoc/InboxSearchComposerV2.js | 389 ++++ .../hoc/MobileView/MobileSearchComponent.js | 236 ++ .../src/hoc/MobileView/MobileSearchResults.js | 193 ++ .../hoc/MobileView/MobileSearchResultsv1.js | 106 + webpack/react-components/src/hoc/Modal.js | 63 + .../react-components/src/hoc/RemovableTags.js | 186 ++ .../src/hoc/ResponseComposer.js | 61 + .../react-components/src/hoc/ResultsTable.js | 267 +++ .../src/hoc/SubformComposer.js | 38 + .../react-components/src/hoc/Tutorial/Help.js | 16 + .../src/hoc/Tutorial/Readme.md | 49 + .../src/hoc/Tutorial/TourProvider.js | 22 + .../src/hoc/Tutorial/Tutorial.js | 62 + .../src/hoc/UploadFileComposer.js | 154 ++ .../src/hoc/ViewComposer/Readme.md | 126 ++ .../src/hoc/ViewComposer/index.js | 219 ++ .../src/hoc/ViewComposer/renderUtils.js | 155 ++ webpack/react-components/src/hoc/formUtils.js | 26 + webpack/react-components/src/index.js | 601 +++++ .../src/molecules/ApiCheckboxes.js | 46 + .../src/molecules/ApiDropdown.js | 76 + .../src/molecules/CityMohalla.js | 76 + .../src/molecules/CityMohalla.stories.js | 26 + .../src/molecules/CustomDropdown.js | 182 ++ .../src/molecules/DashboardBox.js | 69 + .../src/molecules/DateRange.js | 171 ++ .../src/molecules/DateRangeNew.js | 172 ++ .../src/molecules/DetailsCard.js | 143 ++ .../src/molecules/DetailsCard.stories.js | 16 + .../src/molecules/FilterAction.js | 13 + .../src/molecules/FilterForm.js | 74 + .../src/molecules/FormStep.js | 110 + .../src/molecules/FormStep.stories.js | 18 + .../src/molecules/InputCard.js | 60 + .../src/molecules/InputCard.stories.js | 22 + .../src/molecules/Localities.js | 29 + .../src/molecules/LocationDropdownWrapper.js | 97 + .../src/molecules/LocationSearchCard.js | 107 + .../molecules/LocationSearchCard.stories.js | 20 + .../src/molecules/MultiUploadWrapper.js | 144 ++ .../src/molecules/OnGroundEventCard.js | 28 + .../src/molecules/PageBasedInput.js | 19 + .../src/molecules/PitDimension.js | 52 + .../src/molecules/RadioOrSelect.js | 55 + .../src/molecules/RatingCard.js | 108 + .../src/molecules/RatingCard.stories.js | 37 + .../src/molecules/RenderFormFields.js | 389 ++++ .../src/molecules/SearchAction.js | 11 + .../src/molecules/SearchForm.js | 44 + .../src/molecules/SearchOnRadioButtons.js | 36 + .../src/molecules/SortAction.js | 12 + .../src/molecules/TextInputCard.js | 58 + .../src/molecules/TextInputCard.stories.js | 23 + .../src/molecules/TypeSelectCard.js | 50 + .../src/molecules/TypeSelectCard.stories.js | 22 + .../src/molecules/UploadPitPhoto.js | 146 ++ .../src/molecules/WorkflowModal.js | 52 + .../src/molecules/WorkflowStatusFilter.js | 57 + .../react-components/src/stories/Button.js | 50 + .../src/stories/Button.stories.js | 36 + .../react-components/src/stories/Header.js | 43 + .../src/stories/Header.stories.js | 18 + .../src/stories/Introduction.stories.mdx | 207 ++ webpack/react-components/src/stories/Page.js | 64 + .../src/stories/Page.stories.js | 21 + .../src/stories/assets/code-brackets.svg | 1 + .../src/stories/assets/colors.svg | 1 + .../src/stories/assets/comments.svg | 1 + .../src/stories/assets/direction.svg | 1 + .../src/stories/assets/flow.svg | 1 + .../src/stories/assets/plugin.svg | 1 + .../src/stories/assets/repo.svg | 1 + .../src/stories/assets/stackalt.svg | 1 + .../react-components/src/stories/button.css | 30 + .../react-components/src/stories/header.css | 26 + webpack/react-components/src/stories/page.css | 69 + webpack/react-components/webpack.config.js | 48 + webpack/svg-components/package.json | 14 +- webpack/ui-components/package.json | 4 +- 239 files changed, 20807 insertions(+), 13 deletions(-) create mode 100644 webpack/react-components/.babelrc create mode 100644 webpack/react-components/.storybook/main.js create mode 100644 webpack/react-components/.storybook/preview.js create mode 100644 webpack/react-components/CHANGELOG.md create mode 100644 webpack/react-components/README.md create mode 100644 webpack/react-components/docker/Dockerfile create mode 100644 webpack/react-components/docker/nginx.conf create mode 100644 webpack/react-components/envs.js create mode 100644 webpack/react-components/package.json create mode 100644 webpack/react-components/public/index.html create mode 100644 webpack/react-components/src/atoms/ActionBar.js create mode 100644 webpack/react-components/src/atoms/ActionLinks.js create mode 100644 webpack/react-components/src/atoms/Amount.js create mode 100644 webpack/react-components/src/atoms/AppContainer.js create mode 100644 webpack/react-components/src/atoms/ApplyFilterBar.js create mode 100644 webpack/react-components/src/atoms/BackButton.js create mode 100644 webpack/react-components/src/atoms/Banner.js create mode 100644 webpack/react-components/src/atoms/Banner.stories.js create mode 100644 webpack/react-components/src/atoms/Body.js create mode 100644 webpack/react-components/src/atoms/BreadCrumb.js create mode 100644 webpack/react-components/src/atoms/BreakLine.js create mode 100644 webpack/react-components/src/atoms/Button.js create mode 100644 webpack/react-components/src/atoms/ButtonSelector.js create mode 100644 webpack/react-components/src/atoms/ButtonSelector.stories.js create mode 100644 webpack/react-components/src/atoms/Card.js create mode 100644 webpack/react-components/src/atoms/CardBasedOptions.js create mode 100644 webpack/react-components/src/atoms/CardCaption.js create mode 100644 webpack/react-components/src/atoms/CardHeader.js create mode 100644 webpack/react-components/src/atoms/CardLabel.js create mode 100644 webpack/react-components/src/atoms/CardLabelDesc.js create mode 100644 webpack/react-components/src/atoms/CardLabelError.js create mode 100644 webpack/react-components/src/atoms/CardSectionHeader.js create mode 100644 webpack/react-components/src/atoms/CardSectionSubText.js create mode 100644 webpack/react-components/src/atoms/CardSubHeader.js create mode 100644 webpack/react-components/src/atoms/CardText.js create mode 100644 webpack/react-components/src/atoms/CardTextButton.js create mode 100644 webpack/react-components/src/atoms/CheckBox.js create mode 100644 webpack/react-components/src/atoms/CheckBox.stories.js create mode 100644 webpack/react-components/src/atoms/CitizenConsentForm.js create mode 100644 webpack/react-components/src/atoms/CitizenHomeCard.js create mode 100644 webpack/react-components/src/atoms/CitizenInfoLabel.js create mode 100644 webpack/react-components/src/atoms/CloseButton.js create mode 100644 webpack/react-components/src/atoms/CollapseAndExpandGroups.js create mode 100644 webpack/react-components/src/atoms/ConnectingCheckPoints.js create mode 100644 webpack/react-components/src/atoms/ConnectingCheckPoints.stories.js create mode 100644 webpack/react-components/src/atoms/CustomButton.js create mode 100644 webpack/react-components/src/atoms/DatePicker.js create mode 100644 webpack/react-components/src/atoms/DateWrap.js create mode 100644 webpack/react-components/src/atoms/DateWrap.stories.js create mode 100644 webpack/react-components/src/atoms/DescriptionText.js create mode 100644 webpack/react-components/src/atoms/DescriptionText.stories.js create mode 100644 webpack/react-components/src/atoms/DisplayPhotos.js create mode 100644 webpack/react-components/src/atoms/DisplayPhotos.stories.js create mode 100644 webpack/react-components/src/atoms/Dropdown.js create mode 100644 webpack/react-components/src/atoms/Dropdown.stories.js create mode 100644 webpack/react-components/src/atoms/EllipsisMenu.js create mode 100644 webpack/react-components/src/atoms/EmployeeAppContainer.js create mode 100644 webpack/react-components/src/atoms/EmployeeModuleCard.js create mode 100644 webpack/react-components/src/atoms/ErrorMessage.js create mode 100644 webpack/react-components/src/atoms/EventCalendarView.js create mode 100644 webpack/react-components/src/atoms/GreyOutText.js create mode 100644 webpack/react-components/src/atoms/Hamburger.js create mode 100644 webpack/react-components/src/atoms/Header.js create mode 100644 webpack/react-components/src/atoms/HeaderBar.js create mode 100644 webpack/react-components/src/atoms/HeaderBar.stories.js create mode 100644 webpack/react-components/src/atoms/HomeLink.js create mode 100644 webpack/react-components/src/atoms/HomeLink.stories.js create mode 100644 webpack/react-components/src/atoms/HorizontalNav.js create mode 100644 webpack/react-components/src/atoms/HorizontalNavV2.js create mode 100644 webpack/react-components/src/atoms/ImageUploadHandler.js create mode 100644 webpack/react-components/src/atoms/ImageViewer.js create mode 100644 webpack/react-components/src/atoms/ImageViewer.stories.js create mode 100644 webpack/react-components/src/atoms/InboxLinks.js create mode 100644 webpack/react-components/src/atoms/InboxSearchLinks.js create mode 100644 webpack/react-components/src/atoms/InfoBanner.js create mode 100644 webpack/react-components/src/atoms/InputTextAmount.js create mode 100644 webpack/react-components/src/atoms/KeyNote.js create mode 100644 webpack/react-components/src/atoms/KeyNote.stories.js create mode 100644 webpack/react-components/src/atoms/Label.js create mode 100644 webpack/react-components/src/atoms/LabelFieldPair.js create mode 100644 webpack/react-components/src/atoms/LinkButton.js create mode 100644 webpack/react-components/src/atoms/LinkButton.stories.js create mode 100644 webpack/react-components/src/atoms/LinkLabel.js create mode 100644 webpack/react-components/src/atoms/Loader.js create mode 100644 webpack/react-components/src/atoms/Loader.stories.js create mode 100644 webpack/react-components/src/atoms/LoaderWithGap.js create mode 100644 webpack/react-components/src/atoms/LocationSearch.js create mode 100644 webpack/react-components/src/atoms/Menu.js create mode 100644 webpack/react-components/src/atoms/Menu.stories.js create mode 100644 webpack/react-components/src/atoms/MobileNumber.js create mode 100644 webpack/react-components/src/atoms/Modals/WorkflowPopup.js create mode 100644 webpack/react-components/src/atoms/Modals/config/configEstimateModal.js create mode 100644 webpack/react-components/src/atoms/Modals/index.js create mode 100644 webpack/react-components/src/atoms/MultiLink.js create mode 100644 webpack/react-components/src/atoms/MultiSelectDropdown.js create mode 100644 webpack/react-components/src/atoms/NavBar.js create mode 100644 webpack/react-components/src/atoms/NoResultsFound.js create mode 100644 webpack/react-components/src/atoms/OTPInput.js create mode 100644 webpack/react-components/src/atoms/OTPInput.stories.js create mode 100644 webpack/react-components/src/atoms/OpenLinkContainer.js create mode 100644 webpack/react-components/src/atoms/Paragraph.js create mode 100644 webpack/react-components/src/atoms/PopUp.js create mode 100644 webpack/react-components/src/atoms/PopupHeadingLabel.js create mode 100644 webpack/react-components/src/atoms/PrivateRoute.js create mode 100644 webpack/react-components/src/atoms/RadioButtons.js create mode 100644 webpack/react-components/src/atoms/RadioButtons.stories.js create mode 100644 webpack/react-components/src/atoms/Rating.js create mode 100644 webpack/react-components/src/atoms/Rating.stories.js create mode 100644 webpack/react-components/src/atoms/Reason.js create mode 100644 webpack/react-components/src/atoms/RemovableTagNew.js create mode 100644 webpack/react-components/src/atoms/RemoveableTag.js create mode 100644 webpack/react-components/src/atoms/RoundedLabel.js create mode 100644 webpack/react-components/src/atoms/SVG.js create mode 100644 webpack/react-components/src/atoms/SearchComponent.js create mode 100644 webpack/react-components/src/atoms/SearchableDropdown.js create mode 100644 webpack/react-components/src/atoms/SectionalDropdown.js create mode 100644 webpack/react-components/src/atoms/StandaloneSearchBar.js create mode 100644 webpack/react-components/src/atoms/StatusTable.js create mode 100644 webpack/react-components/src/atoms/SubMenu.js create mode 100644 webpack/react-components/src/atoms/SubmitBar.js create mode 100644 webpack/react-components/src/atoms/SubmitBar.stories.js create mode 100644 webpack/react-components/src/atoms/TLCaption.js create mode 100644 webpack/react-components/src/atoms/Table.js create mode 100644 webpack/react-components/src/atoms/TelePhone.js create mode 100644 webpack/react-components/src/atoms/TelePhone.stories.js create mode 100644 webpack/react-components/src/atoms/TextArea.js create mode 100644 webpack/react-components/src/atoms/TextArea.stories.js create mode 100644 webpack/react-components/src/atoms/TextInput.js create mode 100644 webpack/react-components/src/atoms/TextInput.stories.js create mode 100644 webpack/react-components/src/atoms/Toast.js create mode 100644 webpack/react-components/src/atoms/Toast.stories.js create mode 100644 webpack/react-components/src/atoms/ToggleSwitch.js create mode 100644 webpack/react-components/src/atoms/TopBar.js create mode 100644 webpack/react-components/src/atoms/TopBar.stories.js create mode 100644 webpack/react-components/src/atoms/ULBHomeCard.js create mode 100644 webpack/react-components/src/atoms/UnMaskComponent.js create mode 100644 webpack/react-components/src/atoms/UploadFile.js create mode 100644 webpack/react-components/src/atoms/UploadImages.js create mode 100644 webpack/react-components/src/atoms/UploadImages.stories.js create mode 100644 webpack/react-components/src/atoms/ViewDetailsCard.js create mode 100644 webpack/react-components/src/atoms/ViewImages.js create mode 100644 webpack/react-components/src/atoms/WeekPicker.js create mode 100644 webpack/react-components/src/atoms/WhatsNewCard.js create mode 100644 webpack/react-components/src/atoms/WorkflowActions.js create mode 100644 webpack/react-components/src/atoms/WorkflowTimeline.js create mode 100644 webpack/react-components/src/atoms/XlsPreview.js create mode 100644 webpack/react-components/src/atoms/amtUtils/index.js create mode 100644 webpack/react-components/src/atoms/contants.js create mode 100644 webpack/react-components/src/atoms/svgindex.js create mode 100644 webpack/react-components/src/context/index.js create mode 100644 webpack/react-components/src/hoc/FileUploadModal.js create mode 100644 webpack/react-components/src/hoc/FormComposer.js create mode 100644 webpack/react-components/src/hoc/FormComposerV2.js create mode 100644 webpack/react-components/src/hoc/InboxComposer/MobileComponentDirectory.js create mode 100644 webpack/react-components/src/hoc/InboxComposer/index.js create mode 100644 webpack/react-components/src/hoc/InboxSearchComposer.js create mode 100644 webpack/react-components/src/hoc/InboxSearchComposerContext.js create mode 100644 webpack/react-components/src/hoc/InboxSearchComposerReducer.js create mode 100644 webpack/react-components/src/hoc/InboxSearchComposerV2.js create mode 100644 webpack/react-components/src/hoc/MobileView/MobileSearchComponent.js create mode 100644 webpack/react-components/src/hoc/MobileView/MobileSearchResults.js create mode 100644 webpack/react-components/src/hoc/MobileView/MobileSearchResultsv1.js create mode 100644 webpack/react-components/src/hoc/Modal.js create mode 100644 webpack/react-components/src/hoc/RemovableTags.js create mode 100644 webpack/react-components/src/hoc/ResponseComposer.js create mode 100644 webpack/react-components/src/hoc/ResultsTable.js create mode 100644 webpack/react-components/src/hoc/SubformComposer.js create mode 100644 webpack/react-components/src/hoc/Tutorial/Help.js create mode 100644 webpack/react-components/src/hoc/Tutorial/Readme.md create mode 100644 webpack/react-components/src/hoc/Tutorial/TourProvider.js create mode 100644 webpack/react-components/src/hoc/Tutorial/Tutorial.js create mode 100644 webpack/react-components/src/hoc/UploadFileComposer.js create mode 100644 webpack/react-components/src/hoc/ViewComposer/Readme.md create mode 100644 webpack/react-components/src/hoc/ViewComposer/index.js create mode 100644 webpack/react-components/src/hoc/ViewComposer/renderUtils.js create mode 100644 webpack/react-components/src/hoc/formUtils.js create mode 100644 webpack/react-components/src/index.js create mode 100644 webpack/react-components/src/molecules/ApiCheckboxes.js create mode 100644 webpack/react-components/src/molecules/ApiDropdown.js create mode 100644 webpack/react-components/src/molecules/CityMohalla.js create mode 100644 webpack/react-components/src/molecules/CityMohalla.stories.js create mode 100644 webpack/react-components/src/molecules/CustomDropdown.js create mode 100644 webpack/react-components/src/molecules/DashboardBox.js create mode 100644 webpack/react-components/src/molecules/DateRange.js create mode 100644 webpack/react-components/src/molecules/DateRangeNew.js create mode 100644 webpack/react-components/src/molecules/DetailsCard.js create mode 100644 webpack/react-components/src/molecules/DetailsCard.stories.js create mode 100644 webpack/react-components/src/molecules/FilterAction.js create mode 100644 webpack/react-components/src/molecules/FilterForm.js create mode 100644 webpack/react-components/src/molecules/FormStep.js create mode 100644 webpack/react-components/src/molecules/FormStep.stories.js create mode 100644 webpack/react-components/src/molecules/InputCard.js create mode 100644 webpack/react-components/src/molecules/InputCard.stories.js create mode 100644 webpack/react-components/src/molecules/Localities.js create mode 100644 webpack/react-components/src/molecules/LocationDropdownWrapper.js create mode 100644 webpack/react-components/src/molecules/LocationSearchCard.js create mode 100644 webpack/react-components/src/molecules/LocationSearchCard.stories.js create mode 100644 webpack/react-components/src/molecules/MultiUploadWrapper.js create mode 100644 webpack/react-components/src/molecules/OnGroundEventCard.js create mode 100644 webpack/react-components/src/molecules/PageBasedInput.js create mode 100644 webpack/react-components/src/molecules/PitDimension.js create mode 100644 webpack/react-components/src/molecules/RadioOrSelect.js create mode 100644 webpack/react-components/src/molecules/RatingCard.js create mode 100644 webpack/react-components/src/molecules/RatingCard.stories.js create mode 100644 webpack/react-components/src/molecules/RenderFormFields.js create mode 100644 webpack/react-components/src/molecules/SearchAction.js create mode 100644 webpack/react-components/src/molecules/SearchForm.js create mode 100644 webpack/react-components/src/molecules/SearchOnRadioButtons.js create mode 100644 webpack/react-components/src/molecules/SortAction.js create mode 100644 webpack/react-components/src/molecules/TextInputCard.js create mode 100644 webpack/react-components/src/molecules/TextInputCard.stories.js create mode 100644 webpack/react-components/src/molecules/TypeSelectCard.js create mode 100644 webpack/react-components/src/molecules/TypeSelectCard.stories.js create mode 100644 webpack/react-components/src/molecules/UploadPitPhoto.js create mode 100644 webpack/react-components/src/molecules/WorkflowModal.js create mode 100644 webpack/react-components/src/molecules/WorkflowStatusFilter.js create mode 100644 webpack/react-components/src/stories/Button.js create mode 100644 webpack/react-components/src/stories/Button.stories.js create mode 100644 webpack/react-components/src/stories/Header.js create mode 100644 webpack/react-components/src/stories/Header.stories.js create mode 100644 webpack/react-components/src/stories/Introduction.stories.mdx create mode 100644 webpack/react-components/src/stories/Page.js create mode 100644 webpack/react-components/src/stories/Page.stories.js create mode 100644 webpack/react-components/src/stories/assets/code-brackets.svg create mode 100644 webpack/react-components/src/stories/assets/colors.svg create mode 100644 webpack/react-components/src/stories/assets/comments.svg create mode 100644 webpack/react-components/src/stories/assets/direction.svg create mode 100644 webpack/react-components/src/stories/assets/flow.svg create mode 100644 webpack/react-components/src/stories/assets/plugin.svg create mode 100644 webpack/react-components/src/stories/assets/repo.svg create mode 100644 webpack/react-components/src/stories/assets/stackalt.svg create mode 100644 webpack/react-components/src/stories/button.css create mode 100644 webpack/react-components/src/stories/header.css create mode 100644 webpack/react-components/src/stories/page.css create mode 100644 webpack/react-components/webpack.config.js diff --git a/.github/workflows/publishComponents.yml b/.github/workflows/publishComponents.yml index eec19f17fa3..097cff4560c 100644 --- a/.github/workflows/publishComponents.yml +++ b/.github/workflows/publishComponents.yml @@ -5,6 +5,8 @@ on: branches: [ 'develop-webpack' ] paths: - 'webpack/ui-components/**' + - 'webpack/react-components/**' + - 'webpack/svg-components/**' - 'webpack/libraries/**' - 'react/modules/core/**' @@ -37,6 +39,42 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.npm_token }} + publish-webpack-svg-components: + name: Publish Webpack SVG Components + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 20 + registry-url: https://registry.npmjs.org/ + - name: Install dependencies for Webpack UI Components + run: | + cd webpack/svg-components/ + rm -rf node_modules yarn.lock + yarn install --frozen-lockfile + npm publish --tag core-webpack-v0.1 + env: + NODE_AUTH_TOKEN: ${{ secrets.npm_token }} + + publish-webpack-react-components: + name: Publish Webpack React Components + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 20 + registry-url: https://registry.npmjs.org/ + - name: Install dependencies for Webpack UI Components + run: | + cd webpack/react-components/ + rm -rf node_modules yarn.lock + yarn install --frozen-lockfile + npm publish --tag core-webpack-v0.1 + env: + NODE_AUTH_TOKEN: ${{ secrets.npm_token }} + publish-react-module-libraries: name: Publish React Module Libraries runs-on: ubuntu-latest diff --git a/webpack/libraries/package.json b/webpack/libraries/package.json index 374e4899249..a61764f8260 100644 --- a/webpack/libraries/package.json +++ b/webpack/libraries/package.json @@ -1,6 +1,6 @@ { "name": "@egovernments/digit-ui-libraries", - "version": "1.8.1-upgrade.4", + "version": "1.8.1-upgrade.5", "main": "dist/main.js", "module": "dist/main.js", "source": "src/index.js", @@ -48,13 +48,13 @@ "i18next-react-postprocessor": "3.0.7", "pdfmake": "0.1.72", "react": "19.0.0", - "react-i18next": "11.16.2", + "react-i18next": "15.0.0", "react-redux": "7.2.8", "react-router-dom": "5.3.0", "redux": "4.1.2", "xlsx": "0.17.5", - "@egovernments/digit-ui-components": "0.0.2-beta.3-webpack.2", - "@egovernments/digit-ui-svg-components": "1.0.9" + "@egovernments/digit-ui-components": "0.0.2-beta.4-webpack.2", + "@egovernments/digit-ui-svg-components": "1.0.0-upgrade.1" }, "browserslist": { "production": [ diff --git a/webpack/react-components/.babelrc b/webpack/react-components/.babelrc new file mode 100644 index 00000000000..5f90443d15e --- /dev/null +++ b/webpack/react-components/.babelrc @@ -0,0 +1,5 @@ +{ + "presets": [ + "@babel/preset-env","@babel/preset-react" + ] + } \ No newline at end of file diff --git a/webpack/react-components/.storybook/main.js b/webpack/react-components/.storybook/main.js new file mode 100644 index 00000000000..c9fc54bc80a --- /dev/null +++ b/webpack/react-components/.storybook/main.js @@ -0,0 +1,4 @@ +module.exports = { + stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], + addons: ["@storybook/addon-links", "@storybook/addon-essentials"], +}; diff --git a/webpack/react-components/.storybook/preview.js b/webpack/react-components/.storybook/preview.js new file mode 100644 index 00000000000..5b4ce217235 --- /dev/null +++ b/webpack/react-components/.storybook/preview.js @@ -0,0 +1,9 @@ +import "@egovernments/digit-ui-css/example/index.css"; +import { initLibraries } from "@egovernments/digit-ui-libraries"; + +// TODO: It should be removed bcz we should not use any library in components +initLibraries(); + +export const parameters = { + actions: { argTypesRegex: "^on[A-Z].*" }, +}; diff --git a/webpack/react-components/CHANGELOG.md b/webpack/react-components/CHANGELOG.md new file mode 100644 index 00000000000..e377e5a0db3 --- /dev/null +++ b/webpack/react-components/CHANGELOG.md @@ -0,0 +1,171 @@ +Here's the `CHANGELOG` file for the specified versions: + +```markdown +# Changelog + +## [1.8.22] [3-Feb-2025] +- FEATURE/HCMPRE-2208 : Fixed some loader component issue in inbox & form composers + +## [1.8.15] [1-Feb-2025] +- FEATURE/HCMPRE-1425 : Added the workbench module patches and Updated localisation search screen, and core module #2181 +- Upgraded with new Components in core, workbench screens + +## [1.8.10] [19-Nov-2024] +- Republihsing the same due to component version issue, + + +## [1.8.3] [19-Nov-2024] +- Updated Landing page css and made the stable version with new components integrated core + sandbox + + +## [1.8.2-beta.19] +- Updated the Employee Module card component + +## [1.8.2-beta.17] +- updated loader component style + + +## [1.8.2-beta.12] +- updated serachcomponent for using inboxserachcomposer inside popup + +## [1.8.2-beta.11] +- fix: Sending disabled in radiobuttons from customdropdown. Added skiplabel prop for skiplabel in formComposerV2 + +## [1.8.2-beta.9] +- fix: Fixed uploader issue +## [1.8.2-beta.8] +- fix: Added placeholder prop for Text Field in Inbox Composerv2. + +## [1.8.2-beta.7] +- fix: Fixed prop for the document upload. + +## [1.8.2-beta.5] +- fix: Added submitIcon props for SubmitBar and labelChildren for FormComposerV2. + +## [1.8.2-beta.3] +- fix: Adding the passing of the min field to the TextInput in RenderFormFields. + +## [1.8.2-beta.1] +- fix: resolved AJV-related Jenkins build issue + +## [1.8.1-beta.25] +- Added classname in LabelFieldPair, viewComposer. + +## [1.8.1-beta.23] +- Enhanced onFormValueChange in formComposer. + +## [1.8.1-beta.22] +- Fixed Tutorial. + +## [1.8.1-beta.21] +- Added classname in Modal. + +## [1.8.1-beta.20] +- Changes in Tutorial, help for more customizability. + +## [1.8.1-beta.19] +- Increased zIndex in Tutorial, so it appears on top of everything. + +## [1.8.1-beta.17] +- Added error classname for fields in renderFormFields. + +## [1.8.1-beta.16] +- Added error classname for toast. + +## [1.8.1-beta.15] +- Used a new Primary constant color "#c84c0e". + - **Note:** Use this version with CSS 1.8.1-beta.8 and core 1.8.1-beta.12. + +## [1.8.1-beta.14] +- Updated code for pagination in ResultsTable component. + +## [1.8.1-beta.13] +- Updated InboxSearchComposerV2 to support custom hook call and refetch option. + +## [1.8.1-beta.12] +- Fixed Tab inbox missing code. + +## [1.8.1-beta.10] +- Introduced `InboxSearchComposerV2` component with browser session integration, removable tags for search/inbox screens on mobile, and a unified configuration for both mobile and desktop screens. + +## [1.8.1-beta.9] +- Fixed Loader with gap. + +## [1.8.1-beta.8] +- Added Close button and Loader. + +## [1.8.1-beta.7] +- Enhanced viewComposer for cardHeader action. + +## [1.8.1-beta.6] +- Added feature for Multi Tab in InboxSearchComposer. + +## [1.8.1-beta.5] +- Added without LabelFieldPair config for removing default card. + +## [1.8.1-beta.4] +- Added Previous button in FormComposer. + +## [1.8.1-beta.3] +- Added XlsPreview component to preview XLS file. + +## [1.8.1-beta.2] +- Moved the sidebar footer outside of "drawer-list" to prevent overlapping issues. + +## [1.8.1-beta.1] +- Republished after merging with Master due to version issues. + +## [1.8.0-beta.5] +- Added file type Excel in multiUploadWrapper. + +## [1.8.0-beta.4] +- Republished. + +## [1.8.0-beta.3] +- Republished due to some issues. + +## [1.8.0-beta.2] +- Added some icons for PQM dashboard. + +## [1.8.0-beta.1] +- Fixed some topbar issues. + +## [1.8.0] +- Workbench v1.0 release. + +## [1.8.0-beta] +- Workbench base version beta release. + +## [1.7.0] +- Urban 2.9. + +## [1.6.0] +- Urban 2.8. + +## [1.5.36] +- Added classname for topbar options. + +## [1.5.35] +- Fixed alignment issue in edit and logout. + +## [1.5.34] +- Updated login SCSS and alignment issues. + +## [1.5.28] +- Passing response data in case for custom component in inbox composer. + +## [1.5.27] +- Integrated with the SVG library. + +## [1.5.26] +- Fixed shipping truck icon fill issue. + +## [1.5.25] +- Added new icon and fixed other issues. + +## [1.5.24] +- Added and updated the README file. + +## [1.5.23] +- Base version. +``` \ No newline at end of file diff --git a/webpack/react-components/README.md b/webpack/react-components/README.md new file mode 100644 index 00000000000..0ae4afe6568 --- /dev/null +++ b/webpack/react-components/README.md @@ -0,0 +1,161 @@ + + + + +# digit-ui-react-components + +## Install + +```bash +npm install --save @egovernments/digit-ui-react-components +``` + +## Limitation + +```bash +This package is specifically designed for DIGIT-UI but can be used across various missions. +``` + +## Usage + +After adding the dependency make sure you have this dependency in + +```bash +frontend/micro-ui/web/package.json +``` + +```json +"@egovernments/digit-ui-react-components":"1.5.24", +``` + +then navigate to App.js + +```bash + frontend/micro-ui/web/src/App.js +``` + +Syntax for importing any component; + +```jsx +import React, { Component } from "react"; +import MyComponent from "@egovernments/digit-ui-react-components"; + +class Example extends Component { + render() { + return ; + } +} +``` +Syntax for the Inbox Composers + +```jsx + import { InboxSearchComposer } from "@egovernments/digit-ui-react-components"; + + +
{t(updatedConfig?.label)}
+
+ +
+
+``` + +Syntax for the FormComposersV2 + +```jsx + import { FormComposerV2 as FormComposer } from "@egovernments/digit-ui-react-components"; + + +
{t("CREATE_HEADER")}
+ { + return { + ...config, + body: config.body.filter((a) => !a.hideInEmployee), + }; + })} + defaultValues={sessionFormData} + onFormValueChange={onFormValueChange} + onSubmit={onFormSubmit} + fieldStyle={{ marginRight: 0 }} + className="form-no-margin" + labelBold={true} + /> +
+``` + +To use the InboxSearchComposer component for managing multiple tabs, follow these steps: + 1. Set `showTab: true` in the inboxconfig. + 2. In the Config array, include configuration objects for each tab. For example: + ```javascript + export const inboxconfig = { + tenantId: "pb", + moduleName: "inboxconfigUiConfig", + showTab: true, + inboxconfig: [ + { + ... + }, + { + ... + } + ] + ``` + 3. Implement custom limit offset by adding customDefaultPagination under uiConfig in the searchResult: + ```javascript + customDefaultPagination: { + limit: 5, + offset: 0, + }, + ``` + 4. For custom table sizes, add an array of page sizes in customPageSizesArray under uiConfig in the searchResult: + ```javascript + customPageSizesArray: [5, 10, 15, 20], + ``` + 5. In the Inbox Screen, initialize the following states: + This state will by default take first object from array config + ```javascript + const [config, setConfig] = useState(myCampaignConfig?.myCampaignConfig?.[0]); + ``` + TabData state used to fetch which tab is active + ```javascript + const [tabData, setTabData] = useState(myCampaignConfig?.myCampaignConfig?.map((i, n) => ({ key: n, label: i.label, active: n === 0 ? true : false }))); + ``` + Add function to perform when tab changes. Here we are setting the respective tab active and updating its config + ```javascript + const onTabChange = (n) => { + setTabData((prev) => prev.map((i, c) => ({ ...i, active: c === n ? true : false }))); + setConfig(myCampaignConfig?.myCampaignConfig?.[n]); + }; + ``` + 6 At last pass all these in InboxSearchComposer props. + +```jsx + +``` + +## Changelog + +### Summary for Version [1.8.2-beta.1] - 2024-06-05 + +For a detailed changelog, see the [CHANGELOG.md](./CHANGELOG.md) file. + + +### Contributors + +[jagankumar-egov] [nipunarora-eGov] [Tulika-eGov] [Ramkrishna-egov] [nabeelmd-eGov] [anil-egov] [vamshikrishnakole-wtt-egov] + +## Documentation + +Documentation Site (https://core.digit.org/guides/developer-guide/ui-developer-guide/digit-ui) + +## Maintainer + +- [jagankumar-egov](https://www.github.com/jagankumar-egov) + + +### Published from DIGIT Frontend +DIGIT Frontend Repo (https://github.com/egovernments/Digit-Frontend/tree/develop) + + +![Logo](https://s3.ap-south-1.amazonaws.com/works-dev-asset/mseva-white-logo.png) diff --git a/webpack/react-components/docker/Dockerfile b/webpack/react-components/docker/Dockerfile new file mode 100644 index 00000000000..89bb70f8ead --- /dev/null +++ b/webpack/react-components/docker/Dockerfile @@ -0,0 +1,21 @@ +FROM egovio/alpine-node-builder-14:yarn AS build +RUN apk update && apk upgrade +RUN apk add --no-cache git>2.30.0 +ARG WORK_DIR +WORKDIR /app +ENV NODE_OPTIONS "--max-old-space-size=1792" + +COPY ${WORK_DIR} . + +#RUN node web/envs.js +RUN node envs.js \ + && yarn install \ + && yarn build-storybook + +FROM nginx:mainline-alpine +ENV WORK_DIR=/var/web/storybook + +RUN mkdir -p ${WORK_DIR} + +COPY --from=build /app/build ${WORK_DIR}/ +COPY --from=build /app/docker/nginx.conf /etc/nginx/conf.d/default.conf \ No newline at end of file diff --git a/webpack/react-components/docker/nginx.conf b/webpack/react-components/docker/nginx.conf new file mode 100644 index 00000000000..9147f7f50a7 --- /dev/null +++ b/webpack/react-components/docker/nginx.conf @@ -0,0 +1,12 @@ +server +{ + listen 80; + underscores_in_headers on; + + location /storybook + { + root /var/web/; + index index.html index.htm; + try_files $uri $uri/ /storybook/index.html; + } +} \ No newline at end of file diff --git a/webpack/react-components/envs.js b/webpack/react-components/envs.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/webpack/react-components/package.json b/webpack/react-components/package.json new file mode 100644 index 00000000000..ceae677cc08 --- /dev/null +++ b/webpack/react-components/package.json @@ -0,0 +1,96 @@ +{ + "name": "@egovernments/digit-ui-react-components", + "version": "1.8.16-upgrade.1", + "license": "MIT", + "main": "dist/main.js", + "module": "dist/main.js", + "source": "src/index.js", + "engines": { + "node": ">=18" + }, + "scripts": { + "example": "cd example && npm run start", + "build": "webpack --mode=production --node-env=production --config webpack.config.js", + "start": "microbundle-crl watch --no-compress --format modern,cjs", + "prepare": "yarn build", + "predeploy": "cd example && yarn install && yarn run build", + "deploy": "gh-pages -d example/build", + "storybook": "start-storybook -p 6006 -s public", + "build-storybook": "build-storybook -s public -o dist-storybook", + "deploy-storybook": "npm run build-storybook && surge --project dist-storybook --domain react-components-$npm_package_version.surge.sh" + }, + "peerDependencies": { + "react": "19.0.0", + "react-router-dom": "5.3.0" + }, + "devDependencies": { + "@storybook/addon-actions": "6.4.20", + "@storybook/addon-essentials": "6.4.20", + "@storybook/addon-links": "6.4.20", + "@storybook/node-logger": "6.4.20", + "@storybook/preset-create-react-app": "3.2.0", + "@storybook/react": "6.4.20", + "babel-eslint": "10.1.0", + "cross-env": "7.0.3", + "gh-pages": "2.2.0", + "husky": "7.0.4", + "lint-staged": "12.3.7", + "microbundle-crl": "0.13.11", + "react": "19.0.0", + "react-dom": "19.0.0", + "react-responsive": "9.0.2", + "react-router-dom": "5.3.0", + "react-scripts": "^4.0.1", + "@babel/core": "^7.23.3", + "@babel/preset-env": "^7.23.3", + "@babel/preset-react": "^7.23.3", + "babel-loader": "8.0.0", + "webpack": "^5.97.1", + "webpack-cli": "^4.10.0" + }, + "files": [ + "dist" + ], + "dependencies": { + "@egovernments/digit-ui-svg-components":"1.0.0-upgrade.1", + "@egovernments/digit-ui-components":"0.0.2-beta.4-webpack.2", + "@googlemaps/js-api-loader": "1.13.10", + "@hookform/resolvers": "1.3.7", + "ajv": "8.11.2", + "ajv-errors": "3.0.0", + "ajv-formats": "2.1.1", + "json-schema-to-yup": "1.8.8", + "react-date-range": "2.0.1", + "react-drag-drop-files": "2.3.10", + "react-hook-form": "7.52.2", + "react-i18next": "15.0.0", + "react-table": "7.7.0", + "react-joyride": "2.5.5", + "@cyntler/react-doc-viewer": "1.10.3" + }, + "resolutions": { + "**/ajv": "8.11.2", + "fast-uri":"2.1.0" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "author": "JaganKumar ", + "keywords": [ + "digit", + "egov", + "dpg", + "digit-ui", + "react", + "components" + ] +} diff --git a/webpack/react-components/public/index.html b/webpack/react-components/public/index.html new file mode 100644 index 00000000000..b6e30e526b9 --- /dev/null +++ b/webpack/react-components/public/index.html @@ -0,0 +1,28 @@ + + + + + + + + + React App + + + +
+ + + \ No newline at end of file diff --git a/webpack/react-components/src/atoms/ActionBar.js b/webpack/react-components/src/atoms/ActionBar.js new file mode 100644 index 00000000000..ddfca0aadc3 --- /dev/null +++ b/webpack/react-components/src/atoms/ActionBar.js @@ -0,0 +1,11 @@ +import React from "react"; + +const ActionBar = (props) => { + return ( +
+ {props.children} +
+ ); +}; + +export default ActionBar; diff --git a/webpack/react-components/src/atoms/ActionLinks.js b/webpack/react-components/src/atoms/ActionLinks.js new file mode 100644 index 00000000000..643f034b7c1 --- /dev/null +++ b/webpack/react-components/src/atoms/ActionLinks.js @@ -0,0 +1,5 @@ +import React from "react"; + +const ActionLinks = (props) => {props.children}; + +export default ActionLinks; diff --git a/webpack/react-components/src/atoms/Amount.js b/webpack/react-components/src/atoms/Amount.js new file mode 100644 index 00000000000..4fbcd888b0d --- /dev/null +++ b/webpack/react-components/src/atoms/Amount.js @@ -0,0 +1,12 @@ +import React from "react"; + + /* Amount component by default round offs and formats for amount */ + +const Amount = ({t,roundOff=true,...props}) => { + const value=roundOff?Math.round(props?.value):props?.value; + return ( +

{value ? `${Digit?.Utils?.dss?.formatterWithoutRound(value, "number")}` : t("ES_COMMON_NA")}

+ ) +} + +export default Amount; \ No newline at end of file diff --git a/webpack/react-components/src/atoms/AppContainer.js b/webpack/react-components/src/atoms/AppContainer.js new file mode 100644 index 00000000000..a6ca8aa5d52 --- /dev/null +++ b/webpack/react-components/src/atoms/AppContainer.js @@ -0,0 +1,13 @@ +import React from "react"; + +const AppContainer = (props) => { + return ( + +
+ {props.children} +
+
+ ); +}; + +export default AppContainer; diff --git a/webpack/react-components/src/atoms/ApplyFilterBar.js b/webpack/react-components/src/atoms/ApplyFilterBar.js new file mode 100644 index 00000000000..49ff45a020e --- /dev/null +++ b/webpack/react-components/src/atoms/ApplyFilterBar.js @@ -0,0 +1,16 @@ +import React from "react"; + +const ApplyFilterBar = (props) => { + return ( +
+ + +
+ ); +}; + +export default ApplyFilterBar; diff --git a/webpack/react-components/src/atoms/BackButton.js b/webpack/react-components/src/atoms/BackButton.js new file mode 100644 index 00000000000..995f9ec6c11 --- /dev/null +++ b/webpack/react-components/src/atoms/BackButton.js @@ -0,0 +1,16 @@ +import React from "react"; +import { ArrowLeft, ArrowLeftWhite } from "./svgindex"; +import { withRouter } from "react-router-dom"; +import { useTranslation } from "react-i18next"; + +const BackButton = ({ history, style, isSuccessScreen, isCommonPTPropertyScreen, getBackPageNumber, className="" ,variant="black"}) => { + const { t } = useTranslation(); + + return ( +
{!isSuccessScreen ?( !isCommonPTPropertyScreen ? (history.goBack(), window.location.href.includes("/citizen/pt/property/new-application/property-type") ? sessionStorage.setItem("docReqScreenByBack",true) : null) : history.go(getBackPageNumber()) ): null}}> + {variant=="black"?( +

{t("CS_COMMON_BACK")}

):} +
+ ); +}; +export default withRouter(BackButton); diff --git a/webpack/react-components/src/atoms/Banner.js b/webpack/react-components/src/atoms/Banner.js new file mode 100644 index 00000000000..520dfb72f78 --- /dev/null +++ b/webpack/react-components/src/atoms/Banner.js @@ -0,0 +1,82 @@ +import React from "react"; +import { SuccessSvg,TickMark } from "./svgindex"; +import { ErrorSvg } from "./svgindex"; +import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; + +const Successful = (props) => { + const { t } = useTranslation(); + const user_type = Digit.SessionStorage.get("userType"); + + return ( +
+
{props.props.message}
+
+ {props.props.whichSvg==="tick"?


: (props?.props?.svg || ) } + {/* {props?.props?.svg || } */} + {(props?.props?.complaintNumber || props.props.info) &&

{props?.props?.complaintNumber ? t("CS_PGR_COMPLAINT_NUMBER") : props.props.info}

} + {(props?.props?.complaintNumber || props?.props?.applicationNumber) &&

{props?.props?.complaintNumber ? props?.props?.complaintNumber : props?.props?.applicationNumber}

} + {props?.props?.applicationNumberOne ?

{props.props.infoOne}

: null} + {props?.props?.applicationNumberOne ?

{props?.props?.applicationNumberOne}

: null} + {props?.props?.multipleResponseIDs && +
+ { + props?.props?.multipleResponseIDs.map(responseIDs=>( +

{responseIDs}

+ )) + } +
+ } +
+
+ ); +}; + +const Error = (props) => { + const { t } = useTranslation(); + const user_type = Digit.SessionStorage.get("userType"); + + return ( +
+
{props.props.message}
+ + {/* error while submition */} +

{props?.props?.complaintNumber ? t("CS_PGR_COMPLAINT_NUMBER") : props.props.info}

+

{props?.props?.complaintNumber ? props?.props?.complaintNumber : props?.props?.applicationNumber}

+ {props?.props?.multipleResponseIDs && +
+ { + props?.props?.multipleResponseIDs.map(responseIDs=>( +

{responseIDs}

+ )) + } +
+ } +
+ ); +}; + +const Banner = (props) => { + return props.successful ? : ; +}; + +Banner.propTypes = { + /** + * Is banner is successful or error? + */ + successful: PropTypes.bool.isRequired, + /** + * Banner message + */ + message: PropTypes.any.isRequired, + /** + * If banner is successful, then show the complaint number + */ + complaintNumber: PropTypes.any, +}; + +Banner.defaultProps = { + successful: true, +}; + +export default Banner; diff --git a/webpack/react-components/src/atoms/Banner.stories.js b/webpack/react-components/src/atoms/Banner.stories.js new file mode 100644 index 00000000000..1eb055735f9 --- /dev/null +++ b/webpack/react-components/src/atoms/Banner.stories.js @@ -0,0 +1,23 @@ +import React from "react"; + +import Banner from "./Banner"; + +export default { + title: "Atom/Banner", + component: Banner, +}; + +const Template = (args) => ; + +export const Successful = Template.bind({}); +Successful.args = { + successful: true, + message: "Your query is resolve.", + complaintNumber: 5343, +}; + +export const Error = Template.bind({}); +Error.args = { + successful: false, + message: "Your query is not resolve.", +}; diff --git a/webpack/react-components/src/atoms/Body.js b/webpack/react-components/src/atoms/Body.js new file mode 100644 index 00000000000..2886f62c1e7 --- /dev/null +++ b/webpack/react-components/src/atoms/Body.js @@ -0,0 +1,7 @@ +import React from "react"; + +const Body = (props) => { + return
{props.children}
; +}; + +export default Body; diff --git a/webpack/react-components/src/atoms/BreadCrumb.js b/webpack/react-components/src/atoms/BreadCrumb.js new file mode 100644 index 00000000000..95997818b33 --- /dev/null +++ b/webpack/react-components/src/atoms/BreadCrumb.js @@ -0,0 +1,53 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { Link } from "react-router-dom"; + +const Breadcrumb = (props) => { + function isLast(index) { + return index === props.crumbs.length - 1; + } + function handleRedirect(path) { + const host = window.location.origin; // Dynamically get the base URL + window.location.href = `${host}${path}`; + } + return ( +
    + {props?.crumbs?.map((crumb, ci) => { + if (!crumb?.show) return; + if (crumb?.isBack) + return ( +
  1. + window.history.back()}> + {crumb.content} + +
  2. + ); + return ( +
  3. + {isLast(ci) || !crumb?.path ? ( + {crumb.content} + ) : ( + crumb?.externalPath ? + ( + handleRedirect(crumb?.path)}>{crumb.content} + ) : + ( + {crumb.content} + ) + )} +
  4. + ); + })} +
+ ); +}; + +Breadcrumb.propTypes = { + crumbs: PropTypes.array, +}; + +Breadcrumb.defaultProps = { + successful: true, +}; + +export default Breadcrumb; diff --git a/webpack/react-components/src/atoms/BreakLine.js b/webpack/react-components/src/atoms/BreakLine.js new file mode 100644 index 00000000000..30112f5809d --- /dev/null +++ b/webpack/react-components/src/atoms/BreakLine.js @@ -0,0 +1,7 @@ +import React from "react"; + +const BreakLine = ({ style = {} }) => { + return
; +}; + +export default BreakLine; diff --git a/webpack/react-components/src/atoms/Button.js b/webpack/react-components/src/atoms/Button.js new file mode 100644 index 00000000000..22e4703d333 --- /dev/null +++ b/webpack/react-components/src/atoms/Button.js @@ -0,0 +1,76 @@ +import React from "react"; +import PropTypes from "prop-types"; + +/** + * Button Component + * + * @author jagankumar-egov + * + * Feature :: CORE + * + * @example + * // Primary button + + ); +}; + +Button.propTypes = { + /** + * ButtonSelector content + */ + label: PropTypes.string.isRequired, + /** + * button border theme + */ + variation: PropTypes.string, + /** + * button icon if any + */ + icon: PropTypes.element, + /** + * click handler + */ + onButtonClick: PropTypes.func.isRequired, + /** + * Custom classname + */ + className: PropTypes.string, + /** + * Custom styles + */ + style: PropTypes.object, + /** + * Custom label style or h2 style + */ + textStyles: PropTypes.object, +}; + +Button.defaultProps = { + label: "TEST", + variation: "primary", + onButtonClick: () => {}, +}; + +export default Button; diff --git a/webpack/react-components/src/atoms/ButtonSelector.js b/webpack/react-components/src/atoms/ButtonSelector.js new file mode 100644 index 00000000000..8eb120c44ac --- /dev/null +++ b/webpack/react-components/src/atoms/ButtonSelector.js @@ -0,0 +1,55 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const ButtonSelector = (props) => { + let theme = "selector-button-primary"; + switch (props.theme) { + case "border": + theme = "selector-button-border"; + break; + default: + theme = "selector-button-primary"; + break; + } + return ( + + ); +}; + +ButtonSelector.propTypes = { + /** + * ButtonSelector content + */ + label: PropTypes.string.isRequired, + /** + * button border theme + */ + theme: PropTypes.string, + /** + * click handler + */ + onSubmit: PropTypes.func, + /** + * CustomBody + */ + ButtonBody: PropTypes.any +}; + +ButtonSelector.defaultProps = { + label: "", + theme: "", + onSubmit: undefined, + ButtonBody: undefined +}; + +export default ButtonSelector; diff --git a/webpack/react-components/src/atoms/ButtonSelector.stories.js b/webpack/react-components/src/atoms/ButtonSelector.stories.js new file mode 100644 index 00000000000..968a5cfb197 --- /dev/null +++ b/webpack/react-components/src/atoms/ButtonSelector.stories.js @@ -0,0 +1,24 @@ +import React from "react"; + +import ButtonSelector from "./ButtonSelector"; + +export default { + title: "Atom/ButtonSelector", + component: ButtonSelector, +}; + +const Template = (args) => ; + +export const Primary = Template.bind({}); +Primary.args = { + label: "Submit", + theme: undefined, + onSubmit: () => alert("You clicked me"), +}; + +export const Secondary = Template.bind({}); +Secondary.args = { + label: "Submit", + theme: "border", + onSubmit: () => alert("You clicked me"), +}; diff --git a/webpack/react-components/src/atoms/Card.js b/webpack/react-components/src/atoms/Card.js new file mode 100644 index 00000000000..4b89fd15e36 --- /dev/null +++ b/webpack/react-components/src/atoms/Card.js @@ -0,0 +1,24 @@ +import React from "react"; +import { useLocation } from "react-router-dom"; + +const Card = ({ onClick, style, children, className, ReactRef, ...props }) => { + const { pathname } = useLocation(); + const classname = Digit.Hooks.useRouteSubscription(pathname); + const info = Digit.UserService.getUser()?.info; + const userType = info?.type; + const isEmployee = classname === "employee" || userType === "EMPLOYEE"; + + return ( +
+ {children} +
+ ); +}; + +export default Card; diff --git a/webpack/react-components/src/atoms/CardBasedOptions.js b/webpack/react-components/src/atoms/CardBasedOptions.js new file mode 100644 index 00000000000..c1b7b96ecc2 --- /dev/null +++ b/webpack/react-components/src/atoms/CardBasedOptions.js @@ -0,0 +1,28 @@ +import React from "react"; + +const Option = ({ name, Icon, onClick, className }) => { + return ( +
+
{Icon}
+

{name}

+
+ ); +}; + +const CardBasedOptions = ({ header, sideOption, options, styles = {}, style={} }) => { + return ( +
+
+

{header}

+

{sideOption.name}

+
+
+ {options.map((props, index) => ( +
+
+ ); +}; + +export default CardBasedOptions; diff --git a/webpack/react-components/src/atoms/CardCaption.js b/webpack/react-components/src/atoms/CardCaption.js new file mode 100644 index 00000000000..42bd8bd4b10 --- /dev/null +++ b/webpack/react-components/src/atoms/CardCaption.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardCaption = (props) => { + return ( + + ); +}; + +export default CardCaption; diff --git a/webpack/react-components/src/atoms/CardHeader.js b/webpack/react-components/src/atoms/CardHeader.js new file mode 100644 index 00000000000..9562f92c763 --- /dev/null +++ b/webpack/react-components/src/atoms/CardHeader.js @@ -0,0 +1,7 @@ +import React from "react"; + +const CardHeader = (props) => { + return
{props.children}
; +}; + +export default CardHeader; diff --git a/webpack/react-components/src/atoms/CardLabel.js b/webpack/react-components/src/atoms/CardLabel.js new file mode 100644 index 00000000000..647b55b5fb4 --- /dev/null +++ b/webpack/react-components/src/atoms/CardLabel.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardLabel = (props) => { + return ( +

+ {props.children} +

+ ); +}; + +export default CardLabel; diff --git a/webpack/react-components/src/atoms/CardLabelDesc.js b/webpack/react-components/src/atoms/CardLabelDesc.js new file mode 100644 index 00000000000..43af6cc3ca4 --- /dev/null +++ b/webpack/react-components/src/atoms/CardLabelDesc.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardLabelDesc = ({ children, style, className }) => { + return ( +

+ {children} +

+ ); +}; + +export default CardLabelDesc; diff --git a/webpack/react-components/src/atoms/CardLabelError.js b/webpack/react-components/src/atoms/CardLabelError.js new file mode 100644 index 00000000000..aa5f5804c2e --- /dev/null +++ b/webpack/react-components/src/atoms/CardLabelError.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardLabelError = (props) => { + return ( +

+ {props.children} +

+ ); +}; + +export default CardLabelError; diff --git a/webpack/react-components/src/atoms/CardSectionHeader.js b/webpack/react-components/src/atoms/CardSectionHeader.js new file mode 100644 index 00000000000..57d9639b66d --- /dev/null +++ b/webpack/react-components/src/atoms/CardSectionHeader.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardSectionHeader = (props) => { + return ( +
+ {props.children} +
+ ); +}; + +export default CardSectionHeader; diff --git a/webpack/react-components/src/atoms/CardSectionSubText.js b/webpack/react-components/src/atoms/CardSectionSubText.js new file mode 100644 index 00000000000..373caa2a0be --- /dev/null +++ b/webpack/react-components/src/atoms/CardSectionSubText.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardSectionSubText = (props) => { + return ( +
+ {props.children} +
+ ); +}; + +export default CardSectionSubText; diff --git a/webpack/react-components/src/atoms/CardSubHeader.js b/webpack/react-components/src/atoms/CardSubHeader.js new file mode 100644 index 00000000000..d7a33c18650 --- /dev/null +++ b/webpack/react-components/src/atoms/CardSubHeader.js @@ -0,0 +1,16 @@ +import React from "react"; + +const CardSubHeader = (props) => { + const user_type = Digit.SessionStorage.get("user_type") === "employee" ? true : false; + + return ( +
+ {props.children} +
+ ); +}; + +export default CardSubHeader; diff --git a/webpack/react-components/src/atoms/CardText.js b/webpack/react-components/src/atoms/CardText.js new file mode 100644 index 00000000000..db2bd48cf27 --- /dev/null +++ b/webpack/react-components/src/atoms/CardText.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardText = (props) => { + return ( +

+ {props.children} +

+ ); +}; + +export default CardText; diff --git a/webpack/react-components/src/atoms/CardTextButton.js b/webpack/react-components/src/atoms/CardTextButton.js new file mode 100644 index 00000000000..e573df0888c --- /dev/null +++ b/webpack/react-components/src/atoms/CardTextButton.js @@ -0,0 +1,7 @@ +import React from "react"; + +const CardText = (props) => { + return

{props.children}

; +}; + +export default CardText; diff --git a/webpack/react-components/src/atoms/CheckBox.js b/webpack/react-components/src/atoms/CheckBox.js new file mode 100644 index 00000000000..a1db224cd47 --- /dev/null +++ b/webpack/react-components/src/atoms/CheckBox.js @@ -0,0 +1,89 @@ +import React,{Fragment} from "react"; +import { CheckSvg } from "./svgindex"; +import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; +const CheckBox = ({ onChange, label, value, disable, ref, checked, inputRef, pageType, style, index, isLabelFirst,customLabelMarkup, ...props }) => { + const { t } = useTranslation() + const userType = pageType || Digit.SessionStorage.get("userType"); + let wrkflwStyle = props.styles; + if (isLabelFirst) { + return ( +
+

{index+1}.

+

+ {label} +

+
+ +

+ +

+
+
+ ); + } else { + return ( +
+
+ +

+ {/* */} + +

+
+

+ {customLabelMarkup ? + <> +

{t("COMMON_CERTIFY_ONE")}

+
+

+ {t("ES_COMMON_NOTE")}{t("COMMON_CERTIFY_TWO")} +

+ : label} +

+
+ ); + } + +}; + +CheckBox.propTypes = { + /** + * CheckBox content + */ + label: PropTypes.string.isRequired, + /** + * onChange func + */ + onChange: PropTypes.func, + /** + * input ref + */ + ref: PropTypes.func, + userType: PropTypes.string, +}; + +CheckBox.defaultProps = {}; + +export default CheckBox; diff --git a/webpack/react-components/src/atoms/CheckBox.stories.js b/webpack/react-components/src/atoms/CheckBox.stories.js new file mode 100644 index 00000000000..2253c6d2ccf --- /dev/null +++ b/webpack/react-components/src/atoms/CheckBox.stories.js @@ -0,0 +1,16 @@ +import React from "react"; + +import CheckBox from "./CheckBox"; + +export default { + title: "Atom/CheckBox", + component: CheckBox, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + label: "Agree to terms and conditions", +}; diff --git a/webpack/react-components/src/atoms/CitizenConsentForm.js b/webpack/react-components/src/atoms/CitizenConsentForm.js new file mode 100644 index 00000000000..a11462bd71c --- /dev/null +++ b/webpack/react-components/src/atoms/CitizenConsentForm.js @@ -0,0 +1,71 @@ +import React, { useState, useEffect } from "react"; +import { Loader, Modal } from ".."; + +const Heading = (props) => { + return

{props.label}

; +}; + +const Close = () => ( + + + +); + +const CloseBtn = (props) => { + return ( +
+ +
+ ); +}; + + +const CitizenConsentForm = ({ t, styles, mdmsConfig = "", setMdmsConfig, labels }) => { + const [showModal, setShowModal] = useState(false); + + useEffect(() => { + if (mdmsConfig && !showModal) setShowModal(true) + }, [mdmsConfig]) + + const closeModal = () => { + setShowModal(false); + setMdmsConfig("") + } + + const url = labels?.filter(data => data.linkId == mdmsConfig)?.[0]?.[Digit.StoreData.getCurrentLanguage()]; + + return ( +
+ {showModal ? } + headerBarEnd={} + actionCancelOnSubmit={closeModal} + formId="modal-action" + popupStyles={{ width: "750px", overflow: "auto" }} + style={{ minHeight: "45px", height: "auto", width: "160px" }} + hideSubmit={true} + headerBarMainStyle={{ margin: "0px", height: "35px" }} + + > + {url ? +
+ +
: +
+ {t("COMMON_URL_NOT_FOUND")} +
} + +
: null} +
+ ); +}; + +export default CitizenConsentForm; diff --git a/webpack/react-components/src/atoms/CitizenHomeCard.js b/webpack/react-components/src/atoms/CitizenHomeCard.js new file mode 100644 index 00000000000..1f131101dbe --- /dev/null +++ b/webpack/react-components/src/atoms/CitizenHomeCard.js @@ -0,0 +1,26 @@ +import React from "react"; +import { Link } from "react-router-dom"; + +const CitizenHomeCard = ({ header, links = [], state, Icon, Info, isInfo = false, styles }) => { + return ( +
+
+

{header}

+ +
+ +
+ {links.map((e, i) => ( +
+ + {e.i18nKey} + +
+ ))} +
+
{isInfo ? : null}
+
+ ); +}; + +export default CitizenHomeCard; diff --git a/webpack/react-components/src/atoms/CitizenInfoLabel.js b/webpack/react-components/src/atoms/CitizenInfoLabel.js new file mode 100644 index 00000000000..652146cf887 --- /dev/null +++ b/webpack/react-components/src/atoms/CitizenInfoLabel.js @@ -0,0 +1,22 @@ +import React from "react"; +import { InfoBannerIcon } from "./svgindex"; + +const CitizenInfoLabel = (props) => { + //if type is "component", then props will come from props?.props. + //if the component has props passed directly, then props will be used. + props = props?.props ? props?.props : props; + const showInfo = props?.showInfo ? props?.showInfo : true; + + return ( +
+ {showInfo &&
+ +

{props?.info}

+
+ } +

{props?.text}

+
+ ); +}; + +export default CitizenInfoLabel; diff --git a/webpack/react-components/src/atoms/CloseButton.js b/webpack/react-components/src/atoms/CloseButton.js new file mode 100644 index 00000000000..9da54d70196 --- /dev/null +++ b/webpack/react-components/src/atoms/CloseButton.js @@ -0,0 +1,12 @@ +import React from "react"; +import {SVG} from "./SVG" + +export const CloseButton = ({ onClick, size = "24" }) => { + return ( +
+ +
+ ); +}; + +export default CloseButton; diff --git a/webpack/react-components/src/atoms/CollapseAndExpandGroups.js b/webpack/react-components/src/atoms/CollapseAndExpandGroups.js new file mode 100644 index 00000000000..473440b077f --- /dev/null +++ b/webpack/react-components/src/atoms/CollapseAndExpandGroups.js @@ -0,0 +1,46 @@ +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { SVG } from "./SVG"; +import PropTypes from "prop-types"; + +const CollapseAndExpandGroups = ({ children, groupElements = false, groupHeader = "", headerLabel = "", headerValue = "", customClass = "" ,showHelper=false,collapseState=false}) => { + const { t } = useTranslation(); + const [collapse, setCollapse] = useState(collapseState); + return ( +
+ {groupHeader &&
{t(groupHeader)}
} + {groupElements && ( +
+ {headerLabel} + {headerValue} +
setCollapse((prev) => !prev)} className="digit-icon-toggle "> + {!collapse && ( + + {showHelper&&
{t("COMMON_CORE_COLLAPSE")}
} + +
+ )} + {collapse && ( + + {showHelper&&
{t("COMMON_CORE_EXPAND")}
} + +
+ )} +
+
+ )} +
{children}
+
+ ); +}; + +CollapseAndExpandGroups.propTypes = { + children: PropTypes.node, + style: PropTypes.object, + customClass: PropTypes.string, + groupElements: PropTypes.bool, + groupHeader: PropTypes.string, + headerLabel: PropTypes.string, + headerValue: PropTypes.string, +}; +export default CollapseAndExpandGroups; diff --git a/webpack/react-components/src/atoms/ConnectingCheckPoints.js b/webpack/react-components/src/atoms/ConnectingCheckPoints.js new file mode 100644 index 00000000000..b2e4fa88ad2 --- /dev/null +++ b/webpack/react-components/src/atoms/ConnectingCheckPoints.js @@ -0,0 +1,59 @@ +import React from "react"; +import PropTypes from "prop-types"; + +export const CheckPoint = (props) => { + return ( +
+

+
+ {props.label} + {props.info ?

{props.info}

: null} + {props.customChild ? props.customChild : null} +
+
+ ); +}; + +export const ConnectingCheckPoints = (props) => { + if (props.children && props.children.length >= 1) { + return ( + + {props.children.map((child, index) => { + return props.children.length === ++index ? ( +
{child}
+ ) : ( +
+ {child} +
+
+ ); + })} +
+ ); + } else { + return null; + } +}; + +CheckPoint.propTypes = { + /** + * Is checkpoint completed or not? + */ + isCompleted: PropTypes.bool, + /** + * key value + */ + key: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + /** + * checkpoint content + */ + label: PropTypes.string, + info: PropTypes.string, +}; + +CheckPoint.defaultProps = { + isCompleted: false, + key: 0, + label: "", + info: "", +}; diff --git a/webpack/react-components/src/atoms/ConnectingCheckPoints.stories.js b/webpack/react-components/src/atoms/ConnectingCheckPoints.stories.js new file mode 100644 index 00000000000..72a8513e99c --- /dev/null +++ b/webpack/react-components/src/atoms/ConnectingCheckPoints.stories.js @@ -0,0 +1,19 @@ +import React from "react"; + +import { CheckPoint } from "./ConnectingCheckPoints"; + +export default { + title: "Atom/CheckPoint", + component: CheckPoint, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + isCompleted: true, + key: 234234, + label: "First checkpoint", + info: "This is the first checkpoint", +}; diff --git a/webpack/react-components/src/atoms/CustomButton.js b/webpack/react-components/src/atoms/CustomButton.js new file mode 100644 index 00000000000..a1ba8a10b8f --- /dev/null +++ b/webpack/react-components/src/atoms/CustomButton.js @@ -0,0 +1,13 @@ +import React from "react"; + +const CustomButton = ({ text, onClick, selected }) => { + return ( + + + + ); +}; + +export default CustomButton; diff --git a/webpack/react-components/src/atoms/DatePicker.js b/webpack/react-components/src/atoms/DatePicker.js new file mode 100644 index 00000000000..6436ffed23b --- /dev/null +++ b/webpack/react-components/src/atoms/DatePicker.js @@ -0,0 +1,72 @@ +import React, { useState, useRef } from "react"; +import { CalendarIcon } from "../atoms/svgindex"; +import PropTypes from "prop-types"; + +const DatePicker = (props) => { + // const [date, setDate] = useState(() => props.initialDate || null); + const dateInp = useRef(); + + function defaultFormatFunc(date) { + if (date) { + const operationDate = typeof date === "string" ? new Date(date) : date; + const years = operationDate?.getFullYear(); + const month = operationDate?.getMonth() + 1; + const _date = operationDate?.getDate(); + return _date && month && years ? `${_date}/${month}/${years}` : ""; + } + return ""; + } + + const getDatePrint = () => props?.formattingFn?.(props?.date) || defaultFormatFunc(props?.date); + const selectDate = (e) => { + const date = e.target.value; + // setDate(date); + props?.onChange?.(date); + }; + let addStyle = {}; + if (Digit.UserService.getType() === "citizen") { + addStyle = { maxWidth: "540px" }; + } + return ( +
+ + {/* + */} + + +
+ ); +}; + +DatePicker.propTypes = { + disabled: PropTypes.bool, + date: PropTypes.any, + min: PropTypes.any, + max: PropTypes.any, + defaultValue: PropTypes.any, + onChange: PropTypes.func, +}; + +export default DatePicker; diff --git a/webpack/react-components/src/atoms/DateWrap.js b/webpack/react-components/src/atoms/DateWrap.js new file mode 100644 index 00000000000..9f0fbed244f --- /dev/null +++ b/webpack/react-components/src/atoms/DateWrap.js @@ -0,0 +1,25 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { Calender } from "./svgindex"; + +const DateWrap = (props) => { + return ( +
+ +

{props.date}

+
+ ); +}; + +DateWrap.propTypes = { + /** + * date + */ + date: PropTypes.any, +}; + +DateWrap.defaultProps = { + date: 0, +}; + +export default DateWrap; diff --git a/webpack/react-components/src/atoms/DateWrap.stories.js b/webpack/react-components/src/atoms/DateWrap.stories.js new file mode 100644 index 00000000000..230abdd47d5 --- /dev/null +++ b/webpack/react-components/src/atoms/DateWrap.stories.js @@ -0,0 +1,19 @@ +import React from "react"; + +import DateWrap from "./DateWrap"; + +export default { + title: "Atom/DateWrap", + component: DateWrap, + argTypes: { + date: { control: "date" }, + }, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + date: 1607498172995, +}; diff --git a/webpack/react-components/src/atoms/DescriptionText.js b/webpack/react-components/src/atoms/DescriptionText.js new file mode 100644 index 00000000000..bd4fa92d8c6 --- /dev/null +++ b/webpack/react-components/src/atoms/DescriptionText.js @@ -0,0 +1,23 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const DescriptionText = (props) => { + return ( +
+

{props.text}

+
+ ); +}; + +DescriptionText.propTypes = { + /** + * DescriptionText contents + */ + date: PropTypes.string, +}; + +DescriptionText.defaultProps = { + text: "", +}; + +export default DescriptionText; diff --git a/webpack/react-components/src/atoms/DescriptionText.stories.js b/webpack/react-components/src/atoms/DescriptionText.stories.js new file mode 100644 index 00000000000..7c996644594 --- /dev/null +++ b/webpack/react-components/src/atoms/DescriptionText.stories.js @@ -0,0 +1,16 @@ +import React from "react"; + +import DescriptionText from "./DescriptionText"; + +export default { + title: "Atom/DescriptionText", + component: DescriptionText, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + text: "This is the description", +}; diff --git a/webpack/react-components/src/atoms/DisplayPhotos.js b/webpack/react-components/src/atoms/DisplayPhotos.js new file mode 100644 index 00000000000..c08c85899d3 --- /dev/null +++ b/webpack/react-components/src/atoms/DisplayPhotos.js @@ -0,0 +1,43 @@ +import React from "react"; +import PropTypes from "prop-types"; +import {PDFSvg} from "./svgindex" + +const ImageOrPDFIcon = ({source, index, last=false, onClick}) => { + return Digit.Utils.getFileTypeFromFileStoreURL(source) === "pdf" ? + + : + issue thumbnail onClick(source, index)}> +} + +const DisplayPhotos = (props) => { + return ( +
+ {props.srcs.map((source, index) => { + return + })} +
+ ); +}; + +DisplayPhotos.propTypes = { + /** + * images + */ + srcs: PropTypes.array, + /** + * optional click handler + */ + onClick: PropTypes.func, +}; + +DisplayPhotos.defaultProps = { + srcs: [], +}; + +export default DisplayPhotos; diff --git a/webpack/react-components/src/atoms/DisplayPhotos.stories.js b/webpack/react-components/src/atoms/DisplayPhotos.stories.js new file mode 100644 index 00000000000..9946593f32d --- /dev/null +++ b/webpack/react-components/src/atoms/DisplayPhotos.stories.js @@ -0,0 +1,20 @@ +import React from "react"; + +import DisplayPhotos from "./DisplayPhotos"; + +export default { + title: "Atom/DisplayPhotos", + component: DisplayPhotos, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + srcs: [ + "https://randomwordgenerator.com/img/picture-generator/5ee6d1454b53b10ff3d8992cc12c30771037dbf85254794e722679d49445_640.jpg", + "https://randomwordgenerator.com/img/picture-generator/55e3d1404351ab14f1dc8460962e33791c3ad6e04e507440762a7cd49348cc_640.jpg", + "https://randomwordgenerator.com/img/picture-generator/57e0d1444250a414f1dc8460962e33791c3ad6e04e50744077297bd59445c2_640.jpg", + ], +}; diff --git a/webpack/react-components/src/atoms/Dropdown.js b/webpack/react-components/src/atoms/Dropdown.js new file mode 100644 index 00000000000..9dd0cac9e5e --- /dev/null +++ b/webpack/react-components/src/atoms/Dropdown.js @@ -0,0 +1,293 @@ +import PropTypes from "prop-types"; +import React, { useEffect, useRef, useState } from "react"; +import { ArrowDown, SearchIcon } from "./svgindex"; + +const TextField = (props) => { + const [value, setValue] = useState(props.selectedVal ? props.selectedVal : ""); + + useEffect(() => { + if (!props.keepNull) + if (props.selectedVal) + setValue(props.selectedVal) + else { setValue(""); props.setFilter("") } + else setValue(""); + }, [props.selectedVal, props.forceSet]); + + function inputChange(e) { + if (props.freeze) return; + + setValue(e.target.value); + props.setFilter(e.target.value); + } + + function broadcastToOpen() { + if (!props.disable) { + props.dropdownDisplay(true); + } + } + + function broadcastToClose() { + props.dropdownDisplay(false); + } + + /* Custom function to scroll and select in the dropdowns while using key up and down */ + const keyChange = (e) => { + if (e.key == "ArrowDown") { + props.setOptionIndex((state) => (state + 1 == props.addProps.length ? 0 : state + 1)); + if (props.addProps.currentIndex + 1 == props.addProps.length) { + e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(0, 0); + } else { + props?.addProps?.currentIndex > 2 && e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0, 45); + } + e.preventDefault(); + } else if (e.key == "ArrowUp") { + props.setOptionIndex((state) => (state !== 0 ? state - 1 : props.addProps.length - 1)); + if (props.addProps.currentIndex == 0) { + e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(100000, 100000); + } else { + props?.addProps?.currentIndex > 2 && e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0, -45); + } + e.preventDefault(); + } else if (e.key == "Enter") { + props.addProps.selectOption(props.addProps.currentIndex); + e.preventDefault(); + } + }; + + return ( + { + broadcastToClose(); + props?.onBlur?.(e); + if (props.selectedVal !== props.filterVal) { + setTimeout(() => { + props.setforceSet((val) => val + 1); + }, 1000); + } + }} + onKeyDown={keyChange} + readOnly={props.disable} + autoFocus={props.autoFocus} + placeholder={props.placeholder} + autoComplete={"off"} + style={props.style} + /> + ); +}; + +const translateDummy = (text) => { + return text; +}; + +const Dropdown = (props) => { + const user_type = Digit.SessionStorage.get("userType"); + const [dropdownStatus, setDropdownStatus] = useState(false); + const [selectedOption, setSelectedOption] = useState(props.selected ? props.selected : null); + const [filterVal, setFilterVal] = useState(""); + const [forceSet, setforceSet] = useState(0); + const [optionIndex, setOptionIndex] = useState(-1); + const optionRef = useRef(null); + const hasCustomSelector = props.customSelector ? true : false; + const t = props.t || translateDummy; + + useEffect(() => { + setSelectedOption(props.selected); + }, [props.selected]); + + function dropdownSwitch() { + if (!props.disable) { + var current = dropdownStatus; + if (!current) { + document.addEventListener("mousedown", handleClick, false); + } + setDropdownStatus(!current); + props?.onBlur?.(); + } + } + + function handleClick(e) { + if (!optionRef.current || !optionRef.current.contains(e.target)) { + document.removeEventListener("mousedown", handleClick, false); + setDropdownStatus(false); + } + } + + function dropdownOn(val) { + const waitForOptions = () => setTimeout(() => setDropdownStatus(val), 500); + const timerId = waitForOptions(); + return () => { + clearTimeout(timerId); + }; + } + + function onSelect(val) { + if (val !== selectedOption || props.allowMultiselect) { + props.select(val); + setSelectedOption(val); + setDropdownStatus(false); + } else { + setSelectedOption(val); + setforceSet(forceSet + 1); + } + } + + function setFilter(val) { + setFilterVal(val); + } + + let filteredOption = + (props.option && props.option?.filter((option) => t(option[props.optionKey])?.toUpperCase()?.indexOf(filterVal?.toUpperCase()) > -1)) || []; + function selectOption(ind) { + onSelect(filteredOption[ind]); + } + + if (props.isBPAREG && selectedOption) { + let isSelectedSameAsOptions = props.option?.filter((ob) => ob?.code === selectedOption?.code)?.length > 0; + if (!isSelectedSameAsOptions) setSelectedOption(null) + } + + return ( +
+ {hasCustomSelector && ( +
+ {props.customSelector} + {props.showArrow && } +
+ )} + {!hasCustomSelector && ( +
+ + {props.showSearchIcon ? null : } + {props.showSearchIcon ? : null} +
+ )} + {dropdownStatus ? ( + props.optionKey ? ( +
+ {filteredOption && + filteredOption.map((option, index) => { + return ( +
onSelect(option)} + > + {option.icon && {option.icon} } + {props.isPropertyAssess ?
{props.t ? props.t(option[props.optionKey]) : option[props.optionKey]}
: + {props.t ? props.t(option[props.optionKey]) : option[props.optionKey]}} +
+ ); + })} + {filteredOption && filteredOption.length === 0 && ( +
{ + + }}> + { {props.t ? props.t("CMN_NOOPTION") : "CMN_NOOPTION"}} +
+ )} +
+ ) : ( +
+ {props.option + ?.filter((option) => option?.toUpperCase().indexOf(filterVal?.toUpperCase()) > -1) + .map((option, index) => { + return ( +

onSelect(option)} + > + {option} +

+ ); + })} +
+ ) + ) : null} +
+ ); +}; + +Dropdown.propTypes = { + customSelector: PropTypes.any, + showArrow: PropTypes.bool, + selected: PropTypes.any, + style: PropTypes.object, + option: PropTypes.array, + optionKey: PropTypes.any, + select: PropTypes.any, + t: PropTypes.func, +}; + +Dropdown.defaultProps = { + customSelector: null, + showArrow: true, +}; + +export default Dropdown; diff --git a/webpack/react-components/src/atoms/Dropdown.stories.js b/webpack/react-components/src/atoms/Dropdown.stories.js new file mode 100644 index 00000000000..0898c7e44e2 --- /dev/null +++ b/webpack/react-components/src/atoms/Dropdown.stories.js @@ -0,0 +1,18 @@ +import React from "react"; + +import Dropdown from "./Dropdown"; + +export default { + title: "Atom/Dropdown", + component: Dropdown, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + selected: "first", + option: ["first", "second", "third"], + optionKey: 0, +}; diff --git a/webpack/react-components/src/atoms/EllipsisMenu.js b/webpack/react-components/src/atoms/EllipsisMenu.js new file mode 100644 index 00000000000..a26a49de1da --- /dev/null +++ b/webpack/react-components/src/atoms/EllipsisMenu.js @@ -0,0 +1,33 @@ +import React, { useRef, useState } from "react"; +import { Ellipsis } from "./svgindex"; + +const Menu = ({ menu, displayKey, onSelect }) => ( +
+ {menu.map((item, index) => ( +
onSelect(item)} key={index}> + {item.icon} + {item[displayKey]} +
+ ))} +
+); + +const EllipsisMenu = ({ menuItems, displayKey, onSelect }) => { + const menuRef = useRef(); + const [active, setActive] = useState(false); + Digit.Hooks.useClickOutside(menuRef, () => setActive(false), active); + + function onItemSelect(item) { + setActive(false); + onSelect(item); + } + + return ( +
+ setActive(true)} /> + {active ? : null} +
+ ); +}; + +export default EllipsisMenu; diff --git a/webpack/react-components/src/atoms/EmployeeAppContainer.js b/webpack/react-components/src/atoms/EmployeeAppContainer.js new file mode 100644 index 00000000000..3aaed46b4fc --- /dev/null +++ b/webpack/react-components/src/atoms/EmployeeAppContainer.js @@ -0,0 +1,7 @@ +import React from "react"; + +const EmployeeAppContainer = (props) => { + return
{props.children}
; +}; + +export default EmployeeAppContainer; diff --git a/webpack/react-components/src/atoms/EmployeeModuleCard.js b/webpack/react-components/src/atoms/EmployeeModuleCard.js new file mode 100644 index 00000000000..14b1c3b0dd9 --- /dev/null +++ b/webpack/react-components/src/atoms/EmployeeModuleCard.js @@ -0,0 +1,124 @@ + + +import { Button, LandingPageCard, } from "@egovernments/digit-ui-components"; +import React, { Fragment } from "react"; +import { ArrowRightInbox } from "./svgindex"; +import { useHistory, useLocation, Link } from "react-router-dom"; + + +/** + * EmployeeModuleCard - A New reusable card component to display module information with KPIs, links, and actions. + * + * @param {Object} props - Component props + * @param {React.Element|string} Icon - Icon to display, can be a React component or a string identifier + * @param {string} moduleName - Name of the module + * @param {Array} kpis - Array of KPI objects to display metrics + * @param {Array} links - Array of link objects for navigation + * @param {string} className - Additional CSS class for the card + * @param {Array} otherLinks - Array of additional links rendered as buttons + * @param {string} buttonSize - Size of the buttons in otherLinks, defaults to "medium" + */ +const EmployeeModuleCard = ({ + Icon, + moduleName, + kpis = [], + links = [], + className, + otherLinks = [], + buttonSize = "medium", +}) => { + // Hook for navigation + const history = useHistory(); + + /** + * Handles navigation when a link is clicked. + * Uses React Router's history for internal navigation and window.location for external links. + * @param {string} link - The link to navigate to + */ + const handleLinkClick = (link) => { + link?.includes(`${window?.contextPath}/`) + ? history?.push(link) // Internal navigation + : (window.location.href = link); // External navigation + }; + + // Configuration object for the LandingPageCard component + const propsForModuleCard = { + // Determines the icon to display. Defaults to "FactIcon" if not a string. + icon: typeof Icon === "string" ? Icon : "FactIcon", + + // Module name to display + moduleName: moduleName, + + // KPIs to display on the card + metrics: kpis, + + // Maps links to include a default icon ("ArrowForward") + links: links?.map((linkObject) => ({ icon: "ArrowForward", ...linkObject })), + + // Renders additional links as buttons in the center of the card + centreChildren: otherLinks?.filter(linkObj=>linkObj&&linkObj?.placement=="top")?.map((linkObj) => ( + + ))} + + + } +
+ {header && renderHeader()} +
checkKeyDown(e)}> +
+ {uiConfig?.showFormInstruction &&

{t(uiConfig?.showFormInstruction)}

} +
+ +
+ {uiConfig?.secondaryLabel && {t(uiConfig?.secondaryLabel)}} + {uiConfig?.isPopUp && uiConfig?.primaryLabel && { + handleSubmit(onSubmit)(e); + // onSubmit(formData, e) + }} disabled={false} />} + {!uiConfig?.isPopUp && uiConfig?.primaryLabel && } +
+
+
+
+ {showToast && + } +
+ + } + return ( + 0 ? navConfig : []} showNav={navConfig?.length > 0 ? true : false} activeLink={activeLink} setActiveLink={setActiveLink} fromSearchComp={true} horizontalLine={uiConfig?.horizontalLine}> +
+ {header && renderHeader()} +
checkKeyDown(e)}> +
+ {uiConfig?.showFormInstruction &&

{t(uiConfig?.showFormInstruction)}

} +
+ activeLink?.name === uiConf.uiConfig.navLink)?.[0]?.uiConfig?.fields : uiConfig?.fields} + control={control} + formData={formData} + errors={errors} + register={register} + setValue={setValue} + getValues={getValues} + setError={setError} + clearErrors={clearErrors} + labelStyle={{fontSize: "16px"}} + apiDetails={apiDetails} + data={data} + /> +
+ { uiConfig?.secondaryLabel && {t(uiConfig?.secondaryLabel)} } + {uiConfig?.isPopUp && uiConfig?.primaryLabel && { + handleSubmit(onSubmit)(e); + // onSubmit(formData, e) + }} disabled={false} />} + {!uiConfig?.isPopUp && uiConfig?.primaryLabel && } +
+
+
+
+ { showToast && + } +
+
+ ) +} + +export default SearchComponent diff --git a/webpack/react-components/src/atoms/SearchableDropdown.js b/webpack/react-components/src/atoms/SearchableDropdown.js new file mode 100644 index 00000000000..935a1647ab0 --- /dev/null +++ b/webpack/react-components/src/atoms/SearchableDropdown.js @@ -0,0 +1,312 @@ +import PropTypes from "prop-types"; +import React, { useEffect, useRef, useState } from "react"; +import { ArrowDown, SearchIcon } from "./svgindex"; + +const TextField = (props) => { + const {value,setValue} = props + + useEffect(() => { + if (!props.keepNull) + if (props.selectedVal) + setValue(props.selectedVal) + else { setValue(""); props.setFilter("") } + else setValue(""); + }, [props.selectedVal, props.forceSet]); + + function inputChange(e) { + if (props.freeze) return; + + setValue(e.target.value); + props.setFilter(e.target.value); + } + + function broadcastToOpen() { + if (!props.disable) { + props.dropdownDisplay(true); + } + } + + function broadcastToClose() { + props.dropdownDisplay(false); + } + + /* Custom function to scroll and select in the dropdowns while using key up and down */ + const keyChange = (e) => { + if (e.key == "ArrowDown") { + props.setOptionIndex((state) => (state + 1 == props.addProps.length ? 0 : state + 1)); + if (props.addProps.currentIndex + 1 == props.addProps.length) { + e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(0, 0); + } else { + props?.addProps?.currentIndex > 2 && e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0, 45); + } + e.preventDefault(); + } else if (e.key == "ArrowUp") { + props.setOptionIndex((state) => (state !== 0 ? state - 1 : props.addProps.length - 1)); + if (props.addProps.currentIndex == 0) { + e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(100000, 100000); + } else { + props?.addProps?.currentIndex > 2 && e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0, -45); + } + e.preventDefault(); + } else if (e.key == "Enter") { + props.addProps.selectOption(props.addProps.currentIndex); + } + }; + + return ( + { + broadcastToClose(); + props?.onBlur?.(e); + if (props.selectedVal !== props.filterVal) { + setTimeout(() => { + props.setforceSet((val) => val + 1); + }, 1000); + } + }} + onKeyDown={keyChange} + readOnly={props.disable} + autoFocus={props.autoFocus} + placeholder={props.placeholder} + autoComplete={"off"} + style={props.style} + /> + ); +}; + +const translateDummy = (text) => { + return text; +}; + +const Dropdown = (props) => { + + const {tableRow,setTableRow} = props; + + const user_type = Digit.SessionStorage.get("userType"); + const [dropdownStatus, setDropdownStatus] = useState(false); + const [selectedOption, setSelectedOption] = useState(props.selected ? props.selected : null); + const [filterVal, setFilterVal] = useState(""); + const [forceSet, setforceSet] = useState(0); + const [optionIndex, setOptionIndex] = useState(-1); + const optionRef = useRef(null); + const hasCustomSelector = props.customSelector ? true : false; + const t = props.t || translateDummy; + + useEffect(() => { + setSelectedOption(props.selected); + }, [props.selected]); + + function dropdownSwitch() { + if (!props.disable) { + var current = dropdownStatus; + if (!current) { + document.addEventListener("mousedown", handleClick, false); + } + setDropdownStatus(!current); + props?.onBlur?.(); + } + } + + function handleClick(e) { + if (!optionRef.current || !optionRef.current.contains(e.target)) { + document.removeEventListener("mousedown", handleClick, false); + setDropdownStatus(false); + } + } + + function dropdownOn(val) { + const waitForOptions = () => setTimeout(() => setDropdownStatus(val), 500); + const timerId = waitForOptions(); + return () => { + clearTimeout(timerId); + }; + } + + function onSelect(val) { + + if (val !== selectedOption || props.allowMultiselect) { + props.select(val); + setSelectedOption(val); + setDropdownStatus(false); + + //here update the tableState + setTableRow((prevState) => { + //just for static screen purposes + const newObj = { + "name": "Name New", + "aadhar": val, + "acno": "1212-1212-1212", + "ifsc": "1313-1313-1331" + } + return [...prevState,newObj] + }) + } else { + setSelectedOption(val); + setforceSet(forceSet + 1); + + + } + } + + function setFilter(val) { + setFilterVal(val); + } + + let filteredOption = + (props.option && props.option?.filter((option) => t(option[props.optionKey])?.toUpperCase()?.indexOf(filterVal?.toUpperCase()) > -1)) || []; + function selectOption(ind) { + onSelect(filteredOption[ind]); + } + + if (props.isBPAREG && selectedOption) { + let isSelectedSameAsOptions = props.option?.filter((ob) => ob?.code === selectedOption?.code)?.length > 0; + if (!isSelectedSameAsOptions) setSelectedOption(null) + } + + return ( +
+ {hasCustomSelector && ( +
+ {props.customSelector} + {props.showArrow && } +
+ )} + {!hasCustomSelector && ( +
+ + {props.showSearchIcon ? null : } + {props.showSearchIcon ? : null} +
+ )} + {dropdownStatus ? ( + props.optionKey ? ( +
+ {filteredOption && + filteredOption.map((option, index) => { + return ( +
onSelect(option)} + > + {option.icon && {option.icon} } + {props.isPropertyAssess ?
{props.t ? props.t(option[props.optionKey]) : option[props.optionKey]}
: + {props.t ? props.t(option[props.optionKey]) : option[props.optionKey]}} +
+ ); + })} + {filteredOption && filteredOption.length === 0 && ( +
{ + + }}> + { {props.t ? props.t("CMN_NOOPTION") : "CMN_NOOPTION"}} +
+ )} +
+ ) : ( +
+ {props.option + ?.filter((option) => option?.toUpperCase().indexOf(filterVal?.toUpperCase()) > -1) + .map((option, index) => { + return ( +

onSelect(option)} + > + {option} +

+ ); + })} +
+ ) + ) : null} +
+ ); +}; + +Dropdown.propTypes = { + customSelector: PropTypes.any, + showArrow: PropTypes.bool, + selected: PropTypes.any, + style: PropTypes.object, + option: PropTypes.array, + optionKey: PropTypes.any, + select: PropTypes.any, + t: PropTypes.func, +}; + +Dropdown.defaultProps = { + customSelector: null, + showArrow: true, +}; + +export default Dropdown; diff --git a/webpack/react-components/src/atoms/SectionalDropdown.js b/webpack/react-components/src/atoms/SectionalDropdown.js new file mode 100644 index 00000000000..726f8304dc9 --- /dev/null +++ b/webpack/react-components/src/atoms/SectionalDropdown.js @@ -0,0 +1,90 @@ +import React, { useEffect, useState } from "react"; +import { ArrowDown } from "./svgindex"; + +const TextField = (props) => { + const [value, setValue] = useState(props.selectedVal ? props.selectedVal : ""); + + useEffect(() => { + props.selectedVal ? setValue(props.selectedVal) : null; + }, [props.selectedVal]); + + function inputChange(e) { + setValue(e.target.value); + props.setFilter(e.target.value); + } + + return ; +}; + +const SectionalDropdown = (props) => { + const [dropdownStatus, setDropdownStatus] = useState(false); + const [selectedOption, setSelectedOption] = useState(props.selected ? props.selected : null); + const [filterVal, setFilterVal] = useState(""); + + useEffect(() => { + setSelectedOption(props.selected); + }, [props.selected]); + + function dropdownSwitch() { + var current = dropdownStatus; + setDropdownStatus(!current); + } + + function dropdownOn() { + setDropdownStatus(true); + } + + function onSelect(selectedOption) { + props.select(selectedOption); + setSelectedOption(selectedOption); + setDropdownStatus(false); + } + + function setFilter(val) { + setFilterVal(val); + } + + return ( +
+
+ + +
+ {dropdownStatus ? ( +
+ {props.menuData + .filter((subMenu) => subMenu.options.filter((option) => option[props.displayKey].toUpperCase().includes(filterVal.toUpperCase()))) + .map((subMenu, index) => { + return ( + +

{subMenu.heading}

+ {subMenu.options.map((option, index) => { + return ( +

onSelect(option)}> + {props.t ? props.t(option[props.displayKey]) : option[props.displayKey]} +

+ ); + })} +
+ ); + })} +
+ ) : null} +
+ ); +}; + +export default SectionalDropdown; diff --git a/webpack/react-components/src/atoms/StandaloneSearchBar.js b/webpack/react-components/src/atoms/StandaloneSearchBar.js new file mode 100644 index 00000000000..b4700aa1858 --- /dev/null +++ b/webpack/react-components/src/atoms/StandaloneSearchBar.js @@ -0,0 +1,10 @@ +import React from "react" +import { SearchIconSvg } from "./svgindex" +const StandaloneSearchBar = ({placeholder}) => { + return
+ + +
+} + +export default StandaloneSearchBar \ No newline at end of file diff --git a/webpack/react-components/src/atoms/StatusTable.js b/webpack/react-components/src/atoms/StatusTable.js new file mode 100644 index 00000000000..e83a23936e6 --- /dev/null +++ b/webpack/react-components/src/atoms/StatusTable.js @@ -0,0 +1,108 @@ +import React from "react"; +import { UnMaskComponent } from ".."; + +export const LastRow = (props) => { + return ( +
+

{props.label}

+

{props.text}

+
+ ); +}; + +export const Row = (props) => { + let value = props.text; + let valueStyle = props.textStyle || {}; + let labelStyle = props.labelStyle || {}; + if (Array.isArray(props.text)) { + value = props.text.map((val, index) => { + if (val?.className) { + return ( +

+ {val?.value} + {/* + Feature :: Privacy + privacy object set to the Mask Component + */} + {props?.privacy && ( + + + + )} +

+ ); + } + return ( +

+ {val} + {props?.privacy && ( + + {/* + Feature :: Privacy + privacy object set to the Mask Component + */} + + + )} +

+ ); + }); + } + // display: inline-flex; + // width: fit-content; + // margin-left: 10px; + // } + + return ( +
+

{props.label}{props?.isMandotary && '*'}

+
+ { + props?.isValueLink ? (

{value}

) :

{value}

+ } + {props?.privacy && ( + + + + )} + {props.caption &&
{props.caption}
} +
+ {props.actionButton ? ( +
+ {props.actionButton} +
+ ) : null} +
+ ); +}; + +export const MediaRow = (props) => { + return ( +
+

{props.label}

+ {props.children} +
+ ); +}; + +export const StatusTable = (props) => { + const employee = Digit.SessionStorage.get("user_type") === "employee" ? true : false; + if (props.dataObject) { + return ( +
+ {Object.keys(props.dataObject).map((name, index) => { + if (++index === Object.keys(props.dataObject).length) { + return ; + } + return ; + })} +
+ ); + } else { + return ( +
+ {props.children} +
+ ); + } +}; diff --git a/webpack/react-components/src/atoms/SubMenu.js b/webpack/react-components/src/atoms/SubMenu.js new file mode 100644 index 00000000000..d74ff7573fc --- /dev/null +++ b/webpack/react-components/src/atoms/SubMenu.js @@ -0,0 +1,105 @@ +import React, { useState } from "react"; +import { Link, useLocation } from "react-router-dom"; +import { + PTIcon, + OBPSIcon, + PropertyHouse, + CaseIcon, + PGRIcon, + FSMIcon, + WSICon, + MCollectIcon, + CollectionIcon, + HomeIcon, + ComplaintIcon, + PersonIcon, + DocumentIconSolid, + DropIcon, + CollectionsBookmarIcons, + FinanceChartIcon, +} from "./svgindex"; + +const IconsObject = { + CommonPTIcon: , + OBPSIcon: , + propertyIcon: , + TLIcon: , + PGRIcon: , + FSMIcon: , + WSIcon: , + MCollectIcon: , + BillsIcon: , + home: , + announcement: , + business: , + store: , + assignment: , + receipt: , + "business-center": , + description: , + "water-tap": , + "collections-bookmark": , + "insert-chart": , + edcr: , + collections: , +}; +const SubMenu = ({ item, t, isEmployee }) => { + const [subnav, setSubnav] = useState(false); + const location = useLocation(); + const { pathname } = location; + const showSubnav = () => setSubnav(!subnav); + + const leftIconCitizenArray = item.icon; + const leftIconCitizen = IconsObject[leftIconCitizenArray] || IconsObject.BillsIcon; + + const leftIconEmployeeItems = item?.icon?.split?.(":")?.[1] || ""; + + const leftIconEmployee = IconsObject[leftIconEmployeeItems] || IconsObject.collections; + + return ( + +
+
+
+ {isEmployee ? leftIconEmployee : leftIconCitizen} + {isEmployee ? item.moduleName : t(Digit.Utils.locale.getTransformedLocale(`ACTION_TEST_${item.moduleName}`))} +
+
{item.links && subnav}
+
+
+ + {subnav && + item.links + .sort((a, b) => a.orderNumber - b.orderNumber) + .map((item, index) => { + if (item.navigationURL.indexOf(`/${window?.contextPath}`) === -1) { + const getOrigin = window.location.origin; + return ( + +
+ {item.label || item.displayName} +
+
+ ); + } + return ( + +
+ {item.label || item.displayName} +
+ + ); + })} +
+ ); +}; + +export default SubMenu; diff --git a/webpack/react-components/src/atoms/SubmitBar.js b/webpack/react-components/src/atoms/SubmitBar.js new file mode 100644 index 00000000000..d553d5626a2 --- /dev/null +++ b/webpack/react-components/src/atoms/SubmitBar.js @@ -0,0 +1,46 @@ +import React, { forwardRef } from "react"; +import PropTypes from "prop-types"; + +const SubmitBar = forwardRef((props, ref) => { + return ( + + ); +}); + +SubmitBar.propTypes = { + /** + * Is it a normal button or submit button? + */ + submit: PropTypes.any, + /** + * style for the button + */ + style: PropTypes.object, + /** + * SubmitButton contents + */ + label: PropTypes.string, + /** + * Optional click handler + */ + onSubmit: PropTypes.func, + /** + * Submit icon + */ + submitIcon: PropTypes.node, +}; + +SubmitBar.defaultProps = {}; + +export default SubmitBar; diff --git a/webpack/react-components/src/atoms/SubmitBar.stories.js b/webpack/react-components/src/atoms/SubmitBar.stories.js new file mode 100644 index 00000000000..ef9f73c0a43 --- /dev/null +++ b/webpack/react-components/src/atoms/SubmitBar.stories.js @@ -0,0 +1,28 @@ +import React from "react"; + +import SubmitBar from "./SubmitBar"; + +export default { + title: "Atom/SubmitBar", + component: SubmitBar, +}; + +const Template = (args) => ; + +export const SubmitButton = Template.bind({}); + +SubmitButton.args = { + submit: true, + style: {}, + label: "Submit", + onSubmit: undefined, +}; + +export const NormalButton = Template.bind({}); + +NormalButton.args = { + submit: false, + style: {}, + label: "Click me", + onSubmit: undefined, +}; diff --git a/webpack/react-components/src/atoms/TLCaption.js b/webpack/react-components/src/atoms/TLCaption.js new file mode 100644 index 00000000000..e13fe31dff5 --- /dev/null +++ b/webpack/react-components/src/atoms/TLCaption.js @@ -0,0 +1,40 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import Reason from "./Reason"; +import TelePhone from "./TelePhone" +import DisplayPhotos from "./DisplayPhotos"; +import UnMaskComponent from "./UnMaskComponent"; + + + +const TLCaption = ({ data, OpenImage, privacy = {} }) => { + + const { t } = useTranslation(); + return ( +
+ {data.date &&

{data.date}

} +

{data.name}

+ {data.mobileNumber && + +

    

+ +
} + {data.source &&

{t("ES_APPLICATION_DETAILS_APPLICATION_CHANNEL_" + data.source.toUpperCase())}

} + {data.comment && } + {data.additionalComment && } + {data?.wfComment.length>0 ?
{data?.wfComment?.map(e => +
+

{t("WF_COMMON_COMMENTS")}

+

{e}

+
+ )}
: null} + + {data?.thumbnailsToShow?.thumbs?.length > 0 ?
+

{t("CS_COMMON_ATTACHMENTS")}

+ { OpenImage(src, index, data?.thumbnailsToShow) }} /> +
: null} +
+ ); +}; + +export default TLCaption; diff --git a/webpack/react-components/src/atoms/Table.js b/webpack/react-components/src/atoms/Table.js new file mode 100644 index 00000000000..c183efe44ac --- /dev/null +++ b/webpack/react-components/src/atoms/Table.js @@ -0,0 +1,281 @@ +import React, { useEffect, useState, useRef, forwardRef } from "react"; +import { useGlobalFilter, usePagination, useRowSelect, useSortBy, useTable } from "react-table"; +import { ArrowBack, ArrowForward, ArrowToFirst, ArrowToLast, SortDown, SortUp, DoubleTickIcon } from "./svgindex"; +import CheckBox from "./CheckBox"; +import ActionBar from "./ActionBar"; +import SubmitBar from "./SubmitBar"; +import Toast from "./Toast"; + +const noop = () => {}; + +const IndeterminateCheckbox = forwardRef( + ({ indeterminate, ...rest }, ref) => { + const defaultRef = useRef() + const resolvedRef = ref || defaultRef + + useEffect(() => { + resolvedRef.current.indeterminate = indeterminate + }, [resolvedRef, indeterminate]) + + return ( + + + + ) + } +) +const getNoColumnBorder=(noColumnBorder)=>noColumnBorder?({ + cellspacing:"0" ,cellpadding:"0" +}):null; +const Table = ({ + className = "table", + t, + data, + columns, + getCellProps, + currentPage = 0, + pageSizeLimit = 10, + disableSort = true, + autoSort = false, + initSortId = "", + onSearch = false, + manualPagination = true, + totalRecords, + onNextPage, + onPrevPage, + globalSearch, + onSort = noop, + onPageSizeChange, + onLastPage, + onFirstPage, + isPaginationRequired = true, + sortParams = [], + showAutoSerialNo = false, + customTableWrapperClassName = "", + styles = {}, + tableTopComponent, + tableRef, + isReportTable = false, + showCheckBox = false, + actionLabel = 'CS_COMMON_DOWNLOAD', + tableSelectionHandler = () => {}, + onClickRow= ()=>{}, + rowClassName = "", + noColumnBorder=false, + customPageSizesArray = null +}) => { + const { + getTableProps, + getTableBodyProps, + headerGroups, + rows, + prepareRow, + page, + canPreviousPage, + canNextPage, + pageOptions, + pageCount, + gotoPage, + nextPage, + previousPage, + setPageSize, + setGlobalFilter, + state: { pageIndex, pageSize, sortBy, globalFilter, selectedRowIds }, + } = useTable( + { + columns, + data, + initialState: { pageIndex: currentPage, pageSize: pageSizeLimit, sortBy: autoSort ? [{ id: initSortId, desc: false }] : sortParams }, + pageCount: totalRecords > 0 ? Math.ceil(totalRecords / pageSizeLimit) : -1, + manualPagination: manualPagination, + disableMultiSort: false, + disableSortBy: disableSort, + manualSortBy: autoSort ? false : true, + autoResetPage: false, + autoResetSortBy: false, + disableSortRemove: true, + disableGlobalFilter: onSearch === false ? true : false, + globalFilter: globalSearch || "text", + useControlledState: (state) => { + return React.useMemo(() => ({ + ...state, + pageIndex: manualPagination ? currentPage : state.pageIndex, + })); + }, + }, + useGlobalFilter, + useSortBy, + usePagination, + useRowSelect, + hooks => { + if(showCheckBox) { + hooks.visibleColumns.push(columns => [ + { + id: 'selection', + Header: ({ getToggleAllPageRowsSelectedProps }) => ( +
+ +
+ ), + Cell: ({ row }) => ( +
+ +
+ ), + }, + ...columns, + ]) + } + } + ); + let isTotalColSpanRendered = false; + const [toast, setToast] = useState({show : false, label : "", error : false}); + + useEffect(() => { + onSort(sortBy); + }, [onSort, sortBy]); + + + useEffect(() => setGlobalFilter(onSearch), [onSearch, setGlobalFilter,data]); + + const handleSelection = async () => { + const selectedRows = rows?.filter(ele => Object.keys(selectedRowIds)?.includes(ele?.id)) + const response = await tableSelectionHandler(selectedRows,t) + setToast({show: true, label: t(response?.label), error: !response?.isSuccess}) + } + + const handleToastClose = () => { + setToast({show : false, label : "", error : false}) + } + + useEffect(()=>{ + if(toast?.show) { + setTimeout(()=>{ + handleToastClose(); + },3000); + } + },[toast?.show]) + + //note -> adding data prop in dependency array to trigger filter whenever state of the table changes + //use case -> without this if we enter string to search and then click on it's attendence checkbox or skill selector for that matter then the global filtering resets and whole table is shown + return ( + + + {tableTopComponent ? tableTopComponent : null} + + + {headerGroups.map((headerGroup) => ( + + {showAutoSerialNo && ( + + )} + {headerGroup.headers.map((column) => ( + + ))} + + ))} + + + {page.map((row, i) => { + // rows.slice(0, 10).map((row, i) => { + prepareRow(row); + return ( + onClickRow(row)} className={rowClassName}> + {showAutoSerialNo && } + {row.cells.map((cell) => { + return ( + + ); + })} + + ); + })} + +
+ {showAutoSerialNo && typeof showAutoSerialNo == "string" ? t(showAutoSerialNo) : t("TB_SNO")} + + {column.render("Header")} + {column.isSorted ? column.isSortedDesc ? : : ""} +
{i + 1} + {cell.attachment_link ? ( + + {cell.render("Cell")} + + ) : ( + {cell.render("Cell")} + )} +
+
+ {isPaginationRequired && ( +
+ {`${t("CS_COMMON_ROWS_PER_PAGE")} :`} + + + + {pageIndex * pageSize + 1} + {"-"} + {manualPagination + ? (currentPage + 1) * pageSizeLimit > totalRecords + ? totalRecords + : (currentPage + 1) * pageSizeLimit + : pageIndex * pageSize + page?.length}{" "} + {/* {(pageIndex + 1) * pageSizeLimit > rows.length ? rows.length : (pageIndex + 1) * pageSizeLimit}{" "} */} + {totalRecords ? `of ${manualPagination ? totalRecords : rows.length}` : ""} + {" "} + + {/* to go to first and last page we need to do a manual pagination , it can be updated later*/} + {!manualPagination && pageIndex != 0 && gotoPage(0)} className={"cp"} />} + {canPreviousPage && manualPagination && onFirstPage && manualPagination && onFirstPage()} className={"cp"} />} + {canPreviousPage && (manualPagination ? onPrevPage() : previousPage())} className={"cp"} />} + {canNextPage && (manualPagination ? onNextPage() : nextPage())} className={"cp"} />} + {!manualPagination && pageIndex != pageCount - 1 && gotoPage(pageCount - 1)} className={"cp"} />} + {rows.length == pageSizeLimit && canNextPage && manualPagination && onLastPage && ( + manualPagination && onLastPage()} className={"cp"} /> + )} + {/* to go to first and last page we need to do a manual pagination , it can be updated later*/} +
+ )} + { Object.keys(selectedRowIds)?.length > 0 && ( + + + +

{`${Object.keys(selectedRowIds)?.length} ${t("COMMON_SELECTED")}`}

+
+ +
)} + {toast?.show && } +
+ ); +}; + +export default Table; \ No newline at end of file diff --git a/webpack/react-components/src/atoms/TelePhone.js b/webpack/react-components/src/atoms/TelePhone.js new file mode 100644 index 00000000000..3b7e1860b6b --- /dev/null +++ b/webpack/react-components/src/atoms/TelePhone.js @@ -0,0 +1,27 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { Phone } from "./svgindex"; + +const TelePhone = ({ mobile, text }) => ( + + {text} +
+ +
+
+); + +TelePhone.propTypes = { + mobile: PropTypes.any, + text: PropTypes.string, +}; + +TelePhone.defaultProps = { + mobile: "", + text: "", +}; + +export default TelePhone; diff --git a/webpack/react-components/src/atoms/TelePhone.stories.js b/webpack/react-components/src/atoms/TelePhone.stories.js new file mode 100644 index 00000000000..69764f33bac --- /dev/null +++ b/webpack/react-components/src/atoms/TelePhone.stories.js @@ -0,0 +1,16 @@ +import React from "react"; + +import TelePhone from "./TelePhone"; + +export default { + title: "Atom/TelePhone", + component: TelePhone, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + mobile: "9292929929", + text: "Joe Doe", +}; diff --git a/webpack/react-components/src/atoms/TextArea.js b/webpack/react-components/src/atoms/TextArea.js new file mode 100644 index 00000000000..957dbb0c40f --- /dev/null +++ b/webpack/react-components/src/atoms/TextArea.js @@ -0,0 +1,45 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const TextArea = (props) => { + const user_type = Digit.SessionStorage.get("userType"); + + return ( + + + {

{props.hintText}

} +
+ ); +}; + +TextArea.propTypes = { + userType: PropTypes.string, + name: PropTypes.string.isRequired, + ref: PropTypes.func, + value: PropTypes.string, + onChange: PropTypes.func, + id: PropTypes.string, +}; + +TextArea.defaultProps = { + ref: undefined, + onChange: undefined, +}; + +export default TextArea; diff --git a/webpack/react-components/src/atoms/TextArea.stories.js b/webpack/react-components/src/atoms/TextArea.stories.js new file mode 100644 index 00000000000..afe730836cd --- /dev/null +++ b/webpack/react-components/src/atoms/TextArea.stories.js @@ -0,0 +1,18 @@ +import React from "react"; + +import TextArea from "./TextArea"; + +export default { + title: "Atom/TextArea", + component: TextArea, +}; + +const Template = (args) => + + ); + }); + + return ( +
+ + {!childrenAtTheBottom && children} + {inputs} + {forcedError && !showErrorBelowChildren && {t(forcedError)}} + {childrenAtTheBottom && children} + {forcedError && showErrorBelowChildren && {t(forcedError)}} + +
+ ); +}; + +FormStep.propTypes = { + config: PropTypes.shape({}), + onSelect: PropTypes.func, + onSkip: PropTypes.func, + onAdd: PropTypes.func, + t: PropTypes.func, +}; + +FormStep.defaultProps = { + config: {}, + onSelect: undefined, + onSkip: undefined, + onAdd: undefined, + t: (value) => value, +}; + +export default FormStep; diff --git a/webpack/react-components/src/molecules/FormStep.stories.js b/webpack/react-components/src/molecules/FormStep.stories.js new file mode 100644 index 00000000000..33618f20523 --- /dev/null +++ b/webpack/react-components/src/molecules/FormStep.stories.js @@ -0,0 +1,18 @@ +import React from "react"; + +import FormStep from "./FormStep"; + +export default { + title: "Molecule/FormStep", + component: FormStep, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + config: { + inputs: [{ type: "text", name: "firstName", label: "First Name", error: "This field is required", validation: null }], + }, +}; diff --git a/webpack/react-components/src/molecules/InputCard.js b/webpack/react-components/src/molecules/InputCard.js new file mode 100644 index 00000000000..46002483135 --- /dev/null +++ b/webpack/react-components/src/molecules/InputCard.js @@ -0,0 +1,60 @@ +import React from "react"; +import PropTypes from "prop-types"; + +import Card from "../atoms/Card"; +import CardHeader from "../atoms/CardHeader"; +import CardText from "../atoms/CardText"; +import SubmitBar from "../atoms/SubmitBar"; +import LinkButton from "../atoms/LinkButton"; +import CardCaption from "../atoms/CardCaption"; +import TextInput from "../atoms/TextInput"; + +const InputCard = ({ + t, + children, + texts = {}, + submit = false, + inputs = [], + inputRef, + onNext, + onSkip, + isDisable, + onAdd, + isMultipleAllow = false, + cardStyle = {}, +}) => { + const isMobile = window.Digit.Utils.browser.isMobile(); + // TODO: inputs handle + return ( + + {texts.headerCaption && {t(texts.headerCaption)}} + {texts?.header && {t(texts.header)}} + {texts?.cardText && {t(texts.cardText)}} + {children} + {texts.submitBarLabel ? : null} + {texts.skipLabel ? {t(texts.skipLabel)} : null} + {texts.skipText ? : null} + {isMultipleAllow && texts.addMultipleText ? : null} + + ); +}; + +InputCard.propTypes = { + text: PropTypes.object, + submit: PropTypes.bool, + onNext: PropTypes.func, + onSkip: PropTypes.func, + onAdd: PropTypes.func, + t: PropTypes.func, +}; + +InputCard.defaultProps = { + texts: {}, + submit: false, + onNext: undefined, + onSkip: undefined, + onAdd: undefined, + t: (value) => value, +}; + +export default InputCard; diff --git a/webpack/react-components/src/molecules/InputCard.stories.js b/webpack/react-components/src/molecules/InputCard.stories.js new file mode 100644 index 00000000000..0b94f76fda2 --- /dev/null +++ b/webpack/react-components/src/molecules/InputCard.stories.js @@ -0,0 +1,22 @@ +import React from "react"; + +import InputCard from "./InputCard"; + +export default { + title: "Molecule/InputCard", + component: InputCard, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + texts: { + headerCaption: "Header Caption", + header: "Header", + cardText: "Card Text", + nextText: "Next", + skipText: "Skip", + }, +}; diff --git a/webpack/react-components/src/molecules/Localities.js b/webpack/react-components/src/molecules/Localities.js new file mode 100644 index 00000000000..68eb85aa176 --- /dev/null +++ b/webpack/react-components/src/molecules/Localities.js @@ -0,0 +1,29 @@ +import React from "react"; +import { Loader } from "../atoms/Loader"; +import Dropdown from "../atoms/Dropdown"; +import { useTranslation } from "react-i18next"; + +const Localities = ({ selectLocality, tenantId, boundaryType, keepNull, selected, optionCardStyles, style, disable, disableLoader, sortFn }) => { + const { t } = useTranslation(); + + const { data: tenantlocalties, isLoading } = Digit.Hooks.useBoundaryLocalities(tenantId, boundaryType, { enabled: !disable }, t); + if (isLoading && !disableLoader) { + return ; + } + + return ( + + ); + //

ABCD

+}; + +export default Localities; diff --git a/webpack/react-components/src/molecules/LocationDropdownWrapper.js b/webpack/react-components/src/molecules/LocationDropdownWrapper.js new file mode 100644 index 00000000000..585702856d9 --- /dev/null +++ b/webpack/react-components/src/molecules/LocationDropdownWrapper.js @@ -0,0 +1,97 @@ +import React,{Fragment,useState,useEffect} from 'react' +import MultiSelectDropdown from '../atoms/MultiSelectDropdown' +import Dropdown from '../atoms/Dropdown' +import { Loader } from '../atoms/Loader' +import { useTranslation } from 'react-i18next' +const LocationDropdownWrapper = ({populators,formData,props,inputRef,errors,setValue}) => { + //based on type (ward/locality) we will render dropdowns respectively + //here we will render two types of dropdown based on allowMultiSelect boolean + // for singleSelect render + + const [options,setOptions] = useState([]) + + const tenantId = Digit.ULBService.getCurrentTenantId() + const headerLocale = Digit.Utils.locale.getTransformedLocale(tenantId); + const { t } = useTranslation() + const { isLoading, data: wardsAndLocalities } = Digit.Hooks.useLocation( + tenantId, 'Ward', + { + select: (data) => { + + const wards = [] + const localities = {} + data?.TenantBoundary[0]?.boundary.forEach((item) => { + localities[item?.code] = item?.children.map(item => ({ code: item.code, name: item.name, i18nKey: `${headerLocale}_ADMIN_${item?.code}`, label: item?.label })) + wards.push({ code: item.code, name: item.name, i18nKey: `${headerLocale}_ADMIN_${item?.code}` }) + }); + + return { + wards, localities + } + } + }); + + + useEffect(() => { + if(wardsAndLocalities) { + if(populators.type==="ward"){ + setOptions(wardsAndLocalities?.wards) + } + else{ + //here you need to set the localities based on the selected ward + let locs = [] + const selectedWardsCodes = formData?.ward?.map(row=>row.code) + selectedWardsCodes?.forEach(code=>{ + locs=[...locs,...wardsAndLocalities?.localities?.[code]] + }) + setOptions(locs) + } + } + }, [wardsAndLocalities,formData?.ward]) + + + if(isLoading) return + + return ( + <> + {populators.allowMultiSelect &&
+ { + if(populators.type === "ward"){ + setValue('locality',[]) + } + props.onChange(e?.map(row => { return row?.[1] ? row[1] : null }).filter(e => e)) + }} + selected={props?.value} + defaultLabel={t(populators?.defaultText)} + defaultUnit={t(populators?.selectedText)} + config={populators} + /> +
} + {!populators.allowMultiSelect && + { + props.onChange([e], populators.name); + }} + selected={props.value?.[0] || populators.defaultValue} + defaultValue={props.value?.[0] || populators.defaultValue} + t={t} + errorStyle={errors?.[populators.name]} + optionCardStyles={populators?.optionsCustomStyle} + /> + } + + ) +} + +export default LocationDropdownWrapper \ No newline at end of file diff --git a/webpack/react-components/src/molecules/LocationSearchCard.js b/webpack/react-components/src/molecules/LocationSearchCard.js new file mode 100644 index 00000000000..a894348905d --- /dev/null +++ b/webpack/react-components/src/molecules/LocationSearchCard.js @@ -0,0 +1,107 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; + +import Card from "../atoms/Card"; +import CardHeader from "../atoms/CardHeader"; +import CardText from "../atoms/CardText"; +import CardLabelError from "../atoms/CardLabelError"; +import LocationSearch from "../atoms/LocationSearch"; +import SubmitBar from "../atoms/SubmitBar"; +import LinkButton from "../atoms/LinkButton"; + +const LocationSearchCard = ({ + header, + cardText, + nextText, + t, + skipAndContinueText, + forcedError, + skip, + onSave, + onChange, + position, + disabled, + cardBodyStyle = {}, + isPTDefault, + PTdefaultcoord, + isPlaceRequired, + handleRemove, + Webview=false, + isPopUp=false, +}) => { + let isDisabled = false || disabled; + const onLocationChange = (val, location) => { + isDisabled = val ? false : true; + onChange(val, location); + }; + + const onLocationChangewithPlace = (val, location, place) => { + isDisabled = val ? false : true; + onChange(val, location, place); + }; + + return ( + + {header} +
+ {isPopUp && + + + + + +
+ } + style={{width: "100px", display:"inline"}} + onClick={(e) => handleRemove()} + />} + + {/* Click and hold to drop the pin to complaint location. If you are not + able to pin the location you can skip the continue for next step. */} + {cardText} + + + + {forcedError && {t(forcedError)}} + + + {skip ? : null} +
+ ); +}; + +LocationSearchCard.propTypes = { + header: PropTypes.string, + cardText: PropTypes.string, + nextText: PropTypes.string, + skipAndContinueText: PropTypes.string, + skip: PropTypes.func, + onSave: PropTypes.func, + onChange: PropTypes.func, + position: PropTypes.any, + isPTDefault: PropTypes.any, + PTdefaultcoord: PropTypes.any, + isPlaceRequired: PropTypes.any, +}; + +LocationSearchCard.defaultProps = { + header: "", + cardText: "", + nextText: "", + skipAndContinueText: "", + skip: () => {}, + onSave: null, + onChange: () => {}, + position: undefined, + isPTDefault: false, + PTdefaultcoord: {}, + isPlaceRequired: false, + handleRemove: () => {}, + Webview:false, + isPopUp:false, +}; + +export default LocationSearchCard; diff --git a/webpack/react-components/src/molecules/LocationSearchCard.stories.js b/webpack/react-components/src/molecules/LocationSearchCard.stories.js new file mode 100644 index 00000000000..96517792e00 --- /dev/null +++ b/webpack/react-components/src/molecules/LocationSearchCard.stories.js @@ -0,0 +1,20 @@ +import React from "react"; + +import LocationSearchCard from "./LocationSearchCard"; + +export default { + title: "Molecule/LocationSearchCard", + component: LocationSearchCard, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args = { + header: "Header", + cardText: "Card Text", + nextText: "Next Text", + skipAndContinueText: "Skip", + skip: true, +}; diff --git a/webpack/react-components/src/molecules/MultiUploadWrapper.js b/webpack/react-components/src/molecules/MultiUploadWrapper.js new file mode 100644 index 00000000000..d0a4323de69 --- /dev/null +++ b/webpack/react-components/src/molecules/MultiUploadWrapper.js @@ -0,0 +1,144 @@ +import React, { useEffect, useReducer, useState } from "react" +import UploadFile from "../atoms/UploadFile" + +const displayError = ({ t, error, name }, customErrorMsg) => ( + +
{customErrorMsg ? t(customErrorMsg) : t(error)}
+
{customErrorMsg ? '' : `${t('ES_COMMON_DOC_FILENAME')} : ${name} ...`}
+
+) + +const fileValidationStatus = (file, regex, maxSize, t) => { + + const status = { valid: true, name: file?.name?.substring(0, 15), error: '' }; + if (!file) return; + + if (!regex.test(file.type) && (file.size / 1024 / 1024) > maxSize) { + status.valid = false; status.error = t(`NOT_SUPPORTED_FILE_TYPE_AND_FILE_SIZE_EXCEEDED_5MB`); + } + + if (!regex.test(file.type)) { + status.valid = false; status.error = t(`NOT_SUPPORTED_FILE_TYPE`); + } + + if ((file.size / 1024 / 1024) > maxSize) { + status.valid = false; status.error = t(`FILE_SIZE_EXCEEDED_5MB`); + } + + return status; +} +const checkIfAllValidFiles = (files, regex, maxSize, t, maxFilesAllowed, state) => { + if (!files.length || !regex || !maxSize) return [{}, false]; + + // added another condition files.length > 0 , for when user uploads files more than maxFilesAllowed in one go the + const uploadedFiles = state.length + 1 + if ( maxFilesAllowed && (uploadedFiles > maxFilesAllowed || files.length > maxFilesAllowed)) return [[{ valid: false, name: files[0]?.name?.substring(0, 15), error: t(`FILE_LIMIT_EXCEEDED`)}],true] + + // Adding a check for fileSize > maxSize + // const maxSizeInBytes = maxSize * 1000000 + // if(files?.some(file => file.size > maxSizeInBytes)){ + // return [[{ valid: false, name: "", error: t(`FILE_SIZE_EXCEEDED_5MB`) }], true] + // } + + const messages = []; + let isInValidGroup = false; + for (let file of files) { + const fileStatus = fileValidationStatus(file, regex, maxSize, t); + if (!fileStatus.valid) { + isInValidGroup = true; + } + messages.push(fileStatus); + } + + return [messages, isInValidGroup]; +} + +// can use react hook form to set validations @neeraj-egov +const MultiUploadWrapper = ({ t, module = "PGR", tenantId = Digit.ULBService.getStateId(), getFormState, requestSpecifcFileRemoval, extraStyleName = "", setuploadedstate = [], showHintBelow, hintText, allowedFileTypesRegex = /(.*?)(jpg|jpeg|webp|aif|png|image|pdf|msword|openxmlformats-officedocument|xls|xlsx|openxmlformats-officedocument|wordprocessingml|document|spreadsheetml|sheet|ms-excel)$/i, allowedMaxSizeInMB = 10, acceptFiles = "image/*, .jpg, .jpeg, .webp, .aif, .png, .image, .pdf, .msword, .openxmlformats-officedocument, .dxf, .xlsx, .xls, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", maxFilesAllowed, customClass="", customErrorMsg,containerStyles }) => { + const FILES_UPLOADED = "FILES_UPLOADED" + const TARGET_FILE_REMOVAL = "TARGET_FILE_REMOVAL" + + const [fileErrors, setFileErrors] = useState([]); + const [enableButton, setEnableButton] = useState(true) + + const uploadMultipleFiles = (state, payload) => { + const { files, fileStoreIds } = payload; + const filesData = Array.from(files) + const newUploads = filesData?.map((file, index) => [file.name, { file, fileStoreId: fileStoreIds[index] }]) + return [...state, ...newUploads] + } + + const removeFile = (state, payload) => { + const __indexOfItemToDelete = state.findIndex(e => e[1].fileStoreId.fileStoreId === payload.fileStoreId.fileStoreId) + const mutatedState = state.filter((e, index) => index !== __indexOfItemToDelete) + setFileErrors([]) + return [...mutatedState] + } + + const uploadReducer = (state, action) => { + switch (action.type) { + case FILES_UPLOADED: + return uploadMultipleFiles(state, action.payload) + case TARGET_FILE_REMOVAL: + return removeFile(state, action.payload) + default: + break; + } + } + + const [state, dispatch] = useReducer(uploadReducer, [...setuploadedstate]) + + const onUploadMultipleFiles = async (e) => { + setEnableButton(false) + setFileErrors([]) + const files = Array.from(e.target.files); + + if (!files.length) return; + const [validationMsg, error] = checkIfAllValidFiles(files, allowedFileTypesRegex, allowedMaxSizeInMB, t, maxFilesAllowed, state); + + if (!error) { + try { + const { data: { files: fileStoreIds } = {} } = await Digit.UploadServices.MultipleFilesStorage(module, e.target.files, tenantId) + setEnableButton(true) + return dispatch({ type: FILES_UPLOADED, payload: { files: e.target.files, fileStoreIds } }) + } catch (err) { + setEnableButton(true) + } + } else { + setFileErrors(validationMsg) + setEnableButton(true) + } + } + + useEffect(() => getFormState(state), [state]) + + useEffect(() => { + requestSpecifcFileRemoval ? dispatch({ type: TARGET_FILE_REMOVAL, payload: requestSpecifcFileRemoval }) : null + }, [requestSpecifcFileRemoval]) + + return ( +
+ onUploadMultipleFiles(e)} + removeTargetedFile={(fileDetailsData) => dispatch({ type: TARGET_FILE_REMOVAL, payload: fileDetailsData })} + uploadedFiles={state} + multiple={true} + showHintBelow={showHintBelow} + hintText={hintText} + extraStyleName={extraStyleName} + onDelete={() => { + setFileErrors([]) + }} + accept={acceptFiles} + customClass={customClass} + enableButton={enableButton} + /> + + {fileErrors.length ? fileErrors.map(({ valid, name, type, size, error }) => ( + valid ? null : displayError({ t, error, name }, customErrorMsg) + )) : null} + +
) +} + +export default MultiUploadWrapper \ No newline at end of file diff --git a/webpack/react-components/src/molecules/OnGroundEventCard.js b/webpack/react-components/src/molecules/OnGroundEventCard.js new file mode 100644 index 00000000000..317c79faac6 --- /dev/null +++ b/webpack/react-components/src/molecules/OnGroundEventCard.js @@ -0,0 +1,28 @@ +import React from "react" +import EventCalendarView from "../atoms/EventCalendarView" +import { MapMarker, Clock } from "../atoms/svgindex" + +const OnGroundEventCard = ({onClick = () => null, name, id, eventDetails, onGroundEventMonth="MAR", onGroundEventDate="12 - 16", onGroundEventName="To the moon", onGroundEventLocation="Moon", onGroundEventTimeRange="10:00 am - 1:00 pm", eventCategory, showEventCatergory }) => { + + const onEventCardClick = () => onClick(id) + + return
+ +
+

{name}

+ {!showEventCatergory ?
+ +

{eventDetails?.address}

+
: null} + {!showEventCatergory ?
+ +

{onGroundEventTimeRange}

+
: null} + {showEventCatergory ?
+

{eventCategory}

+
: null} +
+
+} + +export default OnGroundEventCard \ No newline at end of file diff --git a/webpack/react-components/src/molecules/PageBasedInput.js b/webpack/react-components/src/molecules/PageBasedInput.js new file mode 100644 index 00000000000..0615e05fa7d --- /dev/null +++ b/webpack/react-components/src/molecules/PageBasedInput.js @@ -0,0 +1,19 @@ +import React from "react"; +import Card from "../atoms/Card"; +import SubmitBar from "../atoms/SubmitBar"; + +const PageBasedInput = ({ children, texts, onSubmit }) => { + return ( +
+ + {children} + + +
+ +
+
+ ); +}; + +export default PageBasedInput; diff --git a/webpack/react-components/src/molecules/PitDimension.js b/webpack/react-components/src/molecules/PitDimension.js new file mode 100644 index 00000000000..733d555764c --- /dev/null +++ b/webpack/react-components/src/molecules/PitDimension.js @@ -0,0 +1,52 @@ +import React from "react"; +import TextInput from "../atoms/TextInput"; +import CardText from "../atoms/CardText"; + +const DimentionInput = ({ name, value, onChange, disable }) => ( + +); + +const PitDimension = ({ sanitationType, t, size = {}, handleChange, disable = false }) => { + return sanitationType?.dimension === "dd" ? ( +
+
+ + + {t("CS_FILE_PROPERTY_DIAMETER")} + +
+ x +
+ + + {t("CS_FILE_PROPERTY_HEIGHT")} + +
+
+ ) : ( +
+
+ + + {t("CS_FILE_PROPERTY_LENGTH")} + +
+ x +
+ + + {t("CS_FILE_PROPERTY_WIDTH")} + +
+ x +
+ + + {t("CS_FILE_PROPERTY_HEIGHT")} + +
+
+ ); +}; + +export default PitDimension; diff --git a/webpack/react-components/src/molecules/RadioOrSelect.js b/webpack/react-components/src/molecules/RadioOrSelect.js new file mode 100644 index 00000000000..75e201cc812 --- /dev/null +++ b/webpack/react-components/src/molecules/RadioOrSelect.js @@ -0,0 +1,55 @@ +import React from "react"; +import RadioButtons from "../atoms/RadioButtons"; +import Dropdown from "../atoms/Dropdown"; + +const RadioOrSelect = ({ + options, + onSelect, + optionKey, + selectedOption, + isMandatory, + t, + labelKey, + dropdownStyle = {}, + isDependent = false, + disabled = false, + optionCardStyles, + isPTFlow=false, + isDropDown = false, + innerStyles = {}, + inputStyle = {} +}) => { + return ( + + {options?.length < 5 && !isDropDown ? ( + + ) : ( + + )} + + ); +}; + +export default RadioOrSelect; diff --git a/webpack/react-components/src/molecules/RatingCard.js b/webpack/react-components/src/molecules/RatingCard.js new file mode 100644 index 00000000000..104a6339a52 --- /dev/null +++ b/webpack/react-components/src/molecules/RatingCard.js @@ -0,0 +1,108 @@ +import React, { useState } from "react"; +import { useForm } from "react-hook-form"; +import PropTypes from "prop-types"; + +import TextArea from "../atoms/TextArea"; +import CardLabel from "../atoms/CardLabel"; +import Rating from "../atoms/Rating"; +import CheckBox from "../atoms/CheckBox"; +import Card from "../atoms/Card"; +import CardHeader from "../atoms/CardHeader"; +import SubmitBar from "../atoms/SubmitBar"; +import RadioButtons from "../atoms/RadioButtons"; +import Dropdown from "../atoms/Dropdown"; + +const RatingCard = ({ config, onSelect, t }) => { + const { register, watch, handleSubmit } = useForm(); + const [comments, setComments] = useState(""); + const [rating, setRating] = useState(0); + + const onSubmit = (data) => { + data.rating = rating; + onSelect(data); + }; + + const feedback = (e, ref, index) => { + setRating(index); + }; + + const segments = config.inputs?.map((input, index) => { + if (input.type === "rate") { + return ( + + {t(input.label)} + {input?.error} + feedback(e, ref, i)} /> + + ); + } + + if (input.type === "checkbox") { + return ( + + {t(input.label)} + {input.checkLabels && + input.checkLabels.map((label, index) => )} + + ); + } + + if (input.type === "radio") { + return ( + + {t(input.label)} + + + ); + } + + if (input.type === "textarea") { + return ( + + {t(input.label)} + + + ); + } + + if (input.type === "dropDown") { + return ( + + {t(input.label)} + + + ); + } + }); + return ( +
+ + {t(config.texts.header)} + {segments} + + +
+ ); +}; + +RatingCard.propTypes = { + config: PropTypes.object, + onSubmit: PropTypes.func, + t: PropTypes.func, +}; + +RatingCard.defaultProps = { + config: {}, + onSubmit: undefined, + t: (value) => value, +}; + +export default RatingCard; diff --git a/webpack/react-components/src/molecules/RatingCard.stories.js b/webpack/react-components/src/molecules/RatingCard.stories.js new file mode 100644 index 00000000000..ee8a52c619e --- /dev/null +++ b/webpack/react-components/src/molecules/RatingCard.stories.js @@ -0,0 +1,37 @@ +import React from "react"; + +import RatingCard from "./RatingCard"; + +export default { + title: "Molecule/RatingCard", + component: RatingCard, +}; + +const Template = (args) => ; + +export const InputTypeRate = Template.bind({}); + +InputTypeRate.args = { + config: { + inputs: [{ type: "rate", label: "Label" }], + texts: { header: "Header", submitBarLabel: "Submit" }, + }, +}; + +export const InputTypeCheckbox = Template.bind({}); + +InputTypeCheckbox.args = { + config: { + inputs: [{ type: "checkbox", label: "Label", checkLabels: ["Check Label"] }], + texts: { header: "Header", submitBarLabel: "Submit" }, + }, +}; + +export const InputTypeTextArea = Template.bind({}); + +InputTypeTextArea.args = { + config: { + inputs: [{ type: "textarea", label: "Label", name: "name" }], + texts: { header: "Header", submitBarLabel: "Submit" }, + }, +}; diff --git a/webpack/react-components/src/molecules/RenderFormFields.js b/webpack/react-components/src/molecules/RenderFormFields.js new file mode 100644 index 00000000000..1cdec6afbf9 --- /dev/null +++ b/webpack/react-components/src/molecules/RenderFormFields.js @@ -0,0 +1,389 @@ +import React from 'react'; +import { useTranslation } from "react-i18next"; +import { Controller } from "react-hook-form"; +import CardLabelError from "../atoms/CardLabelError"; +import LabelFieldPair from '../atoms/LabelFieldPair'; +import CardLabel from "../atoms/CardLabel"; +import TextInput from "../atoms/TextInput"; +import TextArea from "../atoms/TextArea"; +import CustomDropdown from './CustomDropdown'; +import MobileNumber from '../atoms/MobileNumber'; +import DateRangeNew from './DateRangeNew'; +import MultiUploadWrapper from "./MultiUploadWrapper"; +import MultiSelectDropdown from '../atoms/MultiSelectDropdown'; +import LocationDropdownWrapper from './LocationDropdownWrapper'; +import WorkflowStatusFilter from './WorkflowStatusFilter'; +import ApiDropdown from './ApiDropdown'; +import ApiCheckboxes from './ApiCheckboxes'; +const RenderFormFields = ({data,...props}) => { + const { t } = useTranslation(); + const { fields, control, formData, errors, register, setValue, getValues, setError, clearErrors, apiDetails} = props + + const fieldSelector = (type, populators, isMandatory, disable = false, component, config) => { + const Component = typeof component === "string" ? Digit.ComponentRegistryService.getComponent(component) : component; + let customValidations = config?.additionalValidation ? Digit?.Customizations?.[apiDetails?.masterName]?.[apiDetails?.moduleName]?.additionalValidations(config?.additionalValidation?.type, formData, config?.additionalValidation?.keys) : null + const customRules = customValidations ? { validate: customValidations} : {} + switch (type) { + case "date": + case "text": + case "number": + case "password": + case "time": + return ( + ( + + )} + name={populators.name} + rules={{required: isMandatory, ...populators.validation, ...customRules }} + control={control} + /> + ); + + case "textarea": + return ( + ( +