diff --git a/micro-ui/web/.env b/micro-ui/web/.env index 3174de8ec10..b696bf04eba 100644 --- a/micro-ui/web/.env +++ b/micro-ui/web/.env @@ -8,4 +8,4 @@ REACT_APP_PROXY_API=https://unified-dev.digit.org REACT_APP_PROXY_ASSETS=https://unified-dev.digit.org REACT_APP_GLOBAL=https://s3.ap-south-1.amazonaws.com/egov-dev-assets/globalConfigsWorkbench.js NODE_TLS_REJECT_UNAUTHORIZED=0; -REACT_APP_PORT=8000 \ No newline at end of file +REACT_APP_PORT=8000 diff --git a/micro-ui/web/lerna.json b/micro-ui/web/lerna.json index 17c7a0f8604..e0472965252 100644 --- a/micro-ui/web/lerna.json +++ b/micro-ui/web/lerna.json @@ -5,6 +5,7 @@ "packages/core", "packages/common", "packages/workbench", + "packages/pgr", "packages/ui-core", "packages/app1" ], diff --git a/micro-ui/web/package.json b/micro-ui/web/package.json index a26212b0e20..2dd955ac0bd 100644 --- a/micro-ui/web/package.json +++ b/micro-ui/web/package.json @@ -18,9 +18,10 @@ "workspaces": [ "packages/core", "packages/workbench", - "packages/common", + "packages/pgr", "packages/ui-core", "packages/app1" + "packages/common" ], "scripts": { "build": "yarn lerna run build", @@ -30,12 +31,14 @@ "build:hrms": "cd packages/hrms && yarn build", "build:workbench": "cd packages/workbench && yarn build", "build:dss": "cd packages/dss && yarn build", + "build:pgr": "cd packages/pgr && yarn build", "start:core": "cd packages/core && yarn start", + "start:workbench": "cd packages/workbench && yarn start", + "start:pgr": "cd packages/pgr && yarn start" "start:common": "cd packages/common && yarn start", - "start:workbench": "cd packages/workbench && yarn start" }, "dependencies": { "dotenv": "^16.3.1", "yarn": "^1.22.21" } -} +} \ No newline at end of file diff --git a/micro-ui/web/packages/core/src/App.js b/micro-ui/web/packages/core/src/App.js index cb86c2bce2b..c1076cd6ce3 100644 --- a/micro-ui/web/packages/core/src/App.js +++ b/micro-ui/web/packages/core/src/App.js @@ -7,7 +7,7 @@ import useRouter from "./hooks/useRouter"; import { DigitUI } from "./Module"; import { initLibraries } from "@digit-ui/digit-ui-libraries-mfe"; import { QueryClient, QueryClientProvider } from "react-query"; -import registerRemotes from "./modules/registerRemotes" +import registerRemotes from "./modules/registerRemotes"; //import { initHRMSComponents } from "@digit-ui/digit-ui-module-hrms-mfe"; // const LandingLazy = lazy(() => import("./modules/Landing")); @@ -23,6 +23,7 @@ initLibraries().then(() => { initDigitUI(); }); +//registering remote apps const queryClient = new QueryClient({ defaultOptions: { queries: { @@ -44,10 +45,10 @@ registerRemotes(queryClient) const App = () => { const { login, history, isSignedIn$, logout } = useAuth(); const { navigate } = useRouter(); - const enabledModules=["PT","HRMS","Workbench","DSS","Measurement"] + const enabledModules = ["PT", "HRMS", "Workbench", "DSS", "Measurement", "PGR"]; const moduleReducers = (initData) => initData; - + const stateCode = window?.globalConfigs?.getConfig("STATE_LEVEL_TENANT_ID") || "pb"; @@ -67,7 +68,6 @@ const App = () => {
- }> {/* @@ -89,9 +89,9 @@ const App = () => { */} - { - - } + + {} +
@@ -99,21 +99,17 @@ const App = () => { ); }; - - const initDigitUI = () => { window.contextPath = window?.globalConfigs?.getConfig("CONTEXT_PATH") || "digit-ui"; - window.Digit.Customizations = { - - }; + window.Digit.Customizations = {}; window?.Digit.ComponentRegistryService.setupRegistry({ // PaymentModule, // ...paymentConfigs, // PaymentLinks, }); - // initHRMSComponents(); - const enabledModules=["PT"]; + // initHRMSComponents(); + const enabledModules = ["PT"]; const moduleReducers = (initData) => initData; @@ -123,7 +119,4 @@ const initDigitUI = () => { // return (); }; - - export default App; - diff --git a/micro-ui/web/packages/core/src/modules/registerRemotes.js b/micro-ui/web/packages/core/src/modules/registerRemotes.js index 5a3c83fbf29..e96c6b86163 100644 --- a/micro-ui/web/packages/core/src/modules/registerRemotes.js +++ b/micro-ui/web/packages/core/src/modules/registerRemotes.js @@ -15,7 +15,17 @@ export default (queryClient) => { queryClient, }, }); - + + registerApplication({ + name: "PGR", + app: () => import("pgr/PGRModule"), + activeWhen: "/workbench-ui/employee/pgr", + customProps: { + title: "PGR is running on host", + queryClient, + }, + }); + registerApplication({ name: "Common", app: () => import("common/CommonModule"), diff --git a/micro-ui/web/packages/core/webpack.dev.js b/micro-ui/web/packages/core/webpack.dev.js index 604e8a3a332..5fbc36cfd5f 100644 --- a/micro-ui/web/packages/core/webpack.dev.js +++ b/micro-ui/web/packages/core/webpack.dev.js @@ -44,6 +44,7 @@ module.exports = () => { // auth: "auth@http://localhost:8082/remoteEntry.js", // header: "header@http://localhost:8083/remoteEntry.js", // dashboard: "dashboard@http://localhost:8084/remoteEntry.js", + pgr: "pgr@https://localhost:8087/remoteEntry.js", // hrms: "hrms@https://localhost:8085/remoteEntry.js", workbench: "workbench@https://localhost:8086/remoteEntry.js", common:"common@https://localhost:8090/remoteEntry.js" diff --git a/micro-ui/web/packages/core/webpack.prod.js b/micro-ui/web/packages/core/webpack.prod.js index ae3ef4c63cb..ad7456ec973 100644 --- a/micro-ui/web/packages/core/webpack.prod.js +++ b/micro-ui/web/packages/core/webpack.prod.js @@ -19,6 +19,7 @@ module.exports = () => { // auth: `auth@${domain}/auth/remoteEntry.js`, // header: `header@${domain}/header/remoteEntry.js`, // dashboard: `dashboard@${domain}/dashboard/remoteEntry.js`, + pgr : `pgr@${domain}/pgr/remoteEntry.js`, // hrms: `hrms@${domain}/hrms/remoteEntry.js`, common: `common-ui@${domain}/common/remoteEntry.js`, workbench : `workbench_web@${domain}/workbench/remoteEntry.js`, diff --git a/micro-ui/web/packages/pgr/package.json b/micro-ui/web/packages/pgr/package.json new file mode 100644 index 00000000000..be4e93b9c2c --- /dev/null +++ b/micro-ui/web/packages/pgr/package.json @@ -0,0 +1,50 @@ +{ + "name": "@digit-ui/digit-ui-module-pgr-mfe", + "version": "1.0.6", + "description": "", + "main": "module.js", + "scripts": { + "predeploy": "yarn build", + "deploy": "gh-pages -d dist", + "start": "webpack serve --config webpack.dev.js", + "build": "webpack --config webpack.prod.js" + }, + "homepage": "http://design-egov.github.io/auth", + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@babel/core": "7.12.10", + "@babel/preset-react": "7.12.10", + "babel-loader": "8.2.2", + "gh-pages": "^5.0.0", + "html-webpack-plugin": "^5.5.0", + "babel-plugin-react-html-attrs": "^3.0.5", + "@babel/preset-env": "7.23.9" + }, + "dependencies": { + "single-spa-react": "^4.6.1", + "@digit-ui/digit-ui-libraries-mfe": "1.0.6", + "@digit-ui/digit-ui-module-core-base": "1.0.8", + "@egovernments/digit-ui-react-components": "1.4.107", + "@egovernments/digit-ui-svg-components": "0.0.8", + "@rjsf/core": "5.10.0", + "@rjsf/utils": "5.10.0", + "@rjsf/validator-ajv8": "5.10.0", + "react": "17.0.1", + "react-date-range": "1.4.0", + "react-dom": "17.0.1", + "react-hook-form": "6.15.8", + "react-i18next": "11.16.2", + "react-query": "3.6.1", + "react-router-dom": "5.2.0", + "react-select": "5.7.4", + "webpack": "^5.68.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.8.1", + "react-redux": "7.2.8", + "redux": "4.1.2", + "redux-thunk": "2.4.1", + "webpack-merge": "5.7.3" + } +} diff --git a/micro-ui/web/packages/pgr/public/index.html b/micro-ui/web/packages/pgr/public/index.html new file mode 100644 index 00000000000..ce70aaede68 --- /dev/null +++ b/micro-ui/web/packages/pgr/public/index.html @@ -0,0 +1,34 @@ + + + + + PGR Page + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/micro-ui/web/packages/pgr/src/EmployeeApp.js b/micro-ui/web/packages/pgr/src/EmployeeApp.js new file mode 100644 index 00000000000..f0747117c18 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/EmployeeApp.js @@ -0,0 +1,23 @@ +import React from "react"; +import { AppContainer, EmployeeAppContainer } from "@egovernments/digit-ui-react-components"; +import Complaint from "./pages/employee/index"; +import { Provider } from "react-redux"; +import getStore from "./redux/store"; +import { PGRReducers } from "./Module"; + +const App = () => { + const { isLoading, data: initData } = Digit.Hooks.useInitStore("pg", ["PT", "HRMS", "Workbench", "DSS", "Measurement", "PGR"]); + const moduleReducers = (initData) => ({ + pgr: PGRReducers(initData), + }); + + return ( + + + + + + ); +}; + +export default App; diff --git a/micro-ui/web/packages/pgr/src/Icons.js b/micro-ui/web/packages/pgr/src/Icons.js new file mode 100644 index 00000000000..c932e7ad466 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/Icons.js @@ -0,0 +1,8 @@ +import React from "react"; + +export const Close = () => ( + + + + +); diff --git a/micro-ui/web/packages/pgr/src/Module.js b/micro-ui/web/packages/pgr/src/Module.js new file mode 100644 index 00000000000..df775c3222a --- /dev/null +++ b/micro-ui/web/packages/pgr/src/Module.js @@ -0,0 +1,87 @@ +import React, { useEffect } from "react"; +import PGRCard from "./components/PGRCard"; + +import getRootReducer from "./redux/reducers"; +import CitizenApp from "./pages/citizen"; + +import EmployeeApp from "./EmployeeApp"; +import { ComplaintIcon, CitizenHomeCard, Loader } from "@egovernments/digit-ui-react-components"; +import { PGR_CITIZEN_CREATE_COMPLAINT } from "./constants/Citizen"; +import { useTranslation } from "react-i18next"; +import { LOCALE } from "./constants/Localization"; +import { ComplaintDetails } from "./pages/employee/ComplaintDetails"; +import { CreateComplaint as CreateComplaintEmp } from "./pages/employee/CreateComplaint"; +import Inbox from "./pages/employee/Inbox"; +import ResponseEmp from "./pages/employee/Response"; + +import { CreateComplaint as CreateComplaintCitizen } from "./pages/citizen/Create"; +import { ComplaintsList } from "./pages/citizen/ComplaintsList"; +import ComplaintDetailsPage from "./pages/citizen/ComplaintDetails"; +import SelectRating from "./pages/citizen/Rating/SelectRating"; +import ResponseCitizen from "./pages/citizen/Response"; +import InboxV2 from "./pages/employee/InboxV2"; + + +export const PGRReducers = getRootReducer; + +const PGRModule = ({ stateCode, userType, tenants }) => { + const moduleCode = "PGR"; + const language = Digit.StoreData.getCurrentLanguage(); + const { isLoading, data: store } = Digit.Services.useStore({ stateCode, moduleCode, language }); + + if (isLoading) { + return ; + } + + Digit.SessionStorage.set("PGR_TENANTS", tenants); + + if (userType === "citizen") { + return ; + } else { + return ; + } +}; + +const PGRLinks = ({ matchPath }) => { + const { t } = useTranslation(); + const [params, setParams, clearParams] = Digit.Hooks.useSessionStorage(PGR_CITIZEN_CREATE_COMPLAINT, {}); + + useEffect(() => { + clearParams(); + }, []); + + const links = [ + { + link: `${matchPath}/create-complaint/complaint-type`, + i18nKey: t("CS_COMMON_FILE_A_COMPLAINT"), + }, + { + link: `${matchPath}/complaints`, + i18nKey: t(LOCALE.MY_COMPLAINTS), + }, + ]; + + return ; +}; + +const componentsToRegister = { + PGRModule, + PGRLinks, + PGRCard, + PGRComplaintDetails : ComplaintDetails, + PGRCreateComplaintEmp : CreateComplaintEmp, + PGRInbox : Inbox, + PGRInboxV2 : InboxV2, + PGRResponseEmp : ResponseEmp, + PGRCreateComplaintCitizen : CreateComplaintCitizen, + PGRComplaintsList : ComplaintsList, + PGRComplaintDetailsPage : ComplaintDetailsPage, + PGRSelectRating : SelectRating, + PGRResponseCitzen : ResponseCitizen +}; + +export const initPGRComponents = () => { + Object.entries(componentsToRegister).forEach(([key, value]) => { + Digit.ComponentRegistryService.setComponent(key, value); + }); +}; diff --git a/micro-ui/web/packages/pgr/src/PGRWrapper.js b/micro-ui/web/packages/pgr/src/PGRWrapper.js new file mode 100644 index 00000000000..1c466976b89 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/PGRWrapper.js @@ -0,0 +1,20 @@ +import React from 'react'; +import { initPGRComponents } from './Module'; +import { QueryClientProvider } from 'react-query'; +import EmployeeApp from './EmployeeApp'; +import { Switch, useLocation, BrowserRouter as Router } from 'react-router-dom'; + +const App = ({ queryClient, title }) => { + initPGRComponents(); + //make way to do this job in container while registering remotes + + return ( + + + + + + ); +}; + +export default App; diff --git a/micro-ui/web/packages/pgr/src/SingleSpaEntry.js b/micro-ui/web/packages/pgr/src/SingleSpaEntry.js new file mode 100644 index 00000000000..194c089d506 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/SingleSpaEntry.js @@ -0,0 +1,26 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import singleSpaReact from "single-spa-react"; +import App from "./PGRWrapper"; + +const appLifeCycles = singleSpaReact({ + React, + ReactDOM, + rootComponent: App, + errorBoundary() { + // https://reactjs.org/docs/error-boundaries.html + return
This renders when a catastrophic error occurs
; + }, +}); + +export function bootstrap(props) { + return appLifeCycles.bootstrap(props); +} + +export function mount(props) { + return appLifeCycles.mount(props); +} + +export function unmount(props) { + return appLifeCycles.unmount(props); +} \ No newline at end of file diff --git a/micro-ui/web/packages/pgr/src/components/Complaint.js b/micro-ui/web/packages/pgr/src/components/Complaint.js new file mode 100644 index 00000000000..3583fa17aad --- /dev/null +++ b/micro-ui/web/packages/pgr/src/components/Complaint.js @@ -0,0 +1,41 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { useHistory } from "react-router-dom"; +import { Card, DateWrap, KeyNote } from "@egovernments/digit-ui-react-components"; +import { CardSubHeader } from "@egovernments/digit-ui-react-components"; +import { LOCALIZATION_KEY } from "../constants/Localization"; + +// import { ConvertTimestampToDate } from "../@egovernments/digit-utils/services/date"; + +const Complaint = ({ data, path }) => { + let { serviceCode, serviceRequestId, applicationStatus } = data; + + const history = useHistory(); + const { t } = useTranslation(); + + const handleClick = () => { + history.push(`${path}/${serviceRequestId}`); + }; + + const closedStatus = ["RESOLVED", "REJECTED", "CLOSEDAFTERREJECTION", "CLOSEDAFTERRESOLUTION"]; + + return ( + + + {t(`SERVICEDEFS.${serviceCode.toUpperCase()}`)} + + + + + +
+

{(closedStatus.includes(applicationStatus) ? t("CS_COMMON_CLOSED") : t("CS_COMMON_OPEN")).toUpperCase()}

+
+ + {t(`${LOCALIZATION_KEY.CS_COMMON}_${applicationStatus}`)} +
+
+ ); +}; + +export default Complaint; diff --git a/micro-ui/web/packages/pgr/src/components/DesktopInbox.js b/micro-ui/web/packages/pgr/src/components/DesktopInbox.js new file mode 100644 index 00000000000..a81aba6a4c8 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/components/DesktopInbox.js @@ -0,0 +1,143 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; +import { Card, Loader } from "@egovernments/digit-ui-react-components"; +import ComplaintsLink from "./inbox/ComplaintLinks"; +import ComplaintTable from "./inbox/ComplaintTable"; +import Filter from "./inbox/Filter"; +import SearchComplaint from "./inbox/search"; +import { LOCALE } from "../constants/Localization"; + +const DesktopInbox = ({ + data, + onFilterChange, + onSearch, + isLoading, + searchParams, + onNextPage, + onPrevPage, + currentPage, + pageSizeLimit, + onPageSizeChange, + totalRecords, +}) => { + const { t } = useTranslation(); + const GetCell = (value) => {value}; + const GetSlaCell = (value) => { + return value < 0 ? {value || ""} : {value || ""}; + }; + + const columns = React.useMemo( + () => [ + { + Header: t("CS_COMMON_COMPLAINT_NO"), + Cell: ({ row }) => { + return ( +
+ + {row.original["serviceRequestId"]} + + {/* goTo(row.row.original["serviceRequestId"])}>{row.row.original["serviceRequestId"]} */} +
+ {t(`SERVICEDEFS.${row.original["complaintSubType"].toUpperCase()}`)} +
+ ); + }, + }, + { + Header: t("WF_INBOX_HEADER_LOCALITY"), + Cell: ({ row }) => { + return GetCell(t(Digit.Utils.locale.getLocalityCode(row.original["locality"], row.original["tenantId"]))); + }, + }, + { + Header: t("CS_COMPLAINT_DETAILS_CURRENT_STATUS"), + Cell: ({ row }) => { + return GetCell(t(`CS_COMMON_${row.original["status"]}`)); + }, + }, + { + Header: t("WF_INBOX_HEADER_CURRENT_OWNER"), + Cell: ({ row }) => { + return GetCell(row.original["taskOwner"]); + }, + }, + { + Header: t("WF_INBOX_HEADER_SLA_DAYS_REMAINING"), + Cell: ({ row }) => { + return GetSlaCell(row.original["sla"]); + }, + }, + ], + [t] + ); + + let result; + if (isLoading) { + result = ; + } else if (data && data.length === 0) { + result = ( + + {t(LOCALE.NO_COMPLAINTS_EMPLOYEE) + .split("\\n") + .map((text, index) => ( +

+ {text} +

+ ))} +
+ ); + } else if (data.length > 0) { + result = ( + { + return { + style: { + minWidth: cellInfo.column.Header === t("CS_COMMON_COMPLAINT_NO") ? "240px" : "", + padding: "20px 18px", + fontSize: "16px", + }, + }; + }} + onNextPage={onNextPage} + onPrevPage={onPrevPage} + totalRecords={totalRecords} + onPageSizeChagne={onPageSizeChange} + currentPage={currentPage} + pageSizeLimit={pageSizeLimit} + /> + ); + } else { + result = ( + + {t(LOCALE.ERROR_LOADING_RESULTS) + .split("\\n") + .map((text, index) => ( +

+ {text} +

+ ))} +
+ ); + } + + return ( +
+
+ +
+ +
+
+
+ +
{result}
+
+
+ ); +}; + +export default DesktopInbox; diff --git a/micro-ui/web/packages/pgr/src/components/FormComposer.js b/micro-ui/web/packages/pgr/src/components/FormComposer.js new file mode 100644 index 00000000000..785f9cde039 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/components/FormComposer.js @@ -0,0 +1,86 @@ +import React, { useMemo } from "react"; +import { useForm } from "react-hook-form"; +import { + BreakLine, + Card, + CardLabel, + CardLabelError, + CardSubHeader, + CardSectionHeader, + TextArea, + TextInput, + ActionBar, + SubmitBar, + LabelFieldPair, +} from "@egovernments/digit-ui-react-components"; + +import { useTranslation } from "react-i18next"; + +export const FormComposer = (props) => { + const { register, handleSubmit, errors } = useForm(); + const { t } = useTranslation(); + + function onSubmit(data) { + props.onSubmit(data); + } + + const fieldSelector = (type, populators) => { + switch (type) { + case "text": + return ( +
+ {populators.componentInFront ? populators.componentInFront : null} + +
+ ); + case "textarea": + return + + + + + ); +}; + +export default RatingAndFeedBack; diff --git a/micro-ui/web/packages/pgr/src/pages/citizen/Rating/SelectRating.js b/micro-ui/web/packages/pgr/src/pages/citizen/Rating/SelectRating.js new file mode 100644 index 00000000000..c24bce32f20 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/citizen/Rating/SelectRating.js @@ -0,0 +1,62 @@ +import React, { useCallback, useState } from "react"; +import { useDispatch } from "react-redux"; +import { RatingCard, CardLabelError } from "@egovernments/digit-ui-react-components"; +import { useParams, Redirect, useHistory } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import { updateComplaints } from "../../../redux/actions/index"; + +const SelectRating = ({ parentRoute }) => { + const { t } = useTranslation(); + const { id } = useParams(); + const dispatch = useDispatch(); + const history = useHistory(); + + let tenantId = Digit.SessionStorage.get("CITIZEN.COMMON.HOME.CITY")?.code || Digit.ULBService.getCurrentTenantId(); + const complaintDetails = Digit.Hooks.pgr.useComplaintDetails({ tenantId: tenantId, id: id }).complaintDetails; + const updateComplaint = useCallback((complaintDetails) => dispatch(updateComplaints(complaintDetails)), [dispatch]); + const [submitError, setError] = useState(false) + + function log(data) { + if (complaintDetails && data.rating > 0 ) { + complaintDetails.service.rating = data.rating; + complaintDetails.service.additionalDetail = data.CS_FEEDBACK_WHAT_WAS_GOOD.join(","); + complaintDetails.workflow = { + action: "RATE", + comments: data.comments, + verificationDocuments: [], + }; + updateComplaint({ service: complaintDetails.service, workflow: complaintDetails.workflow }); + history.push(`${parentRoute}/response`); + } + else{ + setError(true) + } + } + + const config = { + texts: { + header: "CS_COMPLAINT_RATE_HELP_TEXT", + submitBarLabel: "CS_COMMONS_NEXT", + }, + inputs: [ + { + type: "rate", + maxRating: 5, + label: t("CS_COMPLAINT_RATE_TEXT"), + error: submitError ? {t("CS_FEEDBACK_ENTER_RATING_ERROR")} : null + }, + { + type: "checkbox", + label: "CS_FEEDBACK_WHAT_WAS_GOOD", + checkLabels: [t("CS_FEEDBACK_SERVICES"), t("CS_FEEDBACK_RESOLUTION_TIME"), t("CS_FEEDBACK_QUALITY_OF_WORK"), t("CS_FEEDBACK_OTHERS")], + }, + { + type: "textarea", + label: t("CS_COMMON_COMMENTS"), + name: "comments", + }, + ], + }; + return ; +}; +export default SelectRating; diff --git a/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/AddtionalDetails.js b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/AddtionalDetails.js new file mode 100644 index 00000000000..7c9ae3f20ac --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/AddtionalDetails.js @@ -0,0 +1,97 @@ +import React, { useCallback, useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { useDispatch, useSelector } from "react-redux"; +import { useParams, useHistory, Redirect } from "react-router-dom"; + +import { BackButton, Card, CardHeader, CardText, TextArea, SubmitBar } from "@egovernments/digit-ui-react-components"; + +import { updateComplaints } from "../../../redux/actions/index"; +import { LOCALIZATION_KEY } from "../../../constants/Localization"; + +const AddtionalDetails = (props) => { + // const [details, setDetails] = useState(null); + const history = useHistory(); + let { id } = useParams(); + const dispatch = useDispatch(); + const appState = useSelector((state) => state)["common"]; + let { t } = useTranslation(); + + const {complaintDetails} = props + useEffect(() => { + if (appState.complaints) { + const { response } = appState.complaints; + if (response && response.responseInfo.status === "successful") { + history.push(`${props.match.path}/response/:${id}`); + } + } + }, [appState.complaints, props.history]); + + const updateComplaint = useCallback( + async (complaintDetails) => { + await dispatch(updateComplaints(complaintDetails)); + history.push(`${props.match.path}/response/${id}`); + }, + [dispatch] + ); + + const getUpdatedWorkflow = (reopenDetails, type) => { + switch (type) { + case "REOPEN": + return { + action: "REOPEN", + comments: reopenDetails.addtionalDetail, + assignes: [], + verificationDocuments: reopenDetails.verificationDocuments, + }; + default: + return ""; + } + }; + + function reopenComplaint() { + let reopenDetails = Digit.SessionStorage.get(`reopen.${id}`); + if (complaintDetails) { + complaintDetails.workflow = getUpdatedWorkflow( + reopenDetails, + // complaintDetails, + "REOPEN" + ); + complaintDetails.service.additionalDetail = { + REOPEN_REASON: reopenDetails.reason, + }; + updateComplaint({ service: complaintDetails.service, workflow: complaintDetails.workflow }); + } + return ( + + ); + } + + function textInput(e) { + // setDetails(e.target.value); + let reopenDetails = Digit.SessionStorage.get(`reopen.${id}`); + Digit.SessionStorage.set(`reopen.${id}`, { + ...reopenDetails, + addtionalDetail: e.target.value, + }); + } + + return ( + + + {t(`${LOCALIZATION_KEY.CS_ADDCOMPLAINT}_PROVIDE_ADDITIONAL_DETAILS`)} + {t(`${LOCALIZATION_KEY.CS_ADDCOMPLAINT}_ADDITIONAL_DETAILS_TEXT`)} + +
+ +
+
+
+ ); +}; + +export default AddtionalDetails; diff --git a/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/Reason.js b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/Reason.js new file mode 100644 index 00000000000..a67b9b52c1c --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/Reason.js @@ -0,0 +1,57 @@ +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Link, useHistory, useParams } from "react-router-dom"; +import { BackButton, Card, CardHeader, CardLabelError, CardText, RadioButtons, SubmitBar } from "@egovernments/digit-ui-react-components"; + +import { LOCALIZATION_KEY } from "../../../constants/Localization"; +import { getRoute, PgrRoutes, PGR_BASE } from "../../../constants/Routes"; + +const ReasonPage = (props) => { + const history = useHistory(); + const { t } = useTranslation(); + const { id } = useParams(); + const [selected, setSelected] = useState(null); + const [valid, setValid] = useState(true); + + const onRadioChange = (value) => { + let reopenDetails = Digit.SessionStorage.get(`reopen.${id}`); + Digit.SessionStorage.set(`reopen.${id}`, { ...reopenDetails, reason: value }); + setSelected(value); + }; + + function onSave() { + if (selected === null) { + setValid(false); + } else { + history.push(`${props.match.path}/upload-photo/${id}`); + } + } + + return ( + + {t(`${LOCALIZATION_KEY.CS_REOPEN}_COMPLAINT`)} + + {/* Select the option related to your complaint from the list given below. + If the complaint type you are looking for is not listed select others.{" "} */} + {/* {t(`${TRANSLATION_KEY}_OPTION_ONE`)} */} + + {valid ? null : {t(`${LOCALIZATION_KEY.CS_ADDCOMPLAINT}_ERROR_REOPEN_REASON`)}} + setSelected(value)} + options={[ + t(`${LOCALIZATION_KEY.CS_REOPEN}_OPTION_ONE`), + t(`${LOCALIZATION_KEY.CS_REOPEN}_OPTION_TWO`), + t(`${LOCALIZATION_KEY.CS_REOPEN}_OPTION_THREE`), + t(`${LOCALIZATION_KEY.CS_REOPEN}_OPTION_FOUR`), + ]} + /> + + + + ); +}; + +export default ReasonPage; diff --git a/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/UploadPhoto.js b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/UploadPhoto.js new file mode 100644 index 00000000000..a50ae8af67f --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/UploadPhoto.js @@ -0,0 +1,71 @@ +import React, { useEffect, useState } from "react"; +import { Link, useHistory, useParams } from "react-router-dom"; +import { useTranslation } from "react-i18next"; + +import { Card, SubmitBar, BackButton, ImageUploadHandler, CardLabelError, LinkButton } from "@egovernments/digit-ui-react-components"; + +import { LOCALIZATION_KEY } from "../../../constants/Localization"; + +const UploadPhoto = (props) => { + const { t } = useTranslation(); + const history = useHistory(); + let { id } = useParams(); + const [verificationDocuments, setVerificationDocuments] = useState(null); + const [valid, setValid] = useState(true); + + const handleUpload = (ids) => { + setDocState(ids); + }; + + const setDocState = (ids) => { + if (ids?.length) { + const documents = ids.map((id) => ({ + documentType: "PHOTO", + fileStoreId: id, + documentUid: "", + additionalDetails: {}, + })); + setVerificationDocuments(documents); + } + }; + + function save() { + if (verificationDocuments === null) { + setValid(false); + } else { + history.push(`${props.match.path}/addional-details/${id}`); + } + } + + function skip() { + history.push(`${props.match.path}/addional-details/${id}`); + } + + useEffect(() => { + let reopenDetails = Digit.SessionStorage.get(`reopen.${id}`); + Digit.SessionStorage.set(`reopen.${id}`, { ...reopenDetails, verificationDocuments }); + }, [verificationDocuments, id]); + + return ( + + + + {/* + + */} + + {valid ? null : {t(`${LOCALIZATION_KEY.CS_ADDCOMPLAINT}_UPLOAD_ERROR_MESSAGE`)}} + + {props.skip ? : null} + + + ); +}; + +export default UploadPhoto; diff --git a/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/index.js b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/index.js new file mode 100644 index 00000000000..ddd9dab9acd --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/citizen/ReopenComplaint/index.js @@ -0,0 +1,28 @@ +import React, { useMemo } from "react"; + +import { Route, Switch, useRouteMatch } from "react-router-dom"; +// import UserOnboarding from "../UserOnboarding/index"; +import { PgrRoutes, getRoute } from "../../../constants/Routes"; +import ReasonPage from "./Reason"; +import UploadPhoto from "./UploadPhoto"; +import AddtionalDetails from "./AddtionalDetails"; +import Response from "../Response"; + +const ReopenComplaint = ({ match, history, parentRoute }) => { + + const allParams = window.location.pathname.split("/") + const id = allParams[allParams.length - 1] + const tenantId = Digit.SessionStorage.get("CITIZEN.COMMON.HOME.CITY")?.code || Digit.ULBService.getCurrentTenantId(); + + const complaintDetails = Digit.Hooks.pgr.useComplaintDetails({ tenantId: tenantId, id: id }).complaintDetails; + return ( + + } /> + } /> + } /> + } /> + + ); +}; + +export { ReopenComplaint }; diff --git a/micro-ui/web/packages/pgr/src/pages/citizen/Response.js b/micro-ui/web/packages/pgr/src/pages/citizen/Response.js new file mode 100644 index 00000000000..28b77b73e40 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/citizen/Response.js @@ -0,0 +1,59 @@ +import React from "react"; +import { Card, Banner, CardText, SubmitBar } from "@egovernments/digit-ui-react-components"; +import { Link } from "react-router-dom"; +import { useSelector } from "react-redux"; +import { PgrRoutes, getRoute } from "../../constants/Routes"; +import { useTranslation } from "react-i18next"; + +const GetActionMessage = ({ action }) => { + const { t } = useTranslation(); + switch (action) { + case "REOPEN": + return t(`CS_COMMON_COMPLAINT_REOPENED`); + case "RATE": + return t("CS_COMMON_THANK_YOU"); + default: + return t(`CS_COMMON_COMPLAINT_SUBMITTED`); + } +}; + +const BannerPicker = ({ response }) => { + const { complaints } = response; + const { t } = useTranslation(); + if (complaints && complaints.response && complaints.response.responseInfo) { + return ( + + ); + } else { + return ; + } +}; + +const TextPicker = ({ response }) => { + const { complaints } = response; + const { t } = useTranslation(); + if (complaints && complaints.response && complaints.response.responseInfo) { + const { action } = complaints.response.ServiceWrappers[0].workflow; + return action === "RATE" ? {t("CS_COMMON_RATING_SUBMIT_TEXT")} : {t("CS_COMMON_TRACK_COMPLAINT_TEXT")}; + } +}; + +const Response = (props) => { + const { t } = useTranslation(); + const appState = useSelector((state) => state)["pgr"]; + return ( + + {appState.complaints.response && } + {appState.complaints.response && } + + + + + ); +}; + +export default Response; diff --git a/micro-ui/web/packages/pgr/src/pages/citizen/index.js b/micro-ui/web/packages/pgr/src/pages/citizen/index.js new file mode 100644 index 00000000000..9319f81beb7 --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/citizen/index.js @@ -0,0 +1,48 @@ +import React from "react"; +import { ReopenComplaint } from "./ReopenComplaint/index"; +import SelectRating from "./Rating/SelectRating"; +import { PgrRoutes, getRoute } from "../../constants/Routes"; +import { useRouteMatch, Switch, useLocation } from "react-router-dom"; +import { AppContainer, BackButton, PrivateRoute } from "@egovernments/digit-ui-react-components"; + +import { CreateComplaint } from "./Create"; +import { ComplaintsList } from "./ComplaintsList"; +import ComplaintDetailsPage from "./ComplaintDetails"; +import Response from "./Response"; +import { useTranslation } from "react-i18next"; + +const App = () => { + const { t } = useTranslation(); + const { path, url, ...match } = useRouteMatch(); + const location = useLocation(); + + const CreateComplaint = Digit?.ComponentRegistryService?.getComponent("PGRCreateComplaintCitizen"); + const ComplaintsList = Digit?.ComponentRegistryService?.getComponent("PGRComplaintsList"); + const ComplaintDetailsPage = Digit?.ComponentRegistryService?.getComponent("PGRComplaintDetailsPage"); + const SelectRating = Digit?.ComponentRegistryService?.getComponent("PGRSelectRating"); + const Response = Digit?.ComponentRegistryService?.getComponent("PGRResponseCitzen"); + + return ( + +
+ {!location.pathname.includes("/response") && {t("CS_COMMON_BACK")}} + + {/* */} + + + + } + /> + } /> + } /> + + {/* */} + +
+
+ ); +}; + +export default App; diff --git a/micro-ui/web/packages/pgr/src/pages/employee/ComplaintDetails.js b/micro-ui/web/packages/pgr/src/pages/employee/ComplaintDetails.js new file mode 100644 index 00000000000..b76bdeed77f --- /dev/null +++ b/micro-ui/web/packages/pgr/src/pages/employee/ComplaintDetails.js @@ -0,0 +1,505 @@ +import React, { useState, useEffect, Fragment } from "react"; +import { useParams } from "react-router-dom"; +import { + BreakLine, + Card, + CardLabel, + CardLabelDesc, + CardSubHeader, + ConnectingCheckPoints, + CheckPoint, + DisplayPhotos, + MediaRow, + LastRow, + Row, + StatusTable, + PopUp, + HeaderBar, + ImageViewer, + TextInput, + TextArea, + UploadFile, + ButtonSelector, + Toast, + ActionBar, + Menu, + SubmitBar, + Dropdown, + Loader, + Modal, + SectionalDropdown, +} from "@egovernments/digit-ui-react-components"; + +import { Close } from "../../Icons"; +import { useTranslation } from "react-i18next"; +import { isError, useQueryClient } from "react-query"; +import StarRated from "../../components/timelineInstances/StarRated"; + +const MapView = (props) => { + return ( +
+ +
+ ); +}; + +const Heading = (props) => { + return

{props.label}

; +}; + +const CloseBtn = (props) => { + return ( +
+ +
+ ); +}; + +const TLCaption = ({ data, comments }) => { + const { t } = useTranslation() + return ( +
+ {data?.date &&

{data?.date}

} +

{data?.name}

+

{data?.mobileNumber}

+ {data?.source &&

{t("ES_COMMON_FILED_VIA_" + data?.source.toUpperCase())}

} + {comments?.map( e => +
+

{t("WF_COMMON_COMMENTS")}

+

{e}

+
+ )} +
+ ); +}; + +const ComplaintDetailsModal = ({ workflowDetails, complaintDetails, close, popup, selectedAction, onAssign, tenantId, t }) => { + + // RAIN-5692 PGR : GRO is assigning complaint, Selecting employee and assign. Its not getting assigned. + // Fix for next action assignee dropdown issue + const stateArray = workflowDetails?.data?.initialActionState?.nextActions?.filter( ele => ele?.action == selectedAction ); + const useEmployeeData = Digit.Hooks.pgr.useEmployeeFilter( + tenantId, + stateArray?.[0]?.assigneeRoles?.length > 0 ? stateArray?.[0]?.assigneeRoles?.join(",") : "", + complaintDetails + ); + const employeeData = useEmployeeData + ? useEmployeeData.map((departmentData) => { + return { heading: departmentData.department, options: departmentData.employees }; + }) + : null; + + const [selectedEmployee, setSelectedEmployee] = useState(null); + const [comments, setComments] = useState(""); + const [file, setFile] = useState(null); + const [uploadedFile, setUploadedFile] = useState(null); + const [error, setError] = useState(null); + const cityDetails = Digit.ULBService.getCurrentUlb(); + const [selectedReopenReason, setSelectedReopenReason] = useState(null); + + useEffect(() => { + (async () => { + setError(null); + if (file) { + if (file.size >= 5242880) { + setError(t("CS_MAXIMUM_UPLOAD_SIZE_EXCEEDED")); + } else { + try { + // TODO: change module in file storage + const response = await Digit.UploadServices.Filestorage("property-upload", file, cityDetails.code); + if (response?.data?.files?.length > 0) { + setUploadedFile(response?.data?.files[0]?.fileStoreId); + } else { + setError(t("CS_FILE_UPLOAD_ERROR")); + } + } catch (err) { + setError(t("CS_FILE_UPLOAD_ERROR")); + } + } + } + })(); + }, [file]); + + const reopenReasonMenu = [t(`CS_REOPEN_OPTION_ONE`), t(`CS_REOPEN_OPTION_TWO`), t(`CS_REOPEN_OPTION_THREE`), t(`CS_REOPEN_OPTION_FOUR`)]; + // const uploadFile = useCallback( () => { + + // }, [file]); + + function onSelectEmployee(employee) { + setSelectedEmployee(employee); + } + + function addComment(e) { + setError(null); + setComments(e.target.value); + } + + function selectfile(e) { + setFile(e.target.files[0]); + } + + function onSelectReopenReason(reason) { + setSelectedReopenReason(reason); + } + + return ( + + } + headerBarEnd={ close(popup)} />} + actionCancelLabel={t("CS_COMMON_CANCEL")} + actionCancelOnSubmit={() => close(popup)} + actionSaveLabel={ + selectedAction === "ASSIGN" || selectedAction === "REASSIGN" + ? t("CS_COMMON_ASSIGN") + : selectedAction === "REJECT" + ? t("CS_COMMON_REJECT") + : selectedAction === "REOPEN" + ? t("CS_COMMON_REOPEN") + : t("CS_COMMON_RESOLVE") + } + actionSaveOnSubmit={() => { + if(selectedAction === "REJECT" && !comments) + setError(t("CS_MANDATORY_COMMENTS")); + else + onAssign(selectedEmployee, comments, uploadedFile); + }} + error={error} + setError={setError} + > + + {selectedAction === "REJECT" || selectedAction === "RESOLVE" || selectedAction === "REOPEN" ? null : ( + + {t("CS_COMMON_EMPLOYEE_NAME")} + {employeeData && } + + )} + {selectedAction === "REOPEN" ? ( + + {t("CS_REOPEN_COMPLAINT")} + + + ) : null} + {t("CS_COMMON_EMPLOYEE_COMMENTS")} +