diff --git a/build/build-config.yml b/build/build-config.yml index a9728596..b3a52610 100644 --- a/build/build-config.yml +++ b/build/build-config.yml @@ -32,4 +32,10 @@ config: image-name: "application-service" dockerfile: "build/maven/Dockerfile" - work-dir: "studio-services/application-service/script" - image-name: "application-service-db" \ No newline at end of file + image-name: "application-service-db" + + - name: "builds/DIGIT-Studio/studio-ui/digit-studio" + build: + - work-dir: "micro-ui/" + dockerfile: "micro-ui/web/docker/Dockerfile" + image-name: "digit-studio" \ No newline at end of file diff --git a/micro-ui/.gitignore b/micro-ui/.gitignore new file mode 100644 index 00000000..feb4cac5 --- /dev/null +++ b/micro-ui/.gitignore @@ -0,0 +1,32 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +.env +.eslintcache + +# yarn $ +.yarn +yarn.lock +.yarnrc.yml + +# dependencies +node_modules +.yarn +/.pnp +.pnp.js + +# testing +/coverage + +# production +/web/build +dist +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/micro-ui/Jenkinsfile b/micro-ui/Jenkinsfile new file mode 100644 index 00000000..1206b9c1 --- /dev/null +++ b/micro-ui/Jenkinsfile @@ -0,0 +1,3 @@ +library 'ci-libs' + +buildPipeline(configFile: './build/build-config.yml') diff --git a/micro-ui/README.md b/micro-ui/README.md new file mode 100644 index 00000000..9420dbb7 --- /dev/null +++ b/micro-ui/README.md @@ -0,0 +1,140 @@ + +# workbench ui + +A React App built on top of DIGIT UI Core. + +# DIGIT + +DIGIT eGovernance Platform Services + +DIGIT (Digital Infrastructure for Governance, Impact & Transformation) is India's largest platform for governance services. Visit https://core.digit.org/ for more details. + +DIGIT platform is microservices based API platform enabling quick rebundling of services as per specific needs. This is a repo that lays down the core platform on top of which other mission services depend. + + +# DIGIT UI + + +This repository contains source code for web implementation of the new Digit UI modules with dependencies and libraries. + +Workbench module is used to Manage the master data (MDMS V2 Service) used across the DIGIT Services / Applications + +It is also used to manage the Localisation data present in the system (Localisation service) + + +## Run Locally + +Clone the project + +```bash + git clone https://github.com/egovernments/DIGIT-Frontend.git +``` + +Go to the Sub directory to run UI +```bash + cd into micro-ui/web/micro-ui-internals +``` + +Install dependencies + +```bash + yarn install +``` + +Add .env file +```bash + micro-ui/web/micro-ui-internals/example/.env +``` + +Start the server + +```bash + yarn start +``` + + +## Environment Variables + +To run this project, you will need to add the following environment variables to your .env file + +`REACT_APP_PROXY_API` :: `{{server url}}` + +`REACT_APP_GLOBAL` :: `{{server url}}` + +`REACT_APP_PROXY_ASSETS` :: `{{server url}}` + +`REACT_APP_USER_TYPE` :: `{{EMPLOYEE||CITIZEN}}` + +`SKIP_PREFLIGHT_CHECK` :: `true` + +[sample .env file](https://github.com/egovernments/Digit-Core/blob/workbench/frontend/micro-ui/web/micro-ui-internals/example/.env-unifieddev) + +## Tech Stack + +**Libraries:** + +[React](https://react.dev/) + +[React Hook Form](https://www.react-hook-form.com/) + +[React Query](https://tanstack.com/query/v3/) + +[Tailwind CSS](https://tailwindcss.com/) + +[Webpack](https://webpack.js.org/) + +## License + +[MIT](https://choosealicense.com/licenses/mit/) + + +## Author + +- [@jagankumar-egov](https://www.github.com/jagankumar-egov) + + +## Documentation + +[Documentation](https://https://core.digit.org/guides/developer-guide/ui-developer-guide/digit-ui) + + +## Support + +For support, add the issues in https://github.com/egovernments/DIGIT-core/issues. + + +## Modules + + 1. Core + 2. Workbench + 3. HRMS + 4. Dashboard + 5. Engagement + 6. Payment + +## Starting with Digit-UI App (Impelmentation Teams) - MICRO-UI + + +Go to the Sub directory to run UI + +```bash + cd into micro-ui/web +``` + +```bash + yarn install +``` + +Add .env file +```bash + micro-ui/web/.env +``` + +Start the server + +```bash + yarn start +``` + + +![Logo](https://s3.ap-south-1.amazonaws.com/works-dev-asset/mseva-white-logo.png) diff --git a/micro-ui/package.json b/micro-ui/package.json new file mode 100644 index 00000000..19a3c47d --- /dev/null +++ b/micro-ui/package.json @@ -0,0 +1,4 @@ +{ + "name": "workbench-ui", + "version": "1.0.0" +} \ No newline at end of file diff --git a/micro-ui/web/.babelrc b/micro-ui/web/.babelrc new file mode 100644 index 00000000..f42d4730 --- /dev/null +++ b/micro-ui/web/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-react"], + "plugins": ["@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-optional-chaining"] +} \ No newline at end of file diff --git a/micro-ui/web/.env.sample b/micro-ui/web/.env.sample new file mode 100644 index 00000000..e87c7f58 --- /dev/null +++ b/micro-ui/web/.env.sample @@ -0,0 +1,3 @@ +SKIP_PREFLIGHT_CHECK=true +REACT_APP_STATE_LEVEL_TENANT_ID=pb +REACT_APP_PROXY_URL=https://works-dev.digit.org diff --git a/micro-ui/web/docker/Dockerfile b/micro-ui/web/docker/Dockerfile new file mode 100644 index 00000000..4ba26aaf --- /dev/null +++ b/micro-ui/web/docker/Dockerfile @@ -0,0 +1,41 @@ +# Use Alpine-based Node.js image as the build stage +FROM ghcr.io/egovernments/alpine-node-builder-14:yarn AS build + +# Update and upgrade the package lists and add required dependencies +RUN apk update && apk upgrade +RUN apk add --no-cache git>2.30.0 + +# Define working directory +ARG WORK_DIR +WORKDIR /app + +# Set memory limits for Node.js processes +ENV NODE_OPTIONS "--max-old-space-size=8168" + +# Copy the application files +COPY ${WORK_DIR} . + +# List the contents of the directory for debugging +RUN ls -lah + +# Clean up yarn cache and node_modules to avoid old dependencies being used +RUN yarn cache clean && rm -rf node_modules + +# Install dependencies and build +RUN cd web/ \ + && ./install-deps.sh \ + && yarn install \ + && yarn build:webpack + +# Use Nginx to serve the static files +FROM nginx:mainline-alpine + +# Set the working directory for Nginx +ENV WORK_DIR=/var/web/digit-ui + +# Create the target directory for the web build +RUN mkdir -p ${WORK_DIR} + +# Copy the build output and Nginx configuration from the build stage +COPY --from=build /app/web/build ${WORK_DIR}/ +COPY --from=build /app/web/docker/nginx.conf /etc/nginx/conf.d/default.conf diff --git a/micro-ui/web/docker/devDockerfile b/micro-ui/web/docker/devDockerfile new file mode 100644 index 00000000..d7b1ba18 --- /dev/null +++ b/micro-ui/web/docker/devDockerfile @@ -0,0 +1,26 @@ +#FROM egovio/alpine-node-builder-14:yarn AS build +FROM ghcr.io/egovernments/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 ls -lah + +#RUN node web/envs.js +RUN cd web/ \ + && node envs.js \ + && ./install-deps.sh \ + && yarn install \ + && yarn build + +#FROM nginx:mainline-alpine +FROM ghcr.io/egovernments/nginx:mainline-alpine +ENV WORK_DIR=/var/web/digit-ui + +RUN mkdir -p ${WORK_DIR} + +COPY --from=build /app/web/build ${WORK_DIR}/ +COPY --from=build /app/web/docker/nginx.conf /etc/nginx/conf.d/default.conf diff --git a/micro-ui/web/docker/masDockerfile b/micro-ui/web/docker/masDockerfile new file mode 100644 index 00000000..5d7cf45d --- /dev/null +++ b/micro-ui/web/docker/masDockerfile @@ -0,0 +1,25 @@ +#FROM egovio/alpine-node-builder-14:yarn AS build +FROM ghcr.io/egovernments/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=3792" + +COPY ${WORK_DIR} . +RUN ls -lah + +#RUN node web/envs.js +RUN cd web/ \ + && node envs.js \ + && yarn install \ + && yarn build + +#FROM nginx:mainline-alpine +FROM ghcr.io/egovernments/nginx:mainline-alpine +ENV WORK_DIR=/var/web/digit-ui + +RUN mkdir -p ${WORK_DIR} + +COPY --from=build /app/web/build ${WORK_DIR}/ +COPY --from=build /app/web/docker/nginx.conf /etc/nginx/conf.d/default.conf diff --git a/micro-ui/web/docker/nginx.conf b/micro-ui/web/docker/nginx.conf new file mode 100644 index 00000000..4f532e4a --- /dev/null +++ b/micro-ui/web/docker/nginx.conf @@ -0,0 +1,12 @@ +server +{ + listen 80; + underscores_in_headers on; + + location /digit-ui + { + root /var/web; + index index.html index.htm; + try_files $uri $uri/ /digit-ui/index.html; + } +} \ No newline at end of file diff --git a/micro-ui/web/envs.js b/micro-ui/web/envs.js new file mode 100644 index 00000000..e69de29b diff --git a/micro-ui/web/install-deps.sh b/micro-ui/web/install-deps.sh new file mode 100755 index 00000000..efaceaee --- /dev/null +++ b/micro-ui/web/install-deps.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +BRANCH="$(git branch --show-current)" + +echo "Main Branch: $BRANCH" + +INTERNALS="micro-ui-internals" + +cp $INTERNALS/example/src/UICustomizations.js src/Customisations + +cd $INTERNALS && echo "Branch: $(git branch --show-current)" && echo "$(git log -1 --pretty=%B)" && echo "installing packages" + + +# yarn install diff --git a/micro-ui/web/micro-ui-internals/.gitignore b/micro-ui/web/micro-ui-internals/.gitignore new file mode 100644 index 00000000..1747c795 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/.gitignore @@ -0,0 +1,143 @@ +# Created by https://www.toptal.com/developers/gitignore/api/node,react +# Edit at https://www.toptal.com/developers/gitignore?templates=node,react + +### eGov ### +packages/css/example/index.css +package-lock.json +locales/ +build/ +packages/**/dist/ + +# yarn # +.yarn +.yarnrc.yml + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test +.env*.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist +dist-storybook + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +### react ### +.DS_* +**/*.backup.* +**/*.back.* + +node_modules + +*.sublime* + +psd +thumb +sketch + +# vs code +.vscode/ + +# End of https://www.toptal.com/developers/gitignore/api/node,react \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/.prettierignore b/micro-ui/web/micro-ui-internals/.prettierignore new file mode 100644 index 00000000..d54de016 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/.prettierignore @@ -0,0 +1,23 @@ + +# See https://help.github.com/ignore-files/ for more about ignoring files. +# dependencies +node_modules +# builds +build +dist +.rpt2_cache +# dev +dev.css +index.css +index.compat.css +index.min.css +# misc +.DS_Store +.env +.env.local +.env.development.local +.env.test.local +.env.production.local +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/micro-ui/web/micro-ui-internals/.prettierrc.json b/micro-ui/web/micro-ui-internals/.prettierrc.json new file mode 100644 index 00000000..b975008d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/.prettierrc.json @@ -0,0 +1,3 @@ +{ + "printWidth": 150 +} diff --git a/micro-ui/web/micro-ui-internals/README.md b/micro-ui/web/micro-ui-internals/README.md new file mode 100644 index 00000000..f23a1fcf --- /dev/null +++ b/micro-ui/web/micro-ui-internals/README.md @@ -0,0 +1,100 @@ + +# workbench ui + +A React App built on top of DIGIT UI Core. + + +# DIGIT UI + +DIGIT (Digital Infrastructure for Governance, Impact & Transformation) is India's largest platform for governance services. Visit https://www.digit.org for more details. + +This repository contains source code for web implementation of the new Digit UI modules with dependencies and libraries. + +Workbench module is used to Manage the master data (MDMS V2 Service) used across the DIGIT Services / Applications + +It is also used to manage the Localisation data present in the system (Localisation service) + + +## Run Locally + +Clone the project + +```bash + git clone https://github.com/egovernments/Digit-Core.git +``` + +Go to the Sub directory to run UI +```bash + cd into frontend/micro-ui/web/micro-ui-internals +``` + +Install dependencies + +```bash + yarn install +``` + +Add .env file +```bash + frontend/micro-ui/web/micro-ui-internals/example/.env +``` + +Start the server + +```bash + yarn start +``` + + +## Environment Variables + +To run this project, you will need to add the following environment variables to your .env file + +`REACT_APP_PROXY_API` :: `{{server url}}` + +`REACT_APP_GLOBAL` :: `{{server url}}` + +`REACT_APP_PROXY_ASSETS` :: `{{server url}}` + +`REACT_APP_USER_TYPE` :: `{{EMPLOYEE||CITIZEN}}` + +`SKIP_PREFLIGHT_CHECK` :: `true` + +[sample .env file](https://github.com/egovernments/Digit-Core/blob/workbench/frontend/micro-ui/web/micro-ui-internals/example/.env-unifieddev) + +## Tech Stack + +**Libraries:** + +[React](https://react.dev/) + +[React Hook Form](https://www.react-hook-form.com/) + +[React Query](https://tanstack.com/query/v3/) + +[Tailwind CSS](https://tailwindcss.com/) + +[Webpack](https://webpack.js.org/) + +## License + +[MIT](https://choosealicense.com/licenses/mit/) + + +## Author + +- [@jagankumar-egov](https://www.github.com/jagankumar-egov) + + +## Documentation + +[Documentation](https://https://core.digit.org/guides/developer-guide/ui-developer-guide/digit-ui) + + +## Support + +For support, add the issues in https://github.com/egovernments/DIGIT-core/issues. + + +![Logo](https://s3.ap-south-1.amazonaws.com/works-dev-asset/mseva-white-logo.png) + diff --git a/micro-ui/web/micro-ui-internals/clean.sh b/micro-ui/web/micro-ui-internals/clean.sh new file mode 100644 index 00000000..2235ef1c --- /dev/null +++ b/micro-ui/web/micro-ui-internals/clean.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +BASEDIR="$( cd "$( dirname "$0" )" && pwd )" + +msg() { + echo -e "\n\n\033[32;32m$1\033[0m" +} + +msg "Cleaning root" +rm -rf node_modules + +msg "Cleaning css" +cd "$BASEDIR/packages/css" && rm -rf node_modules + +msg "Cleaning libraries" +cd "$BASEDIR/packages/libraries" && rm -rf node_modules + +msg "Cleaning react-components" +cd "$BASEDIR/packages/react-components" && rm -rf node_modules + +msg "Cleaning PGR module" +cd "$BASEDIR/packages/modules/pgr" && rm -rf node_modules + +msg "Cleaning FSM module" +cd "$BASEDIR/packages/modules/fsm" && rm -rf node_modules + +msg "Cleaning Core module" +cd "$BASEDIR/packages/modules/core" && rm -rf node_modules diff --git a/micro-ui/web/micro-ui-internals/example/.env-unifiedDev b/micro-ui/web/micro-ui-internals/example/.env-unifiedDev new file mode 100644 index 00000000..115a6f85 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/example/.env-unifiedDev @@ -0,0 +1,7 @@ +SKIP_PREFLIGHT_CHECK=true +REACT_APP_USER_TYPE=EMPLOYEE +REACT_APP_EMPLOYEE_TOKEN=c835932f-2ad4-4d05-83d6-49e0b8c59f8a +REACT_APP_CITIZEN_TOKEN=7cd58aae-30b3-41ed-a1b3-3417107a993c +REACT_APP_PROXY_API=https://staging.digit.org +REACT_APP_PROXY_ASSETS=https://staging.digit.org +REACT_APP_GLOBAL=https://egov-dev-assets.s3.ap-south-1.amazonaws.com/globalConfigsDemo.js diff --git a/micro-ui/web/micro-ui-internals/example/.env-unifieddev b/micro-ui/web/micro-ui-internals/example/.env-unifieddev new file mode 100644 index 00000000..115a6f85 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/example/.env-unifieddev @@ -0,0 +1,7 @@ +SKIP_PREFLIGHT_CHECK=true +REACT_APP_USER_TYPE=EMPLOYEE +REACT_APP_EMPLOYEE_TOKEN=c835932f-2ad4-4d05-83d6-49e0b8c59f8a +REACT_APP_CITIZEN_TOKEN=7cd58aae-30b3-41ed-a1b3-3417107a993c +REACT_APP_PROXY_API=https://staging.digit.org +REACT_APP_PROXY_ASSETS=https://staging.digit.org +REACT_APP_GLOBAL=https://egov-dev-assets.s3.ap-south-1.amazonaws.com/globalConfigsDemo.js diff --git a/micro-ui/web/micro-ui-internals/example/package.json b/micro-ui/web/micro-ui-internals/example/package.json new file mode 100644 index 00000000..e826bb60 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/example/package.json @@ -0,0 +1,38 @@ +{ + "name": "@egovernments/digit-ui-example", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "private": true, + "homepage": "digit-ui", + "scripts": { + "start": "react-scripts start" + }, + "devDependencies": { + "@egovernments/digit-ui-svg-components":"1.0.15", + "@egovernments/digit-ui-libraries": "1.8.11", + "@egovernments/digit-ui-components": "0.2.0-studio.1", + "@egovernments/digit-ui-module-core": "1.8.33", + "@egovernments/digit-ui-module-utilities": "1.0.15", + "@egovernments/digit-ui-react-components": "1.8.19", + "@egovernments/digit-ui-module-public-services": "0.0.1", + "http-proxy-middleware": "^1.0.5", + "react": "17.0.2", + "react-dom": "17.0.2", + "react-i18next": "11.16.2", + "react-router-dom": "5.3.0", + "react-scripts": "^4.0.1" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/micro-ui/web/micro-ui-internals/example/public/index.html b/micro-ui/web/micro-ui-internals/example/public/index.html new file mode 100644 index 00000000..d3fa4d90 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/example/public/index.html @@ -0,0 +1,67 @@ + + + + + + + + + + DIGIT + + + + + + + + + + + +
+ + + diff --git a/micro-ui/web/micro-ui-internals/example/src/ComponentRegistry.js b/micro-ui/web/micro-ui-internals/example/src/ComponentRegistry.js new file mode 100644 index 00000000..9bafce3d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/example/src/ComponentRegistry.js @@ -0,0 +1,11 @@ +class Registry { + constructor(registry = {}) { + this._registry = registry; + } + + getComponent(id) { + return this._registry[id]; + } +} + +export default Registry; diff --git a/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js b/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js new file mode 100644 index 00000000..667ec60d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js @@ -0,0 +1,871 @@ +import { Link } from "react-router-dom"; +import _ from "lodash"; +import { useLocation, useHistory } from "react-router-dom"; +import { useParams } from "react-router-dom"; +import React from "react"; +//import {Button,Tag} from "@egovernments/digit-ui-components"; + +//create functions here based on module name set in mdms(eg->SearchProjectConfig) +//how to call these -> Digit?.Customizations?.[masterName]?.[moduleName] +// these functions will act as middlewares +var Digit = window.Digit || {}; + +function cleanObject(obj) { + for (const key in obj) { + if (Object.hasOwn(obj, key)) { + if (Array.isArray(obj[key])) { + if (obj[key].length === 0) { + delete obj[key]; + } + } else if ( + obj[key] === undefined || + obj[key] === null || + obj[key] === false || + obj[key] === "" || // Check for empty string + (typeof obj[key] === "object" && Object.keys(obj[key]).length === 0) + ) { + delete obj[key]; + } + } + } + return obj; +} + +const businessServiceMap = { + + "muster roll": "MR", + "estimate":"ESTIMATE" +}; + +const inboxModuleNameMap = { + "muster-roll-approval": "muster-roll-service", +}; + +export const UICustomizations = { + businessServiceMap, + updatePayload: (applicationDetails, data, action, businessService) => { + if (businessService === businessServiceMap.estimate) { + const workflow = { + comment: data.comments, + documents: data?.documents?.map((document) => { + return { + documentType: action?.action + " DOC", + fileName: document?.[1]?.file?.name, + fileStoreId: document?.[1]?.fileStoreId?.fileStoreId, + documentUid: document?.[1]?.fileStoreId?.fileStoreId, + tenantId: document?.[1]?.fileStoreId?.tenantId, + }; + }), + assignees: data?.assignees?.uuid ? [data?.assignees?.uuid] : null, + action: action.action, + }; + //filtering out the data + Object.keys(workflow).forEach((key, index) => { + if (!workflow[key] || workflow[key]?.length === 0) delete workflow[key]; + }); + + return { + estimate: applicationDetails, + workflow, + }; + } + if (businessService === businessServiceMap.contract) { + const workflow = { + comment: data?.comments, + documents: data?.documents?.map((document) => { + return { + documentType: action?.action + " DOC", + fileName: document?.[1]?.file?.name, + fileStoreId: document?.[1]?.fileStoreId?.fileStoreId, + documentUid: document?.[1]?.fileStoreId?.fileStoreId, + tenantId: document?.[1]?.fileStoreId?.tenantId, + }; + }), + assignees: data?.assignees?.uuid ? [data?.assignees?.uuid] : null, + action: action.action, + }; + //filtering out the data + Object.keys(workflow).forEach((key, index) => { + if (!workflow[key] || workflow[key]?.length === 0) delete workflow[key]; + }); + + return { + contract: applicationDetails, + workflow, + }; + } + if (businessService === businessServiceMap?.["muster roll"]) { + const workflow = { + comment: data?.comments, + documents: data?.documents?.map((document) => { + return { + documentType: action?.action + " DOC", + fileName: document?.[1]?.file?.name, + fileStoreId: document?.[1]?.fileStoreId?.fileStoreId, + documentUid: document?.[1]?.fileStoreId?.fileStoreId, + tenantId: document?.[1]?.fileStoreId?.tenantId, + }; + }), + assignees: data?.assignees?.uuid ? [data?.assignees?.uuid] : null, + action: action.action, + }; + //filtering out the data + Object.keys(workflow).forEach((key, index) => { + if (!workflow[key] || workflow[key]?.length === 0) delete workflow[key]; + }); + + return { + musterRoll: applicationDetails, + workflow, + }; + } + if (businessService === businessServiceMap?.["works.purchase"]) { + const workflow = { + comment: data.comments, + documents: data?.documents?.map((document) => { + return { + documentType: action?.action + " DOC", + fileName: document?.[1]?.file?.name, + fileStoreId: document?.[1]?.fileStoreId?.fileStoreId, + documentUid: document?.[1]?.fileStoreId?.fileStoreId, + tenantId: document?.[1]?.fileStoreId?.tenantId, + }; + }), + assignees: data?.assignees?.uuid ? [data?.assignees?.uuid] : null, + action: action.action, + }; + //filtering out the data + Object.keys(workflow).forEach((key, index) => { + if (!workflow[key] || workflow[key]?.length === 0) delete workflow[key]; + }); + + const additionalFieldsToSet = { + projectId: applicationDetails.additionalDetails.projectId, + invoiceDate: applicationDetails.billDate, + invoiceNumber: applicationDetails.referenceId.split("_")?.[1], + contractNumber: applicationDetails.referenceId.split("_")?.[0], + documents: applicationDetails.additionalDetails.documents, + }; + return { + bill: { ...applicationDetails, ...additionalFieldsToSet }, + workflow, + }; + } + }, + enableModalSubmit: (businessService, action, setModalSubmit, data) => { + if (businessService === businessServiceMap?.["muster roll"] && action.action === "APPROVE") { + setModalSubmit(data?.acceptTerms); + } + }, + enableHrmsSearch: (businessService, action) => { + if (businessService === businessServiceMap.estimate) { + return action.action.includes("TECHNICALSANCTION") || action.action.includes("VERIFYANDFORWARD"); + } + if (businessService === businessServiceMap.contract) { + return action.action.includes("VERIFY_AND_FORWARD"); + } + if (businessService === businessServiceMap?.["muster roll"]) { + return action.action.includes("VERIFY"); + } + if (businessService === businessServiceMap?.["works.purchase"]) { + return action.action.includes("VERIFY_AND_FORWARD"); + } + return false; + }, + getBusinessService: (moduleCode) => { + if (moduleCode?.includes("estimate")) { + return businessServiceMap?.estimate; + } else if (moduleCode?.includes("contract")) { + return businessServiceMap?.contract; + } else if (moduleCode?.includes("muster roll")) { + return businessServiceMap?.["muster roll"]; + } + else if (moduleCode?.includes("works.purchase")) { + return businessServiceMap?.["works.purchase"]; + } + else if (moduleCode?.includes("works.wages")) { + return businessServiceMap?.["works.wages"]; + } + else if (moduleCode?.includes("works.supervision")) { + return businessServiceMap?.["works.supervision"]; + } + else { + return businessServiceMap; + } + }, + getInboxModuleName: (moduleCode) => { + if (moduleCode?.includes("estimate")) { + return inboxModuleNameMap?.estimate; + } else if (moduleCode?.includes("contract")) { + return inboxModuleNameMap?.contracts; + } else if (moduleCode?.includes("attendence")) { + return inboxModuleNameMap?.attendencemgmt; + } else { + return inboxModuleNameMap; + } + }, + + AttendanceInboxConfig: { + preProcess: (data) => { + //set tenantId + data.body.inbox.tenantId = Digit.ULBService.getCurrentTenantId(); + data.body.inbox.processSearchCriteria.tenantId = Digit.ULBService.getCurrentTenantId(); + + const musterRollNumber = data?.body?.inbox?.moduleSearchCriteria?.musterRollNumber?.trim(); + if (musterRollNumber) data.body.inbox.moduleSearchCriteria.musterRollNumber = musterRollNumber; + + const attendanceRegisterName = data?.body?.inbox?.moduleSearchCriteria?.attendanceRegisterName?.trim(); + if (attendanceRegisterName) data.body.inbox.moduleSearchCriteria.attendanceRegisterName = attendanceRegisterName; + + // deleting them for now(assignee-> need clarity from pintu,ward-> static for now,not implemented BE side) + const assignee = _.clone(data.body.inbox.moduleSearchCriteria.assignee); + delete data.body.inbox.moduleSearchCriteria.assignee; + if (assignee?.code === "ASSIGNED_TO_ME") { + data.body.inbox.moduleSearchCriteria.assignee = Digit.UserService.getUser().info.uuid; + } + + //cloning locality and workflow states to format them + // let locality = _.clone(data.body.inbox.moduleSearchCriteria.locality ? data.body.inbox.moduleSearchCriteria.locality : []); + + let selectedOrg = _.clone(data.body.inbox.moduleSearchCriteria.orgId ? data.body.inbox.moduleSearchCriteria.orgId : null); + delete data.body.inbox.moduleSearchCriteria.orgId; + if (selectedOrg) { + data.body.inbox.moduleSearchCriteria.orgId = selectedOrg?.[0]?.applicationNumber; + } + + // let selectedWard = _.clone(data.body.inbox.moduleSearchCriteria.ward ? data.body.inbox.moduleSearchCriteria.ward : null); + // delete data.body.inbox.moduleSearchCriteria.ward; + // if(selectedWard) { + // data.body.inbox.moduleSearchCriteria.ward = selectedWard?.[0]?.code; + // } + + let states = _.clone(data.body.inbox.moduleSearchCriteria.state ? data.body.inbox.moduleSearchCriteria.state : []); + let ward = _.clone(data.body.inbox.moduleSearchCriteria.ward ? data.body.inbox.moduleSearchCriteria.ward : []); + // delete data.body.inbox.moduleSearchCriteria.locality; + delete data.body.inbox.moduleSearchCriteria.state; + delete data.body.inbox.moduleSearchCriteria.ward; + + // locality = locality?.map((row) => row?.code); + states = Object.keys(states)?.filter((key) => states[key]); + ward = ward?.map((row) => row?.code); + + // //adding formatted data to these keys + // if (locality.length > 0) data.body.inbox.moduleSearchCriteria.locality = locality; + if (states.length > 0) data.body.inbox.moduleSearchCriteria.status = states; + if (ward.length > 0) data.body.inbox.moduleSearchCriteria.ward = ward; + const projectType = _.clone(data.body.inbox.moduleSearchCriteria.projectType ? data.body.inbox.moduleSearchCriteria.projectType : {}); + if (projectType?.code) data.body.inbox.moduleSearchCriteria.projectType = projectType.code; + + //adding tenantId to moduleSearchCriteria + data.body.inbox.moduleSearchCriteria.tenantId = Digit.ULBService.getCurrentTenantId(); + + //setting limit and offset becoz somehow they are not getting set in muster inbox + data.body.inbox.limit = data.state.tableForm.limit; + data.body.inbox.offset = data.state.tableForm.offset; + delete data.state; + return data; + }, + postProcess: (responseArray, uiConfig) => { + const statusOptions = responseArray?.statusMap + ?.filter((item) => item.applicationstatus) + ?.map((item) => ({ code: item.applicationstatus, i18nKey: `COMMON_MASTERS_${item.applicationstatus}` })); + if (uiConfig?.type === "filter") { + let fieldConfig = uiConfig?.fields?.filter((item) => item.type === "dropdown" && item.populators.name === "musterRollStatus"); + if (fieldConfig.length) { + fieldConfig[0].populators.options = statusOptions; + } + } + }, + additionalCustomizations: (row, key, column, value, t, searchResult) => { + if (key === "ATM_MUSTER_ROLL_ID") { + return ( + + + {String(value ? (column.translate ? t(column.prefix ? `${column.prefix}${value}` : value) : value) : t("ES_COMMON_NA"))} + + + ); + } + if (key === "ATM_ATTENDANCE_WEEK") { + const week = `${Digit.DateUtils.ConvertTimestampToDate(value?.startDate, "dd/MM/yyyy")}-${Digit.DateUtils.ConvertTimestampToDate( + value?.endDate, + "dd/MM/yyyy" + )}`; + return
{week}
; + } + if (key === "ATM_NO_OF_INDIVIDUALS") { + return
{value?.length}
; + } + if (key === "ATM_AMOUNT_IN_RS") { + return {value ? Digit.Utils.dss.formatterWithoutRound(value, "number") : t("ES_COMMON_NA")}; + } + if (key === "ATM_SLA") { + return parseInt(value) > 0 ? ( + {t(value) || ""} + ) : ( + {t(value) || ""} + ); + } + if (key === "COMMON_WORKFLOW_STATES") { + return {t(`WF_MUSTOR_${value}`)}; + } + //added this in case we change the key and not updated here , it'll throw that nothing was returned from cell error if that case is not handled here. To prevent that error putting this default + return {t(`CASE_NOT_HANDLED`)}; + }, + MobileDetailsOnClick: (row, tenantId) => { + let link; + Object.keys(row).map((key) => { + if (key === "ATM_MUSTER_ROLL_ID") + link = `/${window.contextPath}/employee/attendencemgmt/view-attendance?tenantId=${tenantId}&musterRollNumber=${row[key]}`; + }); + return link; + }, + populateReqCriteria: () => { + const tenantId = Digit.ULBService.getCurrentTenantId(); + return { + url: "/org-services/organisation/v1/_search", + params: { limit: 50, offset: 0 }, + body: { + SearchCriteria: { + tenantId: tenantId, + functions: { + type: "CBO", + }, + }, + }, + config: { + enabled: true, + select: (data) => { + return data?.organisations; + }, + }, + }; + }, + }, + SearchWageSeekerConfig: { + customValidationCheck: (data) => { + //checking both to and from date are present + const { createdFrom, createdTo } = data; + if ((createdFrom === "" && createdTo !== "") || (createdFrom !== "" && createdTo === "")) + return { warning: true, label: "ES_COMMON_ENTER_DATE_RANGE" }; + + return false; + }, + preProcess: (data) => { + data.params = { ...data.params, tenantId: Digit.ULBService.getCurrentTenantId() }; + + let requestBody = { ...data.body.Individual }; + const pathConfig = { + name: "name.givenName", + }; + const dateConfig = { + createdFrom: "daystart", + createdTo: "dayend", + }; + const selectConfig = { + wardCode: "wardCode[0].code", + socialCategory: "socialCategory.code", + }; + const textConfig = ["name", "individualId"]; + let Individual = Object.keys(requestBody) + .map((key) => { + if (selectConfig[key]) { + requestBody[key] = _.get(requestBody, selectConfig[key], null); + } else if (typeof requestBody[key] == "object") { + requestBody[key] = requestBody[key]?.code; + } else if (textConfig?.includes(key)) { + requestBody[key] = requestBody[key]?.trim(); + } + return key; + }) + .filter((key) => requestBody[key]) + .reduce((acc, curr) => { + if (pathConfig[curr]) { + _.set(acc, pathConfig[curr], requestBody[curr]); + } else if (dateConfig[curr] && dateConfig[curr]?.includes("day")) { + _.set(acc, curr, Digit.Utils.date.convertDateToEpoch(requestBody[curr], dateConfig[curr])); + } else { + _.set(acc, curr, requestBody[curr]); + } + return acc; + }, {}); + + data.body.Individual = { ...Individual }; + return data; + }, + additionalCustomizations: (row, key, column, value, t, searchResult) => { + //here we can add multiple conditions + //like if a cell is link then we return link + //first we can identify which column it belongs to then we can return relevant result + switch (key) { + case "MASTERS_WAGESEEKER_ID": + return ( + + + {String(value ? (column.translate ? t(column.prefix ? `${column.prefix}${value}` : value) : value) : t("ES_COMMON_NA"))} + + + ); + + case "MASTERS_SOCIAL_CATEGORY": + return value ? {String(t(`MASTERS_${value}`))} : t("ES_COMMON_NA"); + + case "CORE_COMMON_PROFILE_CITY": + return value ? {String(t(Digit.Utils.locale.getCityLocale(value)))} : t("ES_COMMON_NA"); + + case "MASTERS_WARD": + return value ? ( + {String(t(Digit.Utils.locale.getMohallaLocale(value, row?.tenantId)))} + ) : ( + t("ES_COMMON_NA") + ); + + case "MASTERS_LOCALITY": + return value ? ( + {String(t(Digit.Utils.locale.getMohallaLocale(value, row?.tenantId)))} + ) : ( + t("ES_COMMON_NA") + ); + default: + return t("ES_COMMON_NA"); + } + }, + MobileDetailsOnClick: (row, tenantId) => { + let link; + Object.keys(row).map((key) => { + if (key === "MASTERS_WAGESEEKER_ID") + link = `/${window.contextPath}/employee/masters/view-wageseeker?tenantId=${tenantId}&wageseekerId=${row[key]}`; + }); + return link; + }, + additionalValidations: (type, data, keys) => { + if (type === "date") { + return data[keys.start] && data[keys.end] ? () => new Date(data[keys.start]).getTime() <= new Date(data[keys.end]).getTime() : true; + } + }, + }, + SearchDefaultConfig: { + customValidationCheck: (data) => { + //checking both to and from date are present + const { createdFrom, createdTo } = data; + if ((createdFrom === "" && createdTo !== "") || (createdFrom !== "" && createdTo === "")) + return { warning: true, label: "ES_COMMON_ENTER_DATE_RANGE" }; + + return false; + }, + preProcess: (data) => { + const location = useLocation(); + data.params = { ...data.params }; + const { masterName } = useParams(); + + const searchParams = new URLSearchParams(location.search); + const paths = { + "SearchProjectConfig": { + basePath: "Projects", + pathConfig: { + // id: "id[0]", + tenantId: "tenantId", + }, + dateConfig: { + endDate: "dayend", + startDate: "daystart" + }, + selectConfig: { + }, + textConfig :["id", "tenantId", "name", "projectNumber", "projectSubType" , "projectType"] + }, + "SearchProductConfig": { + basePath: "Product", + pathConfig: { + id: "id[0]", + }, + dateConfig: { + }, + selectConfig: { + }, + textConfig :["id", "manufacturer", "name", "type"] + }, + "SearchHouseholdConfig": { + basePath: "Household", + pathConfig: { + id: "id[0]", + clientReferenceId: "clientReferenceId[0]", + }, + dateConfig: { + }, + selectConfig: { + }, + textConfig :["boundaryCode", "clientReferenceId", "id"] + }, + "SearchProductVariantConfig": { + basePath: "ProductVariant", + pathConfig: { + id: "id[0]", + }, + dateConfig: { + }, + selectConfig: { + }, + textConfig :["productId", "sku", "variation"] + }, + "SearchProjectBeneficiaryConfig": { + basePath: "ProjectBeneficiary", + pathConfig: { + id: "id[0]", + clientReferenceId: "clientReferenceId[0]", + + }, + dateConfig: { + dateOfRegistration: "daystart" + }, + selectConfig: { + }, + textConfig :["beneficiaryId", "projectId"] + }, + "SearchProjectStaffConfig": { + basePath: "ProjectStaff", + pathConfig: { + id: "id[0]", + }, + dateConfig: { + startDate: "daystart", + endDate: "dayend", + }, + selectConfig: { + }, + textConfig :["projectId", "userId"] + }, + "SearchProjectResourceConfig": { + basePath: "ProjectResource", + pathConfig: { + id: "id[0]" + }, + dateConfig: { + }, + selectConfig: { + }, + textConfig : [] + }, + "SearchProjectTaskConfig": { + basePath: "Task", + pathConfig: { + id: "id[0]", + clientReferenceId: "clientReferenceId[0]", + }, + dateConfig: { + plannedEndDate: "dayend", + plannedStartDate: "daystart", + actualEndDate: "dayend", + actualStartDate: "daystart", + }, + selectConfig: { + }, + textConfig :["projectId","localityCode", "projectBeneficiaryId", "status"] + }, + "SearchFacilityConfig": { + basePath: "Facility", + pathConfig: { + id: "id[0]" + }, + dateConfig: { + }, + selectConfig: { + }, + textConfig :["faciltyUsage","localityCode", "storageCapacity","id"] + }, + "SearchProjectFacilityConfig": { + basePath: "ProjectFacility", + pathConfig: { + id: "id[0]", + projectId: "projectId[0]", + facilityId: "facilityId[0]" + }, + dateConfig: { + }, + selectConfig: { + }, + textConfig :[] + }, + } + + const id = searchParams.get("config")|| masterName; + + if(!paths||!paths?.[id]){ + return data; + } + let requestBody = { ...data.body[paths[id]?.basePath] }; + const pathConfig = paths[id]?.pathConfig; + const dateConfig = paths[id]?.dateConfig; + const selectConfig = paths[id]?.selectConfig; + const textConfig = paths[id]?.textConfig + + if(paths[id].basePath == "Projects"){ + data.state.searchForm={...data.state.searchForm,tenantId:"mz"} + } + let Product = Object.keys(requestBody) + .map((key) => { + if (selectConfig[key]) { + requestBody[key] = _.get(requestBody, selectConfig[key], null); + } else if (typeof requestBody[key] == "object") { + requestBody[key] = requestBody[key]?.code; + } else if (textConfig?.includes(key)) { + requestBody[key] = requestBody[key]?.trim(); + } + return key; + }) + .filter((key) => requestBody[key]) + .reduce((acc, curr) => { + if (pathConfig[curr]) { + _.set(acc, pathConfig[curr], requestBody[curr]); + } else if (dateConfig[curr] && dateConfig[curr]?.includes("day")) { + _.set(acc, curr, Digit.Utils.date.convertDateToEpoch(requestBody[curr], dateConfig[curr])); + } else { + _.set(acc, curr, requestBody[curr]); + } + return acc; + }, {}); + + if(paths[id].basePath == "Projects"){ + + data.body[paths[id].basePath] = [{ ...Product}]; + } + else data.body[paths[id].basePath] = { ...Product}; + return data; + }, + additionalCustomizations: (row, key, column, value, t, searchResult) => { + //here we can add multiple conditions + //like if a cell is link then we return link + //first we can identify which column it belongs to then we can return relevant result + switch (key) { + case "ID": + + return ( + + + + + ); + + case "MASTERS_SOCIAL_CATEGORY": + return value ? {String(t(`MASTERS_${value}`))} : t("ES_COMMON_NA"); + + case "CORE_COMMON_PROFILE_CITY": + return value ? {String(t(Digit.Utils.locale.getCityLocale(value)))} : t("ES_COMMON_NA"); + + case "MASTERS_WARD": + return value ? ( + {String(t(Digit.Utils.locale.getMohallaLocale(value, row?.tenantId)))} + ) : ( + t("ES_COMMON_NA") + ); + + case "MASTERS_LOCALITY": + return value ? ( + {String(t(Digit.Utils.locale.getMohallaLocale(value, row?.tenantId)))} + ) : ( + t("ES_COMMON_NA") + ); + default: + return t("ES_COMMON_NA"); + } + }, + MobileDetailsOnClick: (row, tenantId) => { + let link; + Object.keys(row).map((key) => { + if (key === "MASTERS_WAGESEEKER_ID") + link = `/${window.contextPath}/employee/masters/view-wageseeker?tenantId=${tenantId}&wageseekerId=${row[key]}`; + }); + return link; + }, + additionalValidations: (type, data, keys) => { + if (type === "date") { + return data[keys.start] && data[keys.end] ? () => new Date(data[keys.start]).getTime() <= new Date(data[keys.end]).getTime() : true; + } + }, + }, + SearchMDMSConfig: { + customValidationCheck: (data) => { + //checking both to and from date are present + const { createdFrom, createdTo, field, value } = data; + if ( + (createdFrom === "" && createdTo !== "") || + (createdFrom !== "" && createdTo === "") + ) + return { type: "warning", label: "ES_COMMON_ENTER_DATE_RANGE" }; + + if ((field && !value) || (!field && value)) { + return { + type: "warning", + label: "WBH_MDMS_SEARCH_VALIDATION_FIELD_VALUE_PAIR", + }; + } + + return false; + }, + preProcess: (data, additionalDetails) => { + const tenantId = Digit.ULBService.getCurrentTenantId(); + data.body.MdmsCriteria.tenantId = tenantId; + const filters = {}; + const custom = data.body.MdmsCriteria.custom; + const { field, value, isActive } = custom || {}; + filters[field?.code] = value; + if (isActive) { + if (isActive.value === "all") delete data.body.MdmsCriteria.isActive; + else data.body.MdmsCriteria.isActive = isActive?.value; + } else { + delete data.body.MdmsCriteria.isActive; + } + data.body.MdmsCriteria.filters = filters; + // data.body.MdmsCriteria.limit = 100 + data.body.MdmsCriteria.limit = data.state.tableForm.limit; + data.body.MdmsCriteria.offset = data.state.tableForm.offset; + data.body.MdmsCriteria.schemaCode = + // additionalDetails?.currentSchemaCode + "ACCESSCONTROL-ACTIONS-TEST.actions-test"; + delete data.body.MdmsCriteria.custom; + return data; + }, + additionalCustomizations: (row, key, column, value, t, searchResult) => { + switch (key) { + case "Active": + return ( + // + <> + ); + default: + return t("ES_COMMON_NA"); + } + }, + MobileDetailsOnClick: (row, tenantId) => { + let link; + Object.keys(row).map((key) => { + if (key === "MASTERS_WAGESEEKER_ID") + link = `/${window.contextPath}/employee/masters/view-wageseeker?tenantId=${tenantId}&wageseekerId=${row[key]}`; + }); + return link; + }, + additionalValidations: (type, data, keys) => { + if (type === "date") { + return data[keys.start] && data[keys.end] + ? () => + new Date(data[keys.start]).getTime() <= + new Date(data[keys.end]).getTime() + : true; + } + }, + selectionHandler: (event) => { + console.log(event, "selection handler event"); + }, // selectionHandler : Is used to handle row selections. gets on object which containes 3 key value pairs: allSelected(whether all rows are selected or not), selectedCount (no, of rows selected),selectedRows( an array of selected rows) + actionSelectHandler: (index, label, selectedRows) => { + console.log(index, label, selectedRows, "action handler"); + }, // actionSelectHandler : Is used to handle onClick functions of table action button on row selections, gets index,label and selectedRows as props + footerActionHandler: (index, event) => { + console.log(index, "index"); + console.log(event, "event"); + }, // footerActionHandler : Is used to handle onclick functions of footer action buttons, gets index and event as props + linkColumnHandler: (row) => { + console.log(row, "row"); + const url = `/${window.contextPath}/employee/microplan/view-main?tenantId=${row?.tenantId}&uniqueIdentifier=${row?.uniqueIdentifier}`; + window.location.href = url; + }, + }, + SampleInboxConfig: { + getSearchRequest: ( prop) => { + const tenantId = Digit.ULBService.getCurrentTenantId(); + return { + url: `/plan-service/config/_search`, + params: { }, + body: { + CampaignDetails: { + "tenantId": tenantId, + } + }, + changeQueryName: `boundarySearchForPlanFacility`, + config: { + enabled: true, + select: (data) => { + const result = data?.CampaignDetails?.[0]?.boundaries?.filter((item) => item.type == prop.lowestHierarchy) || []; + return result + }, + }, + }; + }, + additionalCustomizations: (row, key, column, value, t, searchResult) => { + if (key === "Facility name") { + return ( + // , + +const downloadPdf = (blob, fileName) => { + if (window.mSewaApp && window.mSewaApp.isMsewaApp() && window.mSewaApp.downloadBase64File) { + var reader = new FileReader(); + reader.readAsDataURL(blob); + reader.onloadend = function () { + var base64data = reader.result; + window.mSewaApp.downloadBase64File(base64data, fileName); + }; + } else { + const link = document.createElement("a"); + // create a blobURI pointing to our Blob + link.href = URL.createObjectURL(blob); + link.download = fileName; + // some browser needs the anchor to be in the doc + document.body.append(link); + link.click(); + link.remove(); + // in case the Blob uses a lot of memory + setTimeout(() => URL.revokeObjectURL(link.href), 7000); + } +}; + +/* Download Receipts */ + +export const downloadReceipt = async ( + consumerCode, + businessService, + pdfKey = "consolidatedreceipt", + tenantId = Digit.ULBService.getCurrentTenantId(), + receiptNumber = null +) => { + const response = await Digit.ReceiptsService.receipt_download(businessService, consumerCode, tenantId, pdfKey, receiptNumber); + const responseStatus = parseInt(response.status, 10); + if (responseStatus === 201 || responseStatus === 200) { + let filename = receiptNumber ? `receiptNumber-${receiptNumber}.pdf` : `consumer-${consumerCode}.pdf`; + downloadPdf(new Blob([response.data], { type: "application/pdf" }), filename); + } +}; +/* Download Bills */ + +export const downloadBill = async ( + consumerCode, + businessService, + pdfKey = "consolidatedbill", + tenantId = Digit.ULBService.getCurrentTenantId(), +) => { + const response = await Digit.ReceiptsService.bill_download(businessService, consumerCode, tenantId, pdfKey); + const responseStatus = parseInt(response.status, 10); + if (responseStatus === 201 || responseStatus === 200) { + let filename = consumerCode ? `consumerCode-${consumerCode}.pdf` : `consumer-${consumerCode}.pdf`; + downloadPdf(new Blob([response.data], { type: "application/pdf" }), filename); + } +}; + +export const getFileUrl = (linkText = "") => { + const linkList = (linkText && typeof linkText == "string" && linkText.split(",")) || []; + let fileURL = ""; + linkList && + linkList.map((link) => { + if (!link.includes("large") && !link.includes("medium") && !link.includes("small")) { + fileURL = link; + } + }); + return fileURL; +}; + +/* Use this util function to download the file from any s3 links */ +export const downloadPDFFromLink = async (link, openIn = "_blank") => { + var response = await fetch(link, { + responseType: "arraybuffer", + headers: { + "Content-Type": "application/json", + Accept: "application/pdf", + }, + method: "GET", + mode: "cors", + }).then((res) => res.blob()); + if (window.mSewaApp && window.mSewaApp.isMsewaApp() && window.mSewaApp.downloadBase64File) { + var reader = new FileReader(); + reader.readAsDataURL(response); + reader.onloadend = function () { + var base64data = reader.result; + window.mSewaApp.downloadBase64File(base64data, decodeURIComponent(link.split("?")[0].split("/").pop().slice(13))); + }; + } else { + var a = document.createElement("a"); + document.body.appendChild(a); + a.style = "display: none"; + let url = window.URL.createObjectURL(response); + a.href = url; + a.download = decodeURIComponent(link.split("?")[0].split("/").pop().slice(13)); + a.click(); + window.URL.revokeObjectURL(url); + } +}; diff --git a/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/preProcessMDMSConfig.js b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/preProcessMDMSConfig.js new file mode 100644 index 00000000..5d3aa074 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/preProcessMDMSConfig.js @@ -0,0 +1,128 @@ + +import _ from "lodash"; + +/* +PRE-PROCESS MDMS CONFIG +----------------------- +@Author - Hariom Sinha + +Usually FormComposer configs needs some dependendent params to drive the rendering and functionality. In MDMS config, we cannot inject those params. +So, this component is developed to help convert any MDMS config to a FormComposer enabled config by injecting multiple params. +As of now, two params are introduced - + a. translate + b. updateDependent + c. convertStringToRegEx + Based on the newer requirement, this utility can be enhanced to support extra types of params. + +How to use this Pre-Process Utility - +1. Fetch any config from MDMS. +2. In each input object of the config, set preProcess object with required Params. + ex - + { + isMandatory: false, + key: "noSubProject_locality", + type: "radioordropdown", + label: "WORKS_LOCALITY", + disable: false, + preProcess : { + translate : ["populators.error"], + updateDependent : ["populators.options"] + }, + populators: { + name: "noSubProject_locality", + optionsKey: "i18nKey", + error: "WORKS_REQUIRED_ERR", + required: false, + optionsCustomStyle : { + top : "2.5rem" + }, + options: [] + }, + }, +3. Both 'translate' and 'updateDependent' supports multiple JSON paths. This means that we can inject multiple params at a time in the same input object. +4. Any component who wants to transform MDMS config to FormComposer config using this Pre-Process Utility should pass the dependencies based on their requirement. + Example, if one needs to update the dropdown value based on other dropdown field change, then the component can pass that Param as state. + The Component should make calls to this config only when the dependent state changes, to avoid performance issues. + + const config = useMemo( + () => Digit.Utils.preProcessMDMSConfig(t, createProjectConfig, { + updateDependent : [ + { + key : 'withSubProject_project_subScheme', + value : [withSubProjectSubSchemeOptions] + } + ] + }), + [withSubProjectSubSchemeOptions]); +5. Translation and convertStringToRegEx will be handled by the Pre-Preprocess on its own. No params are required for this. +*/ + + +const translate = (config, index, inputIndex, t) => { + + let input = config?.form[index].body[inputIndex]; + //iterate all translate keys and handle translation + for(let toTranslate = 0; toTranslate { + let input = config?.form[index].body[inputIndex]; + //iterate all update options keys and add options as params + for(let toUpdate = 0; toUpdatedependent?.key === inputKey)?.[0]?.value?.[toUpdate])); + } + + return config; +} + +const convertStringToRegEx = (config, index, inputIndex) => { + + let input = config?.form[index].body[inputIndex]; + //iterate all translate keys and handle translation + for(let toValidate = 0; toValidate { + //Do not loop preProcess object, to avoid unnecessary 'translate' and 'updateDependent' calls + //To add any new transform object, simply add a new if statement + if(preProcesses?.translate) { + config = translate(config, index, inputIndex, t); + } + if(preProcesses?.updateDependent) { + config = updateDependent(config, index, inputIndex, inputKey, dependencyConfig); + } + if(preProcesses?.convertStringToRegEx) { + config = convertStringToRegEx(config, index, inputIndex, inputKey); + } + return config; +} + +const preProcessMDMSConfig = (t, config, dependencyConfig) => { + config?.form?.map((section, index)=>{ + section?.body?.map((input, inputIndex)=>{ + let preProcesses = input?.preProcess; + if(preProcesses){ + config = transform(preProcesses, config, index, inputIndex, input?.key, t, dependencyConfig); + } + }) + }) + return config; +} + +export default preProcessMDMSConfig; + diff --git a/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/preProcessMDMSConfigInboxSearch.js b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/preProcessMDMSConfigInboxSearch.js new file mode 100644 index 00000000..05743c93 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/preProcessMDMSConfigInboxSearch.js @@ -0,0 +1,110 @@ + +import _ from "lodash"; + +/* +PRE-PROCESS MDMS CONFIG +----------------------- +@Author - Hariom Sinha + +Usually FormComposer configs needs some dependendent params to drive the rendering and functionality. In MDMS config, we cannot inject those params. +So, this component is developed to help convert any MDMS config to a FormComposer enabled config by injecting multiple params. +As of now, two params are introduced - + a. translate + b. updateDependent + c. convertStringToRegEx + Based on the newer requirement, this utility can be enhanced to support extra types of params. + +How to use this Pre-Process Utility - +1. Fetch any config from MDMS. +2. In each input object of the config, set preProcess object with required Params. + ex - + { + isMandatory: false, + key: "noSubProject_locality", + type: "radioordropdown", + label: "WORKS_LOCALITY", + disable: false, + preProcess : { + translate : ["populators.error"], + updateDependent : ["populators.options"] + }, + populators: { + name: "noSubProject_locality", + optionsKey: "i18nKey", + error: "WORKS_REQUIRED_ERR", + required: false, + optionsCustomStyle : { + top : "2.5rem" + }, + options: [] + }, + }, +3. Both 'translate' and 'updateDependent' supports multiple JSON paths. This means that we can inject multiple params at a time in the same input object. +4. Any component who wants to transform MDMS config to FormComposer config using this Pre-Process Utility should pass the dependencies based on their requirement. + Example, if one needs to update the dropdown value based on other dropdown field change, then the component can pass that Param as state. + The Component should make calls to this config only when the dependent state changes, to avoid performance issues. + + const config = useMemo( + () => Digit.Utils.preProcessMDMSConfig(t, createProjectConfig, { + updateDependent : [ + { + key : 'withSubProject_project_subScheme', + value : [withSubProjectSubSchemeOptions] + } + ] + }), + [withSubProjectSubSchemeOptions]); +5. Translation and convertStringToRegEx will be handled by the Pre-Preprocess on its own. No params are required for this. +*/ + +const convertStringToRegEx = (target) => { + //iterate all translate keys and handle translation + for(let toValidate = 0; toValidate { + //iterate all translate keys and handle translation + for(let toUpdate = 0; toUpdatedependent?.key === inputKey)?.[0]?.value)); + + _.set(target, keyToUpdate, dependentObject); + } + return target; +} + +const transform = (preProcesses, target, inputIndex, inputKey, t, dependencyConfig) => { + //Do not loop preProcess object, to avoid unnecessary 'translate' and 'updateDependent' calls + //To add any new transform object, simply add a new if statement + if(preProcesses?.convertStringToRegEx) { + target = convertStringToRegEx(target); + } + if(preProcesses?.updateDependent) { + target = updateDependent(target, dependencyConfig, inputKey); + } + return target; +} + +const preProcessMDMSConfigInboxSearch = (t, config, jsonpath, dependencyConfig) => { + let targetConfig = _.get(config, jsonpath); + let updatedConfig = []; + //Iterate the entire jsonpath array and push the updated objects in the new res array. + //Set the updated res in place of the targetConfig + targetConfig?.map((target, inputIndex) => { + let preProcesses = target?.preProcess; + updatedConfig.push(transform(preProcesses, target, inputIndex, target?.key, t, dependencyConfig)); + }) + _.set(config, jsonpath, updatedConfig); + return config; +} + +export default preProcessMDMSConfigInboxSearch; + diff --git a/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/privacy.js b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/privacy.js new file mode 100644 index 00000000..ae2d62c5 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/privacy.js @@ -0,0 +1,107 @@ +/** + * Contains all utils used for Privacy + * + * @author jagankumar-egov + * + * Feature :: Privacy + */ + +/** + * Custom util to get the privacy object of current screen + * + * @author jagankumar-egov + * + * @example + * Digit.Utils.getPrivacyObject() + * + * @returns {object} Returns the privacy object + */ +export const getPrivacyObject = () => { + const privacyObj = getAllPrivacyObject(); + return privacyObj?.[window.location.pathname] || {}; +}; + +/** + * Custom util to get the complete privacy object. + * + * @author jagankumar-egov + * + * @example + * Digit.Utils.getAllPrivacyObject() + * + * @returns {object} Returns the key value pair of privacy object in every screens + */ +export const getAllPrivacyObject = () => { + return Digit.SessionStorage.get("PRIVACY_OBJECT") || {}; +}; + +/** + * Custom util to update the privacy object. + * + * @author jagankumar-egov + * + * @example + * Digit.Utils.setPrivacyObject({}) + * + */ +export const setPrivacyObject = (updatedPrivacyValue = {}) => { + return Digit.SessionStorage.set("PRIVACY_OBJECT", { ...updatedPrivacyValue }); +}; + +/** + * Main Util to update the privacy + * + * @author jagankumar-egov + * + * Feature :: Privacy + * + * @example + * Digit.Utils.updatePrivacy(uuid, fieldName) + * + * @returns {object} Returns the updated privacy object + */ +export const updatePrivacy = (uuid, fieldName) => { + const privacyObj = Digit.Utils.getAllPrivacyObject(); + const plainRequestFields = + privacyObj?.[window.location.pathname]?.recordId === uuid ? privacyObj?.[window.location.pathname]?.plainRequestFields || [] : []; + const newObj = { + ...privacyObj, + [window.location.pathname]: { recordId: uuid, plainRequestFields: Array.isArray(fieldName) ? [...fieldName, ...plainRequestFields] : [fieldName, ...plainRequestFields] }, + }; + Digit.Utils.setPrivacyObject({ ...newObj }); + return newObj; +}; + +/** + * Core Component Logic for showing the unmask button and for which fields will be controlled by + * mdms -> DataSecurity -> SecurityPolicy.json + * + * @author jagankumar-egov + * + * Feature :: Privacy + * + * @example + * Digit.Utils.checkPrivacy(mdmsObj, privacyDetail) + * + * @returns {boolean} Returns the show or hide in boolean type + */ + +export const checkPrivacy = (mdmsObj, privacyDetail) => { + if (mdmsObj?.attributes?.some((ele) => (ele?.name === privacyDetail?.fieldName || privacyDetail?.fieldName?.includes(ele?.name) )&& ele?.defaultVisibility === "MASKED")) { + return true; + } + const userInfo = Digit.UserService.getUser(); + const userRoles = userInfo?.info?.roles?.map((roleData) => roleData?.code); + if ( + mdmsObj?.roleBasedDecryptionPolicy?.some( + (ele) => + ele?.roles?.some((e) => userRoles?.includes(e)) && + ele?.attributeAccessList?.some( + (ele) => (ele?.attribute === privacyDetail?.fieldName || privacyDetail?.fieldName?.includes(ele?.attribute)) && ele?.firstLevelVisibility === "MASKED" && ele?.secondLevelVisibility === "PLAIN" + ) + ) + ) { + return true; + } + return false; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/pt/index.js b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/pt/index.js new file mode 100644 index 00000000..ec8ff046 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/libraries/src/utils/pt/index.js @@ -0,0 +1,65 @@ +export const getPropertyTypeLocale = (value) => { + return `PROPERTYTAX_BILLING_SLAB_${value?.split(".")[0]}`; +}; + +export const getPropertySubtypeLocale = (value) => `PROPERTYTAX_BILLING_SLAB_${value}`; + +export const stringReplaceAll = (str = "", searcher = "", replaceWith = "") => { + if (searcher === "") return str; + while (str.includes(searcher)) { + str = str.replace(searcher, replaceWith); + } + return str; +}; + +/* method to check not null if not returns false*/ +export const checkForNotNull = (value = "") => { + return value && value != null && value != undefined && value != "" ? true : false; +}; + +export const convertDotValues = (value = "") => { + return ( + (checkForNotNull(value) && ((value.replaceAll && value.replaceAll(".", "_")) || (value.replace && stringReplaceAll(value, ".", "_")))) || "NA" + ); +}; + +export const convertToLocale = (value = "", key = "") => { + let convertedValue = convertDotValues(value); + if (convertedValue === "NA") { + return "PT_NA"; + } + return `${key}_${convertedValue}`; +}; +export const getMohallaLocale = (value = "", tenantId = "") => { + let convertedValue = convertDotValues(tenantId); + if (convertedValue === "NA" || !checkForNotNull(value)) { + return "PT_NA"; + } + convertedValue = convertedValue.toUpperCase(); + return convertToLocale(value, `${convertedValue}_REVENUE`); +}; + +export const getCityLocale = (value = "") => { + let convertedValue = convertDotValues(value); + if (convertedValue === "NA" || !checkForNotNull(value)) { + return "PT_NA"; + } + convertedValue = convertedValue.toUpperCase(); + return convertToLocale(convertedValue, `TENANT_TENANTS`); +}; + +export const convertDateToEpoch = (dateString, dayStartOrEnd = "dayend") => { + //example input format : "2018-10-02" + try { + const parts = dateString.match(/(\d{4})-(\d{1,2})-(\d{1,2})/); + const DateObj = new Date(Date.UTC(parts[1], parts[2] - 1, parts[3])); + DateObj.setMinutes(DateObj.getMinutes() + DateObj.getTimezoneOffset()); + if (dayStartOrEnd === "dayend") { + DateObj.setHours(DateObj.getHours() + 24); + DateObj.setSeconds(DateObj.getSeconds() - 1); + } + return DateObj.getTime(); + } catch (e) { + return dateString; + } +}; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/README.md b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/README.md new file mode 100644 index 00000000..63ba7e37 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/README.md @@ -0,0 +1,122 @@ + + +# Sample UI Module for DIGIT + +This README provides an overview of creating a new UI module package in the DIGIT platform, following the guidelines from the [DIGIT Developer Guide](https://core.digit.org/guides/developer-guide/ui-developer-guide/create-a-new-ui-module-package). + +## Prerequisites +Ensure you have the following installed: +- Node.js (14.18) +- npm or yarn +- A working DIGIT UI setup + +## Steps to Create a New UI Module + +### 1. Initialize the Module +Navigate to the `packages/modules` directory inside your DIGIT UI project and create a new folder for the module: +```sh +cd packages/modules +mkdir sample +cd sample +``` + +### 2. Initialize a Package +Run the following command to create a `package.json` file: +```sh +npm init -y +``` +Modify the `package.json` to include necessary dependencies and metadata: +```json +{ + "name": "@egovernments/digit-ui-module-sample", + "version": "0.0.1", + "main": "src/index.js", + "dependencies": { + "react": "17.0.2", + "react-router-dom": "5.3.0" + } +} +``` + +### 3. Set Up the Module Structure +Create the necessary directories and files: +```sh +mkdir -p src/pages src/components src/config +``` + +Create an `index.js` file in `src/`: +```js +export * from "./pages"; +export * from "./components"; +export * from "./config"; +``` + +### 4. Define Routes in `module.js` +Create a `module.js` file inside `src/`: +```js +const sampleModule = { + routes: [ + { + path: "/sample", + component: () => import("./pages/SamplePage"), + private: true, + }, + ], +}; +export default sampleModule; +``` + +### 5. Create a Sample Page +Inside `src/pages`, create `SamplePage.js`: +```js +import React from "react"; +const SamplePage = () => { + return
Welcome to the Sample Module!
; +}; +export default SamplePage; +``` + +### 6. Import the Module in Root Application +Modify `root-app` to include the new module: +```js +import {initSampleComponents} from "@egovernments/digit-ui-module-sample"; + +const modules = ["sample"]; + +initSampleComponents() + +``` + +### 7. Run and Test +Build and start the application: +```sh +yarn install +yarn start +``` +Navigate to `http://localhost:3000/sample` to see the new module in action. + +## Conclusion +This guide provides a structured approach to integrating a new module into the DIGIT UI platform. Follow these steps to create, configure, and deploy your module efficiently. + +For more details, refer to the official [DIGIT Developer Guide](https://core.digit.org/guides/developer-guide/ui-developer-guide/create-a-new-ui-module-package). + + +## License + +[MIT](https://choosealicense.com/licenses/mit/) + +## Documentation + +Documentation Site (https://core.digit.org/guides/developer-guide/ui-developer-guide/digit-ui) +Workbench Documentation(https://workbench.digit.org/platform/functional-specifications/workbench-ui) + +## Maintainer + +- [jagankumar-egov](https://www.github.com/jagankumar-egov) + + +### Published from DIGIT Frontend +DIGIT Frontend Repo (https://github.com/egovernments/Digit-Frontend/tree/master) + + +![Logo](https://s3.ap-south-1.amazonaws.com/works-dev-asset/mseva-white-logo.png) \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/package.json b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/package.json new file mode 100644 index 00000000..525618d4 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/package.json @@ -0,0 +1,36 @@ +{ + "name": "@egovernments/digit-ui-module-public-services", + "version": "0.0.1", + "description": "Public Service Module UI", + "main": "dist/index.js", + "module": "dist/index.modern.js", + "source": "src/Module.js", + "files": [ + "dist" + ], + "scripts": { + "start": "microbundle-crl watch --no-compress --format modern,cjs", + "build": "microbundle-crl --compress --no-sourcemap --format cjs", + "prepublish": "yarn build" + }, + "peerDependencies": { + "react": "17.0.2", + "react-router-dom": "5.3.0" + }, + "dependencies": { + "@egovernments/digit-ui-react-components": "1.8.19", + "@egovernments/digit-ui-components": "0.2.0-studio.1", + "react": "17.0.2", + "react-date-range": "^1.4.0", + "react-dom": "17.0.2", + "react-hook-form": "6.15.8", + "react-i18next": "11.16.2", + "react-query": "3.6.1", + "react-router-dom": "5.3.0" + }, + "resolutions": { + "styled-components": "5.0.0" + }, + "author": "Jagankumar ", + "license": "MIT" +} diff --git a/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/src/Module.js b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/src/Module.js new file mode 100644 index 00000000..29abf618 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/src/Module.js @@ -0,0 +1,56 @@ +import { Loader} from "@egovernments/digit-ui-components"; +import React from "react"; +import { useRouteMatch } from "react-router-dom"; +import { default as EmployeeApp } from "./pages/employee"; +import PublicServicesCard from "./components/PublicServicesCard"; +import { updateCustomConfigs } from "./utils"; + + +// SampleModule component manages the initialization and rendering of the module +export const PublicServicesModule = ({ stateCode, userType, tenants }) => { + // Get the current route path and URL using React Router + const { path, url } = useRouteMatch(); + + // Get the currently selected tenant ID from DIGIT's ULB Service + const tenantId = Digit.ULBService.getCurrentTenantId(); + + // Define the modules that this component depends on + const moduleCode = ["sample", "common", "workflow"]; + + // Get the current language selected in the DIGIT Store + const language = Digit.StoreData.getCurrentLanguage(); + + // Fetch module-specific store data + const { isLoading, data: store } = Digit.Services.useStore({ + stateCode, + moduleCode, + language, + }); + + // Display a loader until the data is available + if (isLoading) { + return ; + } + + // Render the EmployeeApp component with required props + return ; +}; + +// Register components to be used in DIGIT's Component Registry +const componentsToRegister = { + PublicServicesModule, + PublicServicesCard, +}; + +// Initialize and register module components +export const initPublicServiceComponents = () => { + // Apply custom hooks overrides + + // Update custom configurations + updateCustomConfigs(); + + // Register each component with the DIGIT Component Registry + Object.entries(componentsToRegister).forEach(([key, value]) => { + Digit.ComponentRegistryService.setComponent(key, value); + }); +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/src/components/AdditionalComponent.js b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/src/components/AdditionalComponent.js new file mode 100644 index 00000000..63020c3e --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/PublicServices/src/components/AdditionalComponent.js @@ -0,0 +1,136 @@ +import { Button, Dropdown, LabelFieldPair, TextInput, CustomSVG, Card,HeaderComponent } from "@egovernments/digit-ui-components"; +import React, { Fragment, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; + +const AdditionalComponent = ({ onSelect, ...props }) => { + const { t } = useTranslation(); + // option for dropdown + const [options, setOptions] = useState([ + { + code: "ADHAAR", + name: "Adhaar", + }, + { + code: "PANCARD", + name: "Pan Card", + }, + { + code: "PASSPORT", + name: "Passport", + }, + ]); + + // state for storing data + const [documentData, setDocumentData] = useState([ + { + key: 1, + type: null, + value: null, + }, + ]); + + // fn to update the value based on type. + const handleUpdateField = ({ type, value, item, index }) => { + switch (type) { + case "TYPE": + setDocumentData((prev) => { + return prev?.map((i, n) => { + if (i.key === item.key) { + return { + ...i, + type: value?.code, + }; + } + return i; + }); + }); + break; + case "VALUE": + setDocumentData((prev) => { + return prev?.map((i, n) => { + if (i.key === item.key) { + return { + ...i, + value: value, + }; + } + return i; + }); + }); + break; + default: + break; + } + }; + + //fn to add more field + const add = () => { + setDocumentData((prev) => [ + ...prev, + { + key: prev?.length + 1, + value: null, + type: null, + }, + ]); + }; + //fn to delete field + const deleteItem = (data) => { + const fil = documentData.filter((i) => i.key !== data.key); + const up = fil.map((item, index) => ({ ...item, key: index + 1 })); + setDocumentData(up); + }; + + // when doc update calling onselect for update the value in formdata + useEffect(() => { + onSelect("additionalDetails", documentData); + }, [documentData]); + + return ( + <> + {documentData?.map((item, index) => ( + + {documentData?.length > 1 ? ( +
deleteItem(item, index)}> + +
+ ) : null} + + +
+ +
+
+ i.code === item?.type)} + select={(value) => { + handleUpdateField({ type: "TYPE", value: value, item: item, index: index }); + }} + /> +
+ + +
+ +
+
+
+ handleUpdateField({ type: "VALUE", value: event.target.value, item: item, index: index })} + /> +
+
+
+ ))} + + + )} + + ); +} + +export default ApplicationDetailsActionBar; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsContent.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsContent.js new file mode 100644 index 00000000..5596d7b6 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsContent.js @@ -0,0 +1,484 @@ +import { + BreakLine, + Card, + CardSectionHeader, + CardSubHeader, + CheckPoint, + CollapseAndExpandGroups, + ConnectingCheckPoints, + ViewImages, + Loader, + Row, + StatusTable, + Table, +} from "@egovernments/digit-ui-react-components"; +import { values } from "lodash"; +import React, { Fragment, useCallback, useReducer, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; +import BPADocuments from "./BPADocuments"; +import InspectionReport from "./InspectionReport"; +import NOCDocuments from "./NOCDocuments"; +import PermissionCheck from "./PermissionCheck"; +import PropertyDocuments from "./PropertyDocuments"; +import PropertyEstimates from "./PropertyEstimates"; +import PropertyFloors from "./PropertyFloors"; +import PropertyOwners from "./PropertyOwners"; +import ScruntinyDetails from "./ScruntinyDetails"; +import SubOccupancyTable from "./SubOccupancyTable"; +import TLCaption from "./TLCaption"; +import TLTradeAccessories from "./TLTradeAccessories"; +import TLTradeUnits from "./TLTradeUnits"; +//import WSAdditonalDetails from "./WSAdditonalDetails"; +import WSFeeEstimation from "./WSFeeEstimation"; +//import WSInfoLabel from "../../../ws/src/pageComponents/WSInfoLabel"; +import DocumentsPreview from "./DocumentsPreview"; +import InfoDetails from "./InfoDetails"; +import ViewBreakup from "./ViewBreakup"; +import SubWorkTableDetails from "./SubWorkTableDetails"; + + + +function ApplicationDetailsContent({ + applicationDetails, + workflowDetails, + isDataLoading, + applicationData, + businessService, + timelineStatusPrefix, + showTimeLine = true, + statusAttribute = "status", + paymentsList, + oldValue, + isInfoLabel = false, + noBoxShadow = false, + sectionHeadStyle = false, + modify, + setSaveAttendanceState +}) { + const { t } = useTranslation(); + const [localSearchParams, setLocalSearchParams] = useState(() => ({})); + + + const handleDateRangeChange = useCallback((data) => { + setLocalSearchParams(() => ({ ...data })); + }, []); + + function OpenImage(imageSource, index, thumbnailsToShow) { + window.open(thumbnailsToShow?.fullImage?.[0], "_blank"); + } + + const convertEpochToDateDMY = (dateEpoch) => { + if (dateEpoch == null || dateEpoch == undefined || dateEpoch == "") { + return "NA"; + } + const dateFromApi = new Date(dateEpoch); + let month = dateFromApi.getMonth() + 1; + let day = dateFromApi.getDate(); + let year = dateFromApi.getFullYear(); + month = (month > 9 ? "" : "0") + month; + day = (day > 9 ? "" : "0") + day; + return `${day}/${month}/${year}`; + }; + const getTimelineCaptions = (checkpoint) => { + if (checkpoint.state === "OPEN" || (checkpoint.status === "INITIATED" && !window.location.href.includes("/obps/"))) { + const caption = { + date: convertEpochToDateDMY(applicationData?.auditDetails?.createdTime), + source: applicationData?.channel || "", + }; + return ; + } else if (window.location.href.includes("/obps/") || window.location.href.includes("/noc/") || window.location.href.includes("/ws/")) { + //From BE side assigneeMobileNumber is masked/unmasked with connectionHoldersMobileNumber and not assigneeMobileNumber + const privacy = { uuid: checkpoint?.assignes?.[0]?.uuid, fieldName: ["connectionHoldersMobileNumber"], model: "WaterConnectionOwner" }; + const caption = { + date: checkpoint?.auditDetails?.lastModified, + name: checkpoint?.assignes?.[0]?.name, + mobileNumber: + applicationData?.processInstance?.assignes?.[0]?.uuid === checkpoint?.assignes?.[0]?.uuid && + applicationData?.processInstance?.assignes?.[0]?.mobileNumber + ? applicationData?.processInstance?.assignes?.[0]?.mobileNumber + : checkpoint?.assignes?.[0]?.mobileNumber, + comment: t(checkpoint?.comment), + wfComment: checkpoint.wfComment, + thumbnailsToShow: checkpoint?.thumbnailsToShow, + }; + return ; + } else { + const caption = { + date: `${Digit.DateUtils?.ConvertTimestampToDate(checkpoint.auditDetails.lastModifiedEpoch)} ${Digit.DateUtils?.ConvertEpochToTimeInHours( + checkpoint.auditDetails.lastModifiedEpoch + )} ${Digit.DateUtils?.getDayfromTimeStamp(checkpoint.auditDetails.lastModifiedEpoch)}`, + // name: checkpoint?.assigner?.name, + name: checkpoint?.assignes?.[0]?.name, + // mobileNumber: checkpoint?.assigner?.mobileNumber, + wfComment: checkpoint?.wfComment, + mobileNumber: checkpoint?.assignes?.[0]?.mobileNumber, + }; + + return ; + } + }; + + const getTranslatedValues = (dataValue, isNotTranslated) => { + if (dataValue) { + return !isNotTranslated ? t(dataValue) : dataValue; + } else { + return t("NA"); + } + }; + + const checkLocation = + window.location.href.includes("employee/tl") || window.location.href.includes("employee/obps") || window.location.href.includes("employee/noc"); + const isNocLocation = window.location.href.includes("employee/noc"); + const isBPALocation = window.location.href.includes("employee/obps"); + let isWS = window.location.href.includes("employee/ws") || window.location.href.includes("employee/works")|| window.location.href.includes("employee/project") || window.location.href.includes("employee/estimate") ; + + + + const getRowStyles = (tab="") => { + + if (window.location.href.includes("employee/obps") || window.location.href.includes("employee/noc")) { + return { justifyContent: "space-between", fontSize: "16px", lineHeight: "19px", color: "#0B0C0C" }; + } else if (checkLocation) { + return { justifyContent: "space-between", fontSize: "16px", lineHeight: "19px", color: "#0B0C0C" }; + } + else if ( tab==="fieldSurvey") { + return { + justifyContent: "space-between", flexDirection:"column" + } + } + else { + return {}; + } + + }; + const getTextStyles = (tab="") => { + if ( tab==="fieldSurvey" ) { + return { + marginTop:"1rem", + marginBottom:"1rem" + } + } + else { + return {}; + } + + }; + const getLabelStyles = (tab = "") => { + if ( tab === "fieldSurvey") { + return { + width:"100%" + } + } + else { + return {}; + } + + }; + + const getTableStyles = () => { + if (window.location.href.includes("employee/obps") || window.location.href.includes("employee/noc")) { + return { position: "relative", marginTop: "19px" }; + } else if (checkLocation) { + return { position: "relative", marginTop: "19px" }; + } else { + return {}; + } + }; + + const getMainDivStyles = () => { + if ( + window.location.href.includes("employee/obps") || + window.location.href.includes("employee/noc") || + window.location.href.includes("employee/ws") || + window.location.href.includes("employee/works") || + window.location.href.includes("employee/contracts") + ) { + return { lineHeight: "19px", maxWidth: "950px", minWidth: "280px" }; + } else if (checkLocation) { + return { lineHeight: "19px", maxWidth: "600px", minWidth: "280px" }; + } else { + return {}; + } + }; + + const getTextValue = (value) => { + if (value?.skip) return value.value; + else if (value?.isUnit) return value?.value ? `${getTranslatedValues(value?.value, value?.isNotTranslated)} ${t(value?.isUnit)}` : t("N/A"); + else if (value?.value === "Approved") return { `${getTranslatedValues(value?.value, value?.isNotTranslated)}`} + else if (value?.value === "Rejected") return {t(value?.value)} + else return value?.value ? getTranslatedValues(value?.value, value?.isNotTranslated) : t("N/A"); + }; + + const getClickInfoDetails = () => { + if (window.location.href.includes("disconnection") || window.location.href.includes("application")) { + return "WS_DISCONNECTION_CLICK_ON_INFO_LABEL"; + } else { + return "WS_CLICK_ON_INFO_LABEL"; + } + }; + + const getClickInfoDetails1 = () => { + if (window.location.href.includes("disconnection") || window.location.href.includes("application")) { + return "WS_DISCONNECTION_CLICK_ON_INFO1_LABEL"; + } else { + return ""; + } + }; + + const getCardStyles = () => { + let styles = { position: "relative" } + if (noBoxShadow) styles = { ...styles, boxShadow: "none" }; + return styles; + }; + + return ( + + + {isInfoLabel ? ( + + ) : null} + {applicationDetails?.applicationDetails?.map((detail, index) => ( + + +
+ {index === 0 && !detail.asSectionHeader ? ( + {t(detail.title)} + ) : ( + + + {isNocLocation ? `${t(detail.title)}` : t(detail.title)} + {detail?.Component ? : null} + + + )} + {/* TODO, Later will move to classes */} + {/* Here Render the table for adjustment amount details detail.isTable is true for that table*/} + {/* {detail?.isTable && ( + + + {detail?.headers.map((header) => ( + + ))} + + + {detail?.tableRows.map((row,index)=>{ + if(index===detail?.tableRows.length - 1){ + return <> +
+ + {row.map(element => )} + + + } + return + {row.map(element => )} + })} +
{t(header)}
{t(element)}
{t(element)}
+ )} */} + {detail?.isTable && } + + + {detail?.title && + !detail?.title.includes("NOC") && + detail?.values?.map((value, index) => { + if (value.map === true && value.value !== "N/A") { + return } />; + } + if (value?.isLink == true) { + return ( + + + + {t(value?.title)} + + +
+ ) : isNocLocation || isBPALocation ? ( + `${t(value.title)}` + ) : ( + t(value.title) + ) + } + text={ +
+ + + {value?.value} + + +
+ } + last={index === detail?.values?.length - 1} + caption={value.caption} + className="border-none" + rowContainerStyle={getRowStyles()} + /> + ); + } + return ( + { }} />: getTextValue(value)} + last={index === detail?.values?.length - 1} + caption={value.caption} + className="border-none" + /* privacy object set to the Row Component */ + privacy={value?.privacy} + // TODO, Later will move to classes + rowContainerStyle={getRowStyles(detail?.tab)} + textStyle={getTextStyles(detail?.tab)} + labelStyle={getLabelStyles(detail?.tab)} + /> + ); + })} + + + + + {detail?.additionalDetails?.table + ? detail?.additionalDetails?.table?.weekTable?.tableHeader && ( + <> + + {t(detail?.additionalDetails?.table?.weekTable?.tableHeader)} + + + ) + : null} + + {detail?.additionalDetails?.inspectionReport && ( + + )} + {applicationDetails?.applicationData?.additionalDetails?.fieldinspection_pending?.length > 0 && detail?.additionalDetails?.fiReport && ( + + )} + {/* {detail?.additionalDetails?.FIdocuments && detail?.additionalDetails?.values?.map((doc,index) => ( +
+ {doc.isNotDuplicate &&
+ + + +
+
+
} +
+ )) } */} + {detail?.additionalDetails?.floors && } + {detail?.additionalDetails?.owners && } + {detail?.additionalDetails?.units && } + {detail?.additionalDetails?.accessories && } + {detail?.additionalDetails?.permissions && workflowDetails?.data?.nextActions?.length > 0 && ( + + )} + {detail?.additionalDetails?.obpsDocuments && ( + + )} + {detail?.additionalDetails?.noc && ( + + )} + {detail?.additionalDetails?.scruntinyDetails && } + {detail?.additionalDetails?.buildingExtractionDetails && } + {detail?.additionalDetails?.subOccupancyTableDetails && ( + + )} + {detail?.additionalDetails?.documentsWithUrl && } + {detail?.additionalDetails?.documents && } + {detail?.additionalDetails?.taxHeadEstimatesCalculation && ( + + )} + {/* {detail?.isWaterConnectionDetails && } */} + {detail?.additionalDetails?.redirectUrl && ( +
+ + + {detail?.additionalDetails?.redirectUrl?.title} + + +
+ )} + {detail?.additionalDetails?.estimationDetails && } + {detail?.additionalDetails?.estimationDetails && } +
+
+ ))} + {showTimeLine && workflowDetails?.data?.timeline?.length > 0 && ( + + {workflowDetails?.breakLineRequired === undefined ? : workflowDetails?.breakLineRequired ? : null} + {(workflowDetails?.isLoading || isDataLoading) && } + {!workflowDetails?.isLoading && !isDataLoading && ( + + + {/* {t("ES_APPLICATION_DETAILS_APPLICATION_TIMELINE")} */} + {t("WORKS_WORKFLOW_HISTORY")} + + {workflowDetails?.data?.timeline && workflowDetails?.data?.timeline?.length === 1 ? ( + + ) : ( + + {workflowDetails?.data?.timeline && + workflowDetails?.data?.timeline.map((checkpoint, index, arr) => { + return ( + + + + ); + })} + + )} + + )} + + )} +
+
+ ); +} + +export default ApplicationDetailsContent; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsToast.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsToast.js new file mode 100644 index 00000000..9540495f --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsToast.js @@ -0,0 +1,74 @@ +import React from "react"; +import { Toast } from "@egovernments/digit-ui-react-components"; + +function ApplicationDetailsToast({ t, showToast, closeToast, businessService }) { + if (businessService?.includes("NewTL") || businessService?.includes("TL") || businessService?.includes("EDITRENEWAL")) { + let label = ""; + switch (showToast?.action?.action) { + case "SENDBACK": + label = showToast?.key === "error" ? showToast?.error?.message : t("TL_SENDBACK_CHECKLIST_MESSAGE_HEAD"); + break; + case "FORWARD": + label = showToast?.key === "error" ? showToast?.error?.message : t("TL_FORWARD_SUCCESS_MESSAGE_MAIN"); + break; + case "APPROVE": + label = showToast?.key === "error" ? showToast?.error?.message : t("TL_APPROVAL_CHECKLIST_MESSAGE_HEAD"); + break; + case "SENDBACKTOCITIZEN": + label = showToast?.key === "error" ? showToast?.error?.message : t("TL_SENDBACK_TOCITIZEN_CHECKLIST_MESSAGE_HEAD"); + break; + case "REJECT": + label = showToast?.key === "error" ? showToast?.error?.message : t("TL_APPROVAL_REJ_MESSAGE_HEAD"); + break; + case "RESUBMIT": + label = showToast?.key === "error" ? showToast?.error?.message : t("TL_APPLICATION_RESUBMIT_SUCCESS_MESSAGE_MAIN"); + break; + case "CANCEL": + label = showToast?.key === "error" ? showToast?.error?.message : t("TL_TL_CANCELLED_MESSAGE_HEAD"); + break; + default: + label = showToast?.key === "error" ? showToast?.error?.message : t(`ES_${businessService}_${showToast?.action?.action}_UPDATE_SUCCESS`); + } + return {showToast && }; + } else if (businessService?.includes("BPA") || businessService?.includes("BPA_LOW") || businessService?.includes("BPA_OC")) { + const getMessage = (messages = []) => { + let returnValue = messages[0]; + if(messages?.length == 2) returnValue = businessService?.includes("BPA_OC") ? t(messages[1]) : t(messages [0]); + else returnValue = t(messages[0]); + return returnValue; + } + let label = ""; + switch (showToast?.action?.action) { + case "REVOCATE": + label = showToast?.key === "error" ? showToast?.error?.message : getMessage(["BPA_APPROVAL_REVOCATED_MESSAGE_HEAD", "BPA_APPROVAL_OC_REVOCATED_MESSAGE_HEAD"]); + break; + case "VERIFY_AND_FORWARD": + label = showToast?.key === "error" ? showToast?.error?.message : getMessage(["BPA_FORWARD_SUCCESS_MESSAGE_MAIN"]); + break; + case "SEND_BACK_TO_CITIZEN": + label = showToast?.key === "error" ? showToast?.error?.message : getMessage(["BPA_SENDBACK_SUCCESS_MESSAGE_MAIN"]); + break; + case "APPROVE": + label = showToast?.key === "error" ? showToast?.error?.message : getMessage(["BPA_APPROVAL_CHECKLIST_MESSAGE_HEAD"]); + break; + case "REJECT": + label = showToast?.key === "error" ? showToast?.error?.message : getMessage(["BPA_APPROVAL_REJECTED_MESSAGE_HEAD", "BPA_OC_APPROVAL_REJECTED_MESSAGE_HEAD"]); + break; + case "FORWARD": + label = showToast?.key === "error" ? showToast?.error?.message : getMessage(["BPA_FORWARD_SUCCESS_MESSAGE_MAIN"]); + break; + case "SEND_BACK_FOR_DOCUMENT_VERIFICATION": + case "SEND_BACK_FOR_FIELD_INSPECTION": + label = showToast?.key === "error" ? showToast?.error?.message : getMessage(["BPA_SENDBACK_SUCCESS_MESSAGE_MAIN"]); + break; + default: + label = showToast?.key === "error" ? showToast?.error?.message : t(`ES_${businessService}_${showToast?.action?.action}_UPDATE_SUCCESS`); + } + return {showToast && }; + } else { + const label = showToast?.key === "error" ? showToast?.error?.message : `ES_${businessService}_${showToast?.action?.action}_UPDATE_SUCCESS`; + return {showToast && }; + } +} + +export default ApplicationDetailsToast; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsWarningPopup.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsWarningPopup.js new file mode 100644 index 00000000..e95b9e03 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ApplicationDetailsWarningPopup.js @@ -0,0 +1,54 @@ +import { Card, ButtonSelector, CardText, CardSubHeader, Modal, CardSectionHeader, Row } from "@egovernments/digit-ui-react-components"; +import React from "react"; +import { useTranslation } from "react-i18next"; + +const Close = () => ( + + + + + ); + +const CloseBtn = (props) => { + return ( +
+ +
+ ); + }; + +function ApplicationDetailsWarningPopup({ action,workflowDetails,businessService,isWarningPop,closeWarningPopup }) { +const { t } = useTranslation(); +const isMobile = window.Digit.Utils.browser.isMobile(); +return ( + + {t("PT_DUES_ARE_PENDING")}} + headerBarEnd={ + { + closeWarningPopup(); + }} + /> + } + hideSubmit={true} + isDisabled={false} + popupStyles={isMobile ? {} : { width: "29%", marginTop: "auto" }} + > + +
+

{t("PT_YOU_HAVE")} ₹{action?.AmountDueForPay} {t("PT_DUE_WARNING_MSG2")}

+
+ +
+ + window.location.assign(`${window.location.origin}${action?.redirectionUrl?.pathname}`)} style={{ marginLeft: "10px" }} /> +
+
+
+ ) +
+) +} + +export default ApplicationDetailsWarningPopup; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/BPADocuments.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/BPADocuments.js new file mode 100644 index 00000000..9a1febe0 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/BPADocuments.js @@ -0,0 +1,234 @@ +import React, { useEffect, useState } from "react"; +import { + CardLabel, + Dropdown, + LabelFieldPair, + MultiUploadWrapper, + CardSubHeader +} from "@egovernments/digit-ui-react-components"; +import DocumentsPreview from "./DocumentsPreview"; + +const BPADocuments = ({ t, formData, applicationData, docs, bpaActionsDetails }) => { + const applicationStatus = applicationData?.status || ""; + const actions = bpaActionsDetails?.data?.nextActions || []; + const stateId = Digit.ULBService.getStateId(); + const [documents, setDocuments] = useState(formData?.documents?.documents || []); + const [error, setError] = useState(null); + const [bpaTaxDocuments, setBpaTaxDocuments] = useState([]); + const [enableSubmit, setEnableSubmit] = useState(true) + const [checkRequiredFields, setCheckRequiredFields] = useState(false); + const [checkEnablingDocs, setCheckEnablingDocs] = useState(false); + + const { isLoading: bpaDocsLoading, data: bpaDocs } = Digit.Hooks.obps.useMDMS(stateId, "BPA", ["DocTypeMapping"]); + const { isLoading: commonDocsLoading, data: commonDocs } = Digit.Hooks.obps.useMDMS(stateId, "common-masters", ["DocumentType"]); + + useEffect(() => { + let filtredBpaDocs = []; + if (bpaDocs?.BPA?.DocTypeMapping) { + // filtredBpaDocs = bpaDocs?.BPA?.DocTypeMapping?.filter(data => (data.WFState == "INPROGRESS")) + filtredBpaDocs = bpaDocs?.BPA?.DocTypeMapping?.filter(data => (data.WFState == applicationData?.status ? applicationData?.status : "INPROGRESS" && data.RiskType == applicationData?.riskType && data.ServiceType == applicationData?.additionalDetails?.serviceType && data.applicationType == applicationData?.additionalDetails?.applicationType)) + } + let documentsList = []; + filtredBpaDocs?.[0]?.docTypes?.forEach(doc => { + let code = doc.code; doc.dropdownData = []; doc.uploadedDocuments = []; + commonDocs?.["common-masters"]?.DocumentType?.forEach(value => { + let values = value.code.slice(0, code.length); + if (code === values) { + doc.hasDropdown = true; + value.i18nKey = value.code; + doc.dropdownData.push(value); + } + }); + doc.uploadedDocuments[0] = {}; + doc.uploadedDocuments[0].values = []; + docs?.[0]?.values?.map(upDocs => { + if (code === `${upDocs?.documentType?.split('.')[0]}.${upDocs?.documentType?.split('.')[1]}`) { + doc.uploadedDocuments[0].values.push(upDocs) + } + }) + documentsList.push(doc); + }); + sessionStorage.setItem("BPA_DOCUMENTS", JSON.stringify(documentsList)); + setBpaTaxDocuments(documentsList); + + }, [!bpaDocsLoading, !commonDocsLoading]); + + useEffect(() => { + let count = 0; + bpaTaxDocuments.map(doc => { + let isRequired = false; + documents.map(data => { + if (doc.required && doc.code == `${data.documentType.split('.')[0]}.${data.documentType.split('.')[1]}`) { + isRequired = true; + } + }); + if (!isRequired && doc.required) { + count = count + 1; + } + }); + if ((count == "0" || count == 0) && documents.length > 0) setEnableSubmit(false); + else setEnableSubmit(true); + }, [documents, checkRequiredFields]) + + useEffect(() => { + if ( applicationStatus === "DOC_VERIFICATION_INPROGRESS" && actions?.length > 0 ) setCheckEnablingDocs(true); + else setCheckEnablingDocs(false); + }, [applicationData, bpaActionsDetails]) + + return ( +
+ {bpaTaxDocuments?.map((document, index) => { + return ( +
+ +
+ ); + })} +
+ ); +} + +function SelectDocument({ + t, + document: doc, + setDocuments, + error, + setError, + documents, + setCheckRequiredFields, + index, + applicationStatus, + actions, + bpaTaxDocuments, + checkEnablingDocs +}) { + + const filteredDocument = documents?.filter((item) => item?.documentType?.includes(doc?.code))[0]; + const tenantId = Digit.ULBService.getStateId(); + const [selectedDocument, setSelectedDocument] = useState( + filteredDocument + ? { ...filteredDocument, active: true, code: filteredDocument?.documentType, i18nKey: filteredDocument?.documentType } + : doc?.dropdownData?.length === 1 + ? doc?.dropdownData[0] + : {} + ); + const [file, setFile] = useState(null); + const [uploadedFile, setUploadedFile] = useState(() => filteredDocument?.fileStoreId || null); + const [selectArrayFiles, SetSelectArrayFiles] = useState([]); + const handleSelectDocument = (value) => setSelectedDocument(value); + const allowedFileTypes = /(.*?)(jpg|jpeg|png|image|pdf)$/i; + + function selectfiles(e) { + e && setFile(e.file); + } + + + useEffect(() => { + if (selectedDocument?.code) { + setDocuments((prev) => { + const filteredDocumentsByDocumentType = prev?.filter((item) => item?.documentType !== selectedDocument?.code); + if (uploadedFile?.length === 0 || uploadedFile === null) return filteredDocumentsByDocumentType; + const filteredDocumentsByFileStoreId = filteredDocumentsByDocumentType?.filter((item) => item?.fileStoreId !== uploadedFile); + return [ + ...filteredDocumentsByFileStoreId, + { + documentType: selectedDocument?.code, + fileStoreId: uploadedFile, + documentUid: uploadedFile, + fileName: file?.name || "", + id: documents ? documents.find(x => x.documentType === selectedDocument?.code)?.id : undefined, + }, + ]; + }); + } + }, [uploadedFile, selectedDocument]); + + useEffect(() => { + (async () => { + if (selectArrayFiles.length > 0) { + sessionStorage.removeItem("BPA_DOCUMENTS"); + doc.newUploadedDocs = []; + selectArrayFiles.map(newDoc => { + if (selectedDocument?.code) { + doc.newUploadedDocs.push({ + documentType: selectedDocument?.code, + fileStoreId: newDoc?.fileStoreId?.fileStoreId, + documentUid: newDoc?.fileStoreId?.fileStoreId, + tenantId: newDoc?.fileStoreId?.tenantId + }); + } + }) + bpaTaxDocuments[index] = doc; + sessionStorage.setItem("BPA_DOCUMENTS", JSON.stringify(bpaTaxDocuments)); + } + })(); + }, [selectArrayFiles, selectedDocument]); + + useEffect(() => { + (async () => { + + })(); + }, [file]); + + const getData = (index, state) => { + let data = Object.fromEntries(state); + let newArr = Object.values(data); + if (Object.keys(data).length !== 0) SetSelectArrayFiles(newArr); + selectfiles(newArr[newArr.length - 1]); + } + + return ( +
+ {`${t(doc?.code)}`} + {doc?.uploadedDocuments?.length && } + { + checkEnablingDocs ? +
+ + {doc?.required ? `${t(doc?.code)}* ` : `${t(doc?.code)}`} + + + + +
+ getData(index, e)} + t={t} + allowedFileTypesRegex={allowedFileTypes} + allowedMaxSizeInMB={5} + acceptFiles= "image/*, .pdf, .png, .jpeg, .jpg" + /> +
+
+
: null + } +
+ ); +} + +export default BPADocuments; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/DocumentsPreview.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/DocumentsPreview.js new file mode 100644 index 00000000..dfd57683 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/DocumentsPreview.js @@ -0,0 +1,49 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { CardSubHeader, PDFSvg } from "@egovernments/digit-ui-react-components"; + +function DocumentsPreview({ documents, svgStyles = {}, isSendBackFlow = false, isHrLine = false, titleStyles }) { + const { t } = useTranslation(); + const isStakeholderApplication = window.location.href.includes("stakeholder"); + + return ( +
+ {!isStakeholderApplication && documents?.map((document, index) => ( + + {document?.title ? {t(document?.title)} : null} +
+ {document?.values && document?.values.length > 0 ? document?.values?.map((value, index) => ( + +
+ +
+

{t(value?.title)}

+ {isSendBackFlow ? value?.documentType?.includes("NOC") ?

{t(value?.documentType.split(".")[1])}

:

{t(value?.documentType)}

: ""} +
+ )) : !(window.location.href.includes("citizen")) &&

{t("BPA_NO_DOCUMENTS_UPLOADED_LABEL")}

} +
+ {isHrLine && documents?.length != index + 1 ?
: null} +
+ ))} + {isStakeholderApplication && documents?.map((document, index) => ( + + {document?.title ? {t(document?.title)} : null} +
+ {document?.values && document?.values.length > 0 ? document?.values?.map((value, index) => ( + +
+

{t(value?.title)}

+ {value?.docInfo ?
{`${t(value?.docInfo)}`}
: null} + +

{`${t(value?.title)}`}

+
+
+ )) : !(window.location.href.includes("citizen")) &&

{t("BPA_NO_DOCUMENTS_UPLOADED_LABEL")}

} +
+
+ ))} +
+ ); +} + +export default DocumentsPreview; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/InfoDetails.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/InfoDetails.js new file mode 100644 index 00000000..12e2f64f --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/InfoDetails.js @@ -0,0 +1,34 @@ +import React from "react"; +import { InfoBannerIcon } from "@egovernments/digit-ui-react-components"; + +const EyeSvgINdex = ({ style }) => { + return + + + + + +} +const InfoDetails = ({ t, userType = false, infoBannerLabel = "", infoClickLable = "", infoClickInfoLabel = "", infoClickInfoLabel1 = "" }) => { + userType = userType || Digit.SessionStorage.get("userType"); + return ( + +
+
+
+ +

{t(infoBannerLabel)}

+
+ {`${t(infoClickLable)} `} + + {` ${t(infoClickInfoLabel)}`} +
+ {` ${t(infoClickInfoLabel1)}`} +
+
+
+
+ ); +}; + +export default InfoDetails; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/InspectionReport.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/InspectionReport.js new file mode 100644 index 00000000..a824b05a --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/InspectionReport.js @@ -0,0 +1,49 @@ +import { StatusTable, Row, CardHeader, CardSectionHeader } from "@egovernments/digit-ui-react-components"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import DocumentsPreview from "./DocumentsPreview"; + +const getDocuments = (fiDocuments) => { + const returnDocuments = [{ + title: "BPA_DOCUMENT_DETAILS_LABEL", + values: fiDocuments?.map(doc => ({ + title: doc?.documentType?.replaceAll('.', '_'), + documentType: doc?.documentType, + documentUid: doc?.documentUid, + fileStoreId: doc?.fileStoreId, + id: doc?.id, + url: doc?.url + })) + }]; + return returnDocuments; +}; + +function InspectionReport({ fiReport, isCitizen=false }) { + const { t } = useTranslation(); + + return ( + +
+ {isCitizen?{`${t(`BPA_FI_REPORT`)}`}: + {`${t(`BPA_FI_REPORT`)}`}} + {fiReport.map((fiData, index) => +
+ + {fiReport?.length == 1 ? `${t(`BPA_FI_REPORT`)}` : `${t(`BPA_FI_REPORT`)} - ${index + 1}`} + + + {fiData?.questions?.length && + fiData?.questions?.map((qstn) => +
+ + +
)} + +
+
)} +
+
+ ); +} + +export default InspectionReport; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/NOCDocuments.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/NOCDocuments.js new file mode 100644 index 00000000..1581744f --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/NOCDocuments.js @@ -0,0 +1,202 @@ +import React, { useEffect, useState } from "react"; +import { + CardLabel, + MultiUploadWrapper, + StatusTable, + Row, + LabelFieldPair +} from "@egovernments/digit-ui-react-components"; +import DocumentsPreview from "./DocumentsPreview"; + +function SelectDocument({ + t, + document: doc, + setNocDocuments, + setError, + nocDocuments +}) { + const filteredDocument = nocDocuments?.filter((item) => item?.documentType?.includes(doc?.code))[0]; + const tenantId = Digit.ULBService.getStateId(); + const [selectedDocument, setSelectedDocument] = useState(); + const [file, setFile] = useState(null); + const [uploadedFile, setUploadedFile] = useState(() => filteredDocument?.fileStoreId || null); + const handleSelectDocument = (value) => setSelectedDocument(value); + const allowedFileTypes = /(.*?)(jpg|jpeg|png|image|pdf)$/i; + + function selectfile(e) { + e && setFile(e.file); + } + + useEffect(() => { + if (doc?.dropdownData?.[0]?.code) { + setNocDocuments((prev) => { + const filteredDocumentsByDocumentType = prev?.filter((item) => item?.documentType !== doc?.dropdownData?.[0]?.code); + + if (uploadedFile?.length === 0 || uploadedFile === null) { + return filteredDocumentsByDocumentType; + } + + const filteredDocumentsByFileStoreId = filteredDocumentsByDocumentType?.filter((item) => item?.fileStoreId !== uploadedFile); + return [ + ...filteredDocumentsByFileStoreId, + { + documentType: doc?.dropdownData?.[0].code, + fileStoreId: uploadedFile, + documentUid: uploadedFile, + fileName: file?.name || "", + }, + ]; + }); + } + }, [uploadedFile]); + + + useEffect(() => { + (async () => { + setError(null); + if (file) { + const allowedFileTypesRegex = /(.*?)(jpg|jpeg|png|image|pdf)$/i + if (file.size >= 5242880) { + setError(t("CS_MAXIMUM_UPLOAD_SIZE_EXCEEDED")); + } else if (file?.type && !allowedFileTypesRegex.test(file?.type)) { + setError(t(`NOT_SUPPORTED_FILE_TYPE`)) + } else { + try { + setUploadedFile(null); + const response = await Digit.UploadServices.Filestorage("PT", file, Digit.ULBService.getStateId()); + 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 getData =(state) => { + let data = Object.fromEntries(state); + let newArr = Object.values(data); + selectfile(newArr[newArr.length-1]); + } + + return ( +
+ + {doc?.required ? `${t("TL_BUTTON_UPLOAD FILE")}*` : `${t("TL_BUTTON_UPLOAD FILE")}`} +
+ getData(e)} + t={t} + allowedFileTypesRegex={allowedFileTypes} + allowedMaxSizeInMB={5} + acceptFiles="image/*, .pdf, .png, .jpeg, .jpg" + /> +
+
+
+ ); +} +const NOCDocuments = ({ t, noc, docs, isNoc, applicationData,NOCdata, bpaActionsDetails }) => { + const tenantId = Digit.ULBService.getStateId(); + const stateId = Digit.ULBService.getStateId(); + const bpaApplicationStatus = applicationData?.status || ""; + const actions = bpaActionsDetails?.data?.nextActions || []; + const { isLoading: nocDocsLoading, data: nocDocs } = Digit.Hooks.obps.useMDMS(stateId, "NOC", ["DocumentTypeMapping"], { enabled: isNoc }); + const { isLoading: bpaDocsLoading, data: bpaDocs } = Digit.Hooks.obps.useMDMS(stateId, "BPA", ["DocTypeMapping"], { enabled: !isNoc }); + const { isLoading: commonDocsLoading, data: commonDocs } = Digit.Hooks.obps.useMDMS(stateId, "common-masters", ["DocumentType"]); + const [commonDocMaping, setCommonDocMaping] = useState([]); + const [nocTaxDocuments, setNocTaxDocuments] = useState([]); + const [checkEnablingDocs, setCheckEnablingDocs] = useState(false); + const [nocDocuments, setNocDocuments] = Digit.Hooks.useSessionStorage(noc?.nocType, []); + const [error, setError] = useState(null); + const isEmployee = window.location.href.includes("/employee/") + + useEffect(() => { + setCommonDocMaping(commonDocs?.["common-masters"]?.DocumentType); + }, [commonDocs]); + + useEffect(() => { + let documents = []; + let filteredData + if (isNoc) { + filteredData = nocDocs?.NOC?.DocumentTypeMapping?.filter((data => { + return data?.applicationType === noc?.applicationType && data?.nocType === noc?.nocType + })); + } + else { + filteredData = bpaDocs?.BPA?.DocTypeMapping?.filter(data => (data.WFState == applicationData?.status && data.RiskType == applicationData?.riskType && data.ServiceType == applicationData?.additionalDetails?.serviceType && data.applicationType == applicationData?.additionalDetails?.applicationType)) + } + if (filteredData?.[0]?.docTypes?.[0]) { + filteredData[0].docTypes[0].nocType = filteredData[0].nocType; + filteredData[0].docTypes[0].additionalDetails = { + submissionDetails: noc?.additionalDetails, + applicationStatus: noc?.applicationStatus, + appNumberLink: noc?.applicationNo, + nocNo: noc?.nocNo + } + documents.push(filteredData[0].docTypes[0]); + } + let documentsList = []; + if (documents && documents.length > 0) { + documents.map((doc) => { + let code = doc.documentType; + let nocType = doc.nocType; + doc.dropdownData = []; + commonDocMaping?.forEach((value) => { + let values = value.code.slice(0, code?.length); + if (code === values) { + doc.hasDropdown = true; + doc.dropdownData.push(value); + } + }); + documentsList.push(doc); + }); + setNocTaxDocuments(documentsList); + } + }, [nocDocs, commonDocMaping]); + + useEffect(() => { + if (bpaApplicationStatus === 'NOC_VERIFICATION_INPROGRESS' && actions?.length > 0) setCheckEnablingDocs(true); + else setCheckEnablingDocs(false); + }, [applicationData, bpaActionsDetails]) + + return ( +
+ + + {NOCdata && NOCdata.map((noc,index) => { + if (noc?.value) { + if (noc?.field == "STATUS") { + return + } else { + return + } + } + })} + + + {checkEnablingDocs && nocTaxDocuments?.map((document, index) => { + return ( + + ); + })} +
+ ); +} + +export default NOCDocuments; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PermissionCheck.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PermissionCheck.js new file mode 100644 index 00000000..89007789 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PermissionCheck.js @@ -0,0 +1,87 @@ +import { CheckBox, LinkButton, TextInput,Close, CardSubHeader } from "@egovernments/digit-ui-react-components"; +import React, { useEffect, useState } from "react"; + +const PermissionCheck = ({ permissions, t }) => { + const [approvalChecks, setApprovalChecks, clearApprovals] = Digit.Hooks.useSessionStorage("OBPS_APPROVAL_CHECKS", permissions?.map(permission => ({ label: permission, checked: false }))); //useState(() => permissions?.map(permission => ({ label: permission, checked: false }))) + const [newApprovals, setNewApprovals, clearNewApprovals] = Digit.Hooks.useSessionStorage('OBPS_NEW_APPROVALS', []); + + useEffect(() => { + return () => { + Digit.SessionStorage.del("OBPS_NEW_APPROVALS"); + Digit.SessionStorage.del("OBPS_APPROVAL_CHECKS"); + } + }, []) + + const handleAdd = () => { + setNewApprovals([...newApprovals, { label: '' }]); + } + + const handleRemove = (index) => { + const values = [...newApprovals]; + values.splice(index, 1); + setNewApprovals([...values]); + } + + const handleChange = (event, index) => { + setNewApprovals(() => { + return newApprovals?.map((approval, id) => { + if (index === id) { + return { + label: event?.target?.value, + } + } + return approval; + }) + }) + } + + const handleCheck = (event, label, index) => { + const isChecked = event.target.checked; + setApprovalChecks(() => { + return approvalChecks?.map((approval, id) => { + if (index === id) { + return { + ...approval, + checked: isChecked + } + } + return approval; + }) + }) + } + + return ( +
+ {t("BPA_PERMIT_CONDITIONS")} + {approvalChecks?.map((permission, index) => ( + handleCheck(event, permission?.label, index))} + isLabelFirst={true} + index={index} + /> + ))} + {newApprovals?.map((approval, index) => ( +
handleChange(event, index)} textInputStyle={{maxWidth: "830px", width: "830px"}} placeholder={"Enter permit conditions.........."} /> + { + + + +
+ } + style={{ }} + onClick={(e) => handleRemove(index)} + />} +
+ ))} + + + ) +} + +export default PermissionCheck; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyDocuments.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyDocuments.js new file mode 100644 index 00000000..ea8cd1eb --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyDocuments.js @@ -0,0 +1,83 @@ +import React, { useState, useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { CardSubHeader, PDFSvg } from "@egovernments/digit-ui-react-components"; + +// const PDFSvg = ({ width = 34, height = 34, style, viewBox = "0 0 34 34" }) => ( +// +// +// +// ); + +function PropertyDocuments({ documents, svgStyles = {}, isSendBackFlow=false }) { + const { t } = useTranslation(); + const [filesArray, setFilesArray] = useState(() => [] ); + const tenantId = Digit.ULBService.getCurrentTenantId(); + const [pdfFiles, setPdfFiles] = useState({}); + + useEffect(() => { + let acc = []; + documents?.forEach((element, index, array) => { + acc = [...acc, ...(element.values?element.values:[])]; + }); + setFilesArray(acc?.map((value) => value?.fileStoreId)); + }, [documents]); + + useEffect(() => { + if (filesArray?.length && documents?.[0]?.BS === "BillAmend") { + Digit.UploadServices.Filefetch(filesArray, Digit.ULBService.getCurrentTenantId()).then((res) => { + setPdfFiles(res?.data); + }); + } + else if(filesArray?.length) + { + Digit.UploadServices.Filefetch(filesArray, Digit.ULBService.getStateId()).then((res) => { + setPdfFiles(res?.data); + }); + } + + }, [filesArray]); + + const checkLocation = window.location.href.includes("employee/tl") || window.location.href.includes("/obps") || window.location.href.includes("employee/ws"); + const isStakeholderApplication = window.location.href.includes("stakeholder"); + + return ( +
+ {!isStakeholderApplication && documents?.map((document, index) => ( + + {document?.title ? {t(document?.title)}: null} +
+ {document?.values && document?.values.length>0 ? document?.values?.map((value, index) => ( + +
+ +
+

{t(value?.title)}

+ {isSendBackFlow? value?.documentType?.includes("NOC")?

{t(value?.documentType.split(".")[1])}

:

{t(value?.documentType)}

:""} +
+ )):!(window.location.href.includes("citizen"))&&

{t("BPA_NO_DOCUMENTS_UPLOADED_LABEL")}

} +
+
+ ))} + {isStakeholderApplication && documents?.map((document, index) => ( + + {document?.title ? {t(document?.title)} : null} +
+ {document?.values && document?.values.length>0 ? document?.values?.map((value, index) => ( + +
+

{t(value?.title)}

+ {value?.docInfo ?
{`${t(value?.docInfo)}`}
: null} + + {/*
{decodeURIComponent(pdfFiles[value.fileStoreId]?.split(",")[0].split("?")[0].split("/").pop().slice(13))}
*/} +

{`${t(value?.title)}`}

+
+
+ )):!(window.location.href.includes("citizen"))&&

{t("BPA_NO_DOCUMENTS_UPLOADED_LABEL")}

} +
+
+ ))} +
+ ); +} + +export default PropertyDocuments; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyEstimates.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyEstimates.js new file mode 100644 index 00000000..c4cde767 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyEstimates.js @@ -0,0 +1,39 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { StatusTable, Row, BreakLine } from "@egovernments/digit-ui-react-components"; + +function PropertyEstimates({ taxHeadEstimatesCalculation }) { + const { taxHeadEstimates } = taxHeadEstimatesCalculation; + const { t } = useTranslation(); + + return ( +
+ + + + {taxHeadEstimates?.map((estimate, index) => { + return ( + + ); + })} + + + +
+ ); +} + +export default PropertyEstimates; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyFloors.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyFloors.js new file mode 100644 index 00000000..4f33bbdc --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyFloors.js @@ -0,0 +1,49 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { CardSubHeader, StatusTable, Row, CardSectionHeader } from "@egovernments/digit-ui-react-components"; + +function PropertyFloors({ floors }) { + const { t } = useTranslation(); + + return ( + + {floors.map((floor) => ( +
+ {t(floor?.title)} + {floor?.values?.map((value, index) => { + return ( + + + {t(value.title)} + + +
+ {value?.values?.map((value, index) => { + if (value.map === true && value.value !== "N/A") { + return } />; + } + return ( + + ); + })} +
+
+
+ ); + })} +
+ ))} +
+ ); +} + +export default PropertyFloors; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyOwners.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyOwners.js new file mode 100644 index 00000000..dac9f41c --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/PropertyOwners.js @@ -0,0 +1,94 @@ +import { CardSubHeader, Row, StatusTable } from "@egovernments/digit-ui-react-components"; +import React from "react"; +import { useTranslation } from "react-i18next"; + +function PropertyOwners({ owners }) { + const { t } = useTranslation(); + + const checkLocation = true; + const checkOwnerLength = owners?.length || 1; + let cardStyles = { marginTop: "19px" }; + let statusTableStyles = { position: "relative", padding: "8px" }; + let rowContainerStyle = { justifyContent: "space-between", fontSize: "16px", lineHeight: "19px", color: "#0B0C0C" }; + if (checkLocation && Number(checkOwnerLength) > 1) { + cardStyles = { + marginTop: "19px", + background: "#FAFAFA", + border: "1px solid #D6D5D4", + borderRadius: "4px", + padding: "8px", + lineHeight: "19px", + maxWidth: "600px", + minWidth: "280px", + }; + } else if (checkLocation && !(Number(checkOwnerLength) > 1)) { + cardStyles = { marginTop: "19px", lineHeight: "19px", maxWidth: "600px", minWidth: "280px" }; + statusTableStyles = { position: "relative", marginTop: "19px" }; + } + + if (window.location.href.includes("obps")) { + cardStyles = { ...cardStyles, maxWidth: "950px" }; + cardStyles = { ...cardStyles, maxWidth: "950px" }; + rowContainerStyle = {}; + } + + return ( + + {owners.map((owner, index) => ( +
+ {/* TODO, Later will move to classes */} + 1 + ? { marginBottom: "8px", paddingBottom: "9px", color: "#0B0C0C", fontSize: "16px", lineHeight: "19px" } + : { marginBottom: "8px", color: "#505A5F", fontSize: "24px" } + } + > + {checkLocation && Number(checkOwnerLength) > 1 ? `${t(owner?.title)} ${index + 1}` : t(owner?.title)} + + + +
+ {owner?.values?.map((value, index) => { + if (value.map === true && value.value !== "N/A") { + return } />; + } + return ( + + + + ); + })} +
+
+
+ ))} +
+ ); +} + +export default PropertyOwners; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/Reason.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/Reason.js new file mode 100644 index 00000000..0f226935 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/Reason.js @@ -0,0 +1,10 @@ +import React from "react"; + +const Reason = ({ headComment, otherComment }) => ( +
+

{headComment}

+

{otherComment}

+
+); + +export default Reason; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ScruntinyDetails.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ScruntinyDetails.js new file mode 100644 index 00000000..bde27623 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ScruntinyDetails.js @@ -0,0 +1,46 @@ +import { StatusTable, Row, PDFSvg, CardLabel, CardSubHeader } from "@egovernments/digit-ui-react-components"; +import React, { Fragment } from "react"; +import { useTranslation } from "react-i18next"; + +const ScruntinyDetails = ({ scrutinyDetails, paymentsList=[] }) => { + const { t } = useTranslation(); + let count = 0; + const getTextValues = (data) => { + if (data?.value && data?.isTransLate) return {t(data?.value)}; + else if (data?.value && data?.isTransLate) return t(data?.value); + else if (data?.value) return data?.value; + else t("NA"); + } + return ( + + {!scrutinyDetails?.isChecklist &&
+ +
+ {scrutinyDetails?.values?.map((value, index) => { + if (value?.isUnit) return + else if (value?.isHeader && !value?.isUnit) return {t(value?.title)} + else if (value?.isSubTitle && !value?.isUnit) return {t(value?.title)} + else return + })} + {scrutinyDetails?.permit?.map((value,ind) => { + return {value?.title} + })} +
+
+ {scrutinyDetails?.scruntinyDetails?.map((report, index) => { + return ( + + + +

{t(report?.text)}

+
+ ) + })} +
+
+
} +
+ ) +} + +export default ScruntinyDetails; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/SubOccupancyTable.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/SubOccupancyTable.js new file mode 100644 index 00000000..e266bed6 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/SubOccupancyTable.js @@ -0,0 +1,126 @@ +import React, { Fragment, useMemo } from "react"; +import { Table, StatusTable, Row, CardSubHeader, CardSectionHeader } from "@egovernments/digit-ui-react-components"; +import { useTranslation } from "react-i18next"; + +const SubOccupancyTable = ({ edcrDetails, applicationData }) => { + const { t } = useTranslation(); + const isMobile = window.Digit.Utils.browser.isMobile(); + + const tableHeader = [ + { + name: "BPA_TABLE_COL_FLOOR", + id: "Floor", + }, + { + name: "BPA_TABLE_COL_LEVEL", + id: "Level", + }, + { + name: "BPA_TABLE_COL_OCCUPANCY", + id: "Occupancy", + }, + { + name: "BPA_TABLE_COL_BUILDUPAREA", + id: "BuildupArea", + }, + { + name: "BPA_TABLE_COL_FLOORAREA", + id: "FloorArea", + }, + { + name: "BPA_TABLE_COL_CARPETAREA", + id: "CarpetArea", + } + ] + + const accessData = (plot) => { + const name = plot; + return (originalRow, rowIndex, columns) => { + return originalRow[name]; + } + } + + + const tableColumns = useMemo( + () => { + return tableHeader.map((ob) => ({ + Header: t(`${ob.name}`), + accessor: accessData(ob.id), + id: ob.id + })); + }); + + function getFloorData(block) { + let floors = []; + block?.building?.floors.map((ob) => { + floors.push({ + Floor: t(`BPA_FLOOR_NAME_${ob.number}`), + Level: ob.number, + Occupancy: t(`${ob.occupancies?.[0]?.type}`), + BuildupArea: ob.occupancies?.[0]?.builtUpArea, + FloorArea: ob.occupancies?.[0]?.floorArea || 0, + CarpetArea: ob.occupancies?.[0]?.CarpetArea || 0, + key: t(`BPA_FLOOR_NAME_${ob.number}`), + }); + }); + return floors; + } + + const stringReplaceAll = (str = "", searcher = "", replaceWith = "") => { + if (searcher == "") return str; + while (str.includes(searcher)) { + str = str.replace(searcher, replaceWith); + } + return str; + }; + + function getSubOccupancyValues(index) { + let values = applicationData?.landInfo?.unit; + let returnValue = ""; + if (values?.length > 0) { + let splitArray = values[index]?.usageCategory?.split(','); + if (splitArray?.length) { + const returnValueArray = splitArray.map(data => data ? `${t(`BPA_SUBOCCUPANCYTYPE_${stringReplaceAll(data?.toUpperCase(), "-", "_")}`)}` : "NA"); + returnValue = returnValueArray.join(', ') + } + } + return returnValue ? returnValue : "NA"; + } + + return ( + +
+ + {edcrDetails?.values?.map((value, index) => { + if (value?.isHeader) return {t(value?.title)} + else return + })} + + + {edcrDetails?.subOccupancyTableDetails?.[0]?.value?.planDetail?.blocks.map((block, index) => ( +
0 ? {marginBottom: "30px", background: "#FAFAFA", border: "1px solid #D6D5D4", padding: "8px", borderRadius: "4px", maxWidth: "950px", minWidth: "280px"} : {marginBottom: "30px"}}> + {t("BPA_BLOCK_SUBHEADER")} {index + 1} + + + +
+ { return { style: {} } }} + /> + + ))} + + + ) +} + +export default SubOccupancyTable; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/SubWorkTableDetails.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/SubWorkTableDetails.js new file mode 100644 index 00000000..08b89e68 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/SubWorkTableDetails.js @@ -0,0 +1,77 @@ +import { EditIcon } from '@egovernments/digit-ui-react-components'; +import React from 'react' +import { useTranslation } from "react-i18next"; +import { useHistory } from 'react-router-dom'; + +const SubWorkTableDetails = ({data}) => { + const { t } = useTranslation(); + const history = useHistory(); + const getStyles = (index) => { + let obj = {} + switch (index) { + case 1: + obj = { "width": "1vw" } + break; + case 2: + obj = { "width": "60vw" } + break; + case 3: + obj = { "width": "20vw" } + break; + case 4: + obj = { "width": "10vw" } + break; + default: + obj = { "width": "1vw" } + break; + } + return obj + } + const renderHeader = (headers) => { + return headers?.map((key, index) => { + return + }) + } + + const renderBody = (rows) => { + return rows?.map((row, index) => { + return + + + {row[1] === t("WORKS_TOTAL_AMT") + ? + : } + {row[3] && } + {/* */} + + }) + } + + return ( +
{t(key)}
{row[0]} { row[1] === t("WORKS_TOTAL_AMT") ?
{row[1]}
:
{row[1]}
}
{row[2]}
{row[2]}
+
history.push( + { + pathname: `/digit-ui/employee/contracts/create-contract?estimateNumber=${data?.state?.estimateNumber}&task=${data?.state?.estimateDetails[index]?.name}&subEstimate=${data?.state?.estimateDetails[index]?.estimateDetailNumber}`, + state:{index, data} + } + )}> + {row[3]} +
+
{showDelete() && removeRow(row)}>}
+ + {renderHeader(data?.headers)} + + + {renderBody(data?.tableRows)} + {/* + + + + + */} + +
+ ) +} + +export default SubWorkTableDetails \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLCaption.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLCaption.js new file mode 100644 index 00000000..e5fbcde2 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLCaption.js @@ -0,0 +1,34 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { TelePhone, DisplayPhotos, UnMaskComponent } from "@egovernments/digit-ui-react-components"; +import Reason from "./Reason"; + +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?.wfComment ?
{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/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLTradeAccessories.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLTradeAccessories.js new file mode 100644 index 00000000..536a2ce3 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLTradeAccessories.js @@ -0,0 +1,52 @@ + +import React from "react"; +import { useTranslation } from "react-i18next"; +import { CardSubHeader, StatusTable, Row, CardSectionHeader } from "@egovernments/digit-ui-react-components"; + +function TLTradeAccessories({ units }) { + const { t } = useTranslation(); + return ( + + {units.map((unit, index) => ( + // TODO, Later will move to classes +
+ {`${t(unit?.title)} ${index + 1}`} + + +
+ {unit?.values?.map((value, index) => { + if (value.map === true && value.value !== "N/A") { + return } />; + } + return ( + + ); + })} +
+
+
+ ))} +
+ ); +} + +export default TLTradeAccessories; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLTradeUnits.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLTradeUnits.js new file mode 100644 index 00000000..bf1c1fbc --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/TLTradeUnits.js @@ -0,0 +1,51 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import { CardSubHeader, StatusTable, Row, CardSectionHeader } from "@egovernments/digit-ui-react-components"; + +function TLTradeUnits({ units }) { + const { t } = useTranslation(); + return ( + + {units.map((unit, index) => ( + // TODO, Later will move to classes +
+ {`${t(unit?.title)} ${index + 1}`} + + +
+ {unit?.values?.map((value, index) => { + if (value.map === true && value.value !== "N/A") { + return } />; + } + return ( + + ); + })} +
+
+
+ ))} +
+ ); +} + +export default TLTradeUnits; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ViewBreakup.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ViewBreakup.js new file mode 100644 index 00000000..5608aeb2 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/ViewBreakup.js @@ -0,0 +1,73 @@ +import React, { useState, Fragment } from "react"; +import { useTranslation } from "react-i18next"; +import { CardSectionHeader, Modal, Row, StatusTable } from "@egovernments/digit-ui-react-components"; + +const ViewBreakup = ({ wsAdditionalDetails, workflowDetails }) => { + const { t } = useTranslation(); + const [popup, showPopUp] = useState(false); + const [breakUpData, setBreakUpData] = useState({}); + + const Heading = (props) => { + return

{props.label}

; + }; + + const Close = () => ( + + + + + ); + + const CloseBtn = (props) => { + return ( +
+ +
+ ); + }; + + const onPopupOpen = () => { + let breakupData = wsAdditionalDetails.additionalDetails.data || {}; + const sessionBillData = sessionStorage.getItem("Digit.ADHOC_BILL_ADD_REBATE_DATA"); + const sessionBillFormData = sessionBillData ? JSON.parse(sessionBillData) : {}; + if (sessionBillFormData?.value?.totalAmount) breakupData = sessionBillFormData?.value; + setBreakUpData(breakupData); + showPopUp(true); + } + + return ( + +
+ {wsAdditionalDetails?.additionalDetails?.isViewBreakup ?
onPopupOpen()} style={{ marginTop: "12px" }}> + {t("WS_PAYMENT_VIEW_BREAKUP")} +
: null + } + {popup && + } + headerBarEnd={ { showPopUp(false); }} />} + hideSubmit={true} + popupStyles={{ overflowY: "auto" }} //maxHeight: "calc(100% - 90px)" + headerBarMainStyle={{ marginBottom: "0px" }} + popupModuleMianStyles={{ paddingTop: "0px" }} + > + { + {t("WS_APPLICATION_FEE_HEADER")} + {breakUpData?.billSlabData?.FEE?.map(data => ₹{Number(data?.amount) || 0}} textStyle={{ textAlign: "right" }} />)} +
+ ₹{Number(breakUpData?.fee) || 0}} textStyle={{ textAlign: "right", fontWeight: "700", fontSize: "24px" }} /> + {t("WS_SERVICE_FEE_HEADER")} + {breakUpData?.billSlabData?.CHARGES?.map(data => ₹{Number(data?.amount) || 0}} textStyle={{ textAlign: "right" }} />)} +
+ ₹{Number(breakUpData?.charge) || 0}} textStyle={{ textAlign: "right", fontWeight: "700", fontSize: "24px" }} /> + {breakUpData?.billSlabData?.TAX?.map(data => ₹{Number(data?.amount) || 0}} textStyle={{ textAlign: "right" }} />)} +
+ ₹{Number(breakUpData?.totalAmount) || 0}} textStyle={{ textAlign: "right", fontWeight: "700", fontSize: "24px" }} /> +
} +
} +
+
+ ) +} + +export default ViewBreakup; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WSAdditonalDetails.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WSAdditonalDetails.js new file mode 100644 index 00000000..06814062 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WSAdditonalDetails.js @@ -0,0 +1,399 @@ +import { StatusTable, Row, CardSubHeader } from "@egovernments/digit-ui-react-components"; +import React, { Fragment } from "react"; +import { useTranslation } from "react-i18next"; +import { getQueryStringParams } from "../../../ws/src/utils"; + +const cardSubHeaderStyles = () => { + // return { fontSize: "24px", padding: "0px", margin: "0px", color: "#505A5F" }; + return { fontSize: "24px", marginBottom: "16px", marginTop: "32px" }; +}; + +const cardDivStyles = () => { + return { + border: "1px solid #D6D5D4", + background: "#FAFAFA", + borderRadius: "4px", + padding: "10px 10px 0px 10px", + marginBottom: "10px", + display: "flex", + }; +}; + +const convertEpochToDate = (dateEpoch) => { + if (dateEpoch) { + const dateFromApi = new Date(dateEpoch); + let month = dateFromApi.getMonth() + 1; + let day = dateFromApi.getDate(); + let year = dateFromApi.getFullYear(); + month = (month > 9 ? "" : "0") + month; + day = (day > 9 ? "" : "0") + day; + return `${day}/${month}/${year}`; + } else { + return null; + } +}; + +const WSAdditonalDetails = ({ wsAdditionalDetails, oldValue }) => { + const { t } = useTranslation(); + let filters = getQueryStringParams(location.search); + const serviceType = filters?.service; + const isModify = filters?.mode; + + const oldValueData = oldValue?.[1]; + + const stringReplaceAll = (str = "", searcher = "", replaceWith = "") => { + if (searcher == "") return str; + while (str.includes(searcher)) { + str = str.replace(searcher, replaceWith); + } + return str; + }; + + const renderSWConnectionDetails = () => { + return ( +
+ {oldValueData?.connectionType ? ( + + ) : ( +
{"NA"}
+ )} + + {oldValueData?.noOfWaterClosets ? ( + + ) : ( +
{"NA"}
+ )} + {oldValueData?.noOfToilets ? ( + + ) : ( +
{"NA"}
+ )} +
+ ); + }; + + const renderWSConnectionDetails = () => { + return ( +
+ {oldValueData?.connectionType && ( )} + {oldValueData?.noOfTaps && ( )} + {oldValueData?.waterSource && ( )} + {oldValueData?.pipeSize && ( )} + {oldValueData?.waterSource && ( )} +
+ ); + }; + + const renderSWPlumberDetails = () => { + return ( +
+ {oldValueData?.additionalDetails?.detailsProvidedBy !== wsAdditionalDetails?.additionalDetails?.plumberDetails[0]?.value && + oldValueData?.additionalDetails?.detailsProvidedBy !== null ? ( + + ) : ( +
{"NA"}
+ )} + {oldValueData?.plumberInfo ? ( + + ) : ( +
{"NA"}
+ )} + {oldValueData?.plumberInfo ? ( + + ) : ( +
{"NA"}
+ )} + {oldValueData?.plumberInfo ? ( + + ) : ( +
{"NA"}
+ )} +
+ ); + }; + + const renderWSPlumberDetails = () => { + return ( +
+ {oldValueData?.additionalDetails?.detailsProvidedBy !== wsAdditionalDetails?.additionalDetails?.plumberDetails[0]?.value ? ( + + ) : ( +
{"NA"}
+ )} +
+ ); + }; + + const renderSWRoadCuttingDetails = () => { + { + oldValueData?.roadCuttingInfo?.map((info) => { + return ( +
+ + +
+ ); + }); + } + }; + + const renderSWActivationDetails = () => { + return ( +
+ {oldValueData?.connectionExecutionDate ? ( + + ) : ( +
{"NA"}
+ )} +
+ ); + }; + + const renderWSActivationDetails = () => { + return ( +
+ {oldValueData?.meterId && ( )} + {oldValueData?.additionalDetails?.initialMeterReading && ( )} + {oldValueData?.meterInstallationDate && ( )} + {oldValueData?.connectionExecutionDate && ( )} +
+ ); + }; + + var { connectionDetails, plumberDetails, roadCuttingDetails, activationDetails } = wsAdditionalDetails?.additionalDetails || {connectionDetails:[], plumberDetails: []}; + + // binding old values with new values + if(isModify === "MODIFY"){ + + connectionDetails = connectionDetails?.map((value) => { + if(value.title == "WS_SERV_DETAIL_CONN_TYPE" && oldValueData?.connectionType) value["oldValue"] = [ + { value:value?.value, className:"newValue", style:{ display:"inline"} }, + { + value:`${t("WS_OLD_LABEL_NAME")} ${oldValueData?.connectionType}`, + className:"oldValue", style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"} + }]; + if(value.title == "WS_SERV_DETAIL_NO_OF_TAPS" && oldValueData?.noOfTaps) value["oldValue"] = [ + {value:value?.value,className:"newValue", style:{ display:"inline"}}, + {value:`${t("WS_OLD_LABEL_NAME")} ${oldValueData?.noOfTaps}`, style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"},className:"oldValue"} + ]; + if(value.title == "WS_SERV_DETAIL_WATER_SOURCE" && oldValueData?.waterSource) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${t(oldValueData?.waterSource?.toUpperCase()?.split(".")[0])}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_PIPE_SIZE_IN_INCHES_LABEL" && oldValueData?.pipeSize) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.pipeSize}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_SERV_DETAIL_WATER_SUB_SOURCE" && oldValueData?.waterSource) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${t(oldValueData?.waterSource?.toUpperCase()?.split(".")[1])}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_NUMBER_WATER_CLOSETS_LABEL" && oldValueData?.noOfWaterClosets) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.noOfWaterClosets}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_SERV_DETAIL_NO_OF_TOILETS" && oldValueData?.noOfWaterClosets) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.noOfWaterClosets}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + + return value; + }) + + plumberDetails = plumberDetails?.map((value) => { + if(value.title == "WS_ADDN_DETAILS_PLUMBER_PROVIDED_BY" && oldValueData?.additionalDetails?.detailsProvidedBy && oldValueData?.additionalDetails?.detailsProvidedBy !== value.value ) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.additionalDetails?.detailsProvidedBy}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_ADDN_DETAILS_PLUMBER_LICENCE_NO_LABEL" && oldValueData?.plumberInfo[0]?.licenseNo ) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.plumberInfo[0]?.licenseNo}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_ADDN_DETAILS_PLUMBER_NAME_LABEL" && oldValueData?.plumberInfo[0]?.name ) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.plumberInfo[0]?.name}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_PLUMBER_MOBILE_NO_LABEL" && oldValueData?.plumberInfo[0]?.mobileNumber ) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.plumberInfo[0]?.mobileNumber}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + return value; + }) + + roadCuttingDetails = roadCuttingDetails?.map((roadDetail) => { + const roadDetailValues = roadDetail?.values?.map((value) => { + if(value.title == "WS_ADDN_DETAIL_ROAD_TYPE" && oldValueData?.roadCuttingInfo[0]?.roadType) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.roadCuttingInfo[0]?.roadType}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_ROAD_CUTTING_AREA_LABEL" && oldValueData?.roadCuttingInfo[0]?.roadCuttingArea) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.roadCuttingInfo[0]?.roadCuttingArea}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + return value; + }) + return ({...roadDetail,values:roadDetailValues}); + }) + + activationDetails = activationDetails?.map((value) => { + if(value.title == "WS_SERV_DETAIL_CONN_EXECUTION_DATE" && oldValueData?.connectionExecutionDate) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${convertEpochToDate(oldValueData?.connectionExecutionDate)}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + + if(value.title == "WS_SERV_DETAIL_METER_ID" && oldValueData?.meterId) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.meterId}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + + if(value.title == "WS_INITIAL_METER_READING_LABEL" && oldValueData?.initialMeterReading) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${oldValueData?.initialMeterReading}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + + if(value.title == "WS_INSTALLATION_DATE_LABEL" && oldValueData?.meterInstallationDate) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${convertEpochToDate(oldValueData?.meterInstallationDate)}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + if(value.title == "WS_SERV_DETAIL_CONN_EXECUTION_DATE" && oldValueData?.connectionExecutionDate) value["oldValue"] = [ + {value:value?.value, className:"newValue", style:{ display:"inline"}}, + { + value: `${t("WS_OLD_LABEL_NAME")} ${convertEpochToDate(oldValueData?.connectionExecutionDate)}`, + style:{color:'gray', paddingLeft:"10px", display:"inline", fontSize:"13px"}, className:"oldValue" + } + ]; + return value; + }) + }; + + return ( + +
+ {wsAdditionalDetails?.additionalDetails?.connectionDetails && ( + + {t("WS_COMMON_CONNECTION_DETAIL")} +
+
+ {connectionDetails?.map((value, index) => { + return ( +
+ +
+ ); + })} +
+
+
+ )} + {wsAdditionalDetails?.additionalDetails?.plumberDetails && ( + + {t("WS_COMMON_PLUMBER_DETAILS")} +
+
+ + {plumberDetails?.map((value, index) => { + return ; + })} +
+
+
+ )} + {wsAdditionalDetails?.additionalDetails?.roadCuttingDetails && ( + + {t("WS_ROAD_CUTTING_DETAILS")} +
+
+ {roadCuttingDetails?.map((value) => { + return ( +
1 + ? { + border: "1px solid #D6D5D4", + background: "#FAFAFA", + borderRadius: "4px", + padding: "10px 10px 0px 10px", + margin: "5px 0px", + } + : {} + } + > + {value?.values?.map((roadValue) => ( + + ))} +
+ ); + })} +
+
+
+ )} + {wsAdditionalDetails?.additionalDetails?.activationDetails && ( + + {t("WS_ACTIVATION_DETAILS")} +
+
+ {activationDetails?.map((value, index) => { + return ( + + ); + })} +
+
+
+ )} +
+
+ ); +}; + +export default WSAdditonalDetails; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WSFeeEstimation.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WSFeeEstimation.js new file mode 100644 index 00000000..9a4fe591 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WSFeeEstimation.js @@ -0,0 +1,346 @@ +import React, { useState, Fragment, useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { Card, CardSectionHeader, CardLabel } from "@egovernments/digit-ui-react-components"; +import { Modal, Dropdown, Row, StatusTable, TextInput, Toast } from "@egovernments/digit-ui-react-components"; +import cloneDeep from "lodash/cloneDeep"; + +const Penality_menu = [ + { + title: "PT_PENDING_DUES_FROM_EARLIER", + value: "Pending dues from earlier", + }, + { + title: "PT_MISCALCULATION_OF_EARLIER_ASSESSMENT", + value: "Miscalculation of earlier Assessment", + }, + { + title: "PT_ONE_TIME_PENALITY", + value: "One time penality", + }, + { + title: "PT_OTHERS", + value: "Others", + }, +] +const Rebate_menu = [ + { + title: "PT_ADVANCED_PAID_BY_CITIZEN_EARLIER", + value: "Advanced Paid By Citizen Earlier", + }, + { + title: "PT_REBATE_PROVIDED_BY_COMMISSIONER_EO", + value: "Rebate provided by commissioner/EO", + }, + { + title: "PT_ADDITIONAL_AMOUNT_CHARGED_FROM_THE_CITIZEN", + value: "Additional amount charged from the citizen", + }, + { + title: "PT_OTHERS", + value: "Others", + }, +]; + + +const WSFeeEstimation = ({ wsAdditionalDetails, workflowDetails }) => { + const { t } = useTranslation(); + const [sessionFormData, setSessionFormData, clearSessionFormData] = Digit.Hooks.useSessionStorage("ADHOC_ADD_REBATE_DATA", {}); + const [sessionBillFormData, setSessionBillFormData, clearBillSessionFormData] = Digit.Hooks.useSessionStorage("ADHOC_BILL_ADD_REBATE_DATA", {}); + const isPaid = wsAdditionalDetails?.additionalDetails?.isPaid ? true : false; + const [popup, showPopUp] = useState(false); + const [fields, setFields] = useState(sessionFormData ? sessionFormData : {}); + const [showToast, setShowToast] = useState(null); + const [billDetails, setBillDetails] = useState(wsAdditionalDetails.additionalDetails.data ? wsAdditionalDetails.additionalDetails.data : {}); + const [values, setValues] = useState(wsAdditionalDetails.additionalDetails.values ? wsAdditionalDetails.additionalDetails.values : []); + + const stateCode = Digit.ULBService.getStateId(); + const { isMdmsLoading, data: mdmsRes } = Digit.Hooks.ws.useMDMS(stateCode, "BillingService", ["TaxHeadMaster"]); + + useEffect(() => { + const data = { ...wsAdditionalDetails?.additionalDetails?.appDetails?.additionalDetails }; + setSessionFormData(data); + setFields(data); + if (sessionFormData?.billDetails?.length > 0) { + const values = [ + { title: "WS_APPLICATION_FEE_HEADER", value: sessionFormData?.billDetails?.[0]?.fee }, + { title: "WS_SERVICE_FEE_HEADER", value: sessionFormData?.billDetails?.[0]?.charge }, + { title: "WS_TAX_HEADER", value: sessionFormData?.billDetails?.[0]?.taxAmount }, + ]; + setValues(values); + setBillDetails(sessionFormData?.billDetails?.[0]); + } + }, []); + + let validation = {}; + + const Heading = (props) => { + return

{props.label}

; + }; + + const Close = () => ( + + + + + ); + + const CloseBtn = (props) => { + return ( +
+ +
+ ); + }; + + const closeToast = () => { + setShowToast(false); + }; + + const addAdhocRebatePenality = (e) => { + const adhocAmount = fields?.adhocPenalty ? Number(fields?.adhocPenalty) : 0; + const rebateAmount = fields?.adhocRebate ? Number(fields?.adhocRebate) : 0; + if (adhocAmount || rebateAmount) { + + const totalAmount = wsAdditionalDetails?.additionalDetails?.data?.totalAmount; + const demandId = wsAdditionalDetails?.additionalDetails?.data?.billDetails?.[0]?.demandId; + + if (rebateAmount > totalAmount) { + setShowToast({ isError: false, isWarning: true, key: "error", message: t("ERR_WS_REBATE_GREATER_THAN_AMOUNT") }); + } else { + const applicationNo = wsAdditionalDetails?.additionalDetails?.appDetails?.applicationNo; + const tenantId = wsAdditionalDetails?.additionalDetails?.appDetails?.tenantId; + const appAdditionalDetails = { ...wsAdditionalDetails?.additionalDetails?.appDetails?.additionalDetails, ...fields } + wsAdditionalDetails.additionalDetails.appDetails.additionalDetails = appAdditionalDetails; + + const data = { + CalculationCriteria: + wsAdditionalDetails?.additionalDetails?.appDetails?.service == "WATER" + ? [ + { + applicationNo: applicationNo, + tenantId: tenantId, + waterConnection: wsAdditionalDetails.additionalDetails.appDetails, + }, + ] + : [ + { + applicationNo: applicationNo, + tenantId: tenantId, + sewerageConnection: wsAdditionalDetails.additionalDetails.appDetails, + }, + ], + isconnectionCalculation: false, + }; + + let businessService = wsAdditionalDetails?.additionalDetails?.appDetails?.service == "WATER" ? "WS" : "SW"; + Digit.WSService.wsCalculationEstimate(data, businessService) + .then((result, err) => { + if (result?.Calculation?.[0]?.taxHeadEstimates?.length > 0) { + result?.Calculation?.[0]?.taxHeadEstimates?.forEach(data => data.amount = data.estimateAmount); + } + + result.Calculation[0].billSlabData = _.groupBy(result?.Calculation?.[0]?.taxHeadEstimates, 'category'); + const values = [ + { title: "WS_APPLICATION_FEE_HEADER", value: result.Calculation?.[0]?.fee }, + { title: "WS_SERVICE_FEE_HEADER", value: result.Calculation?.[0]?.charge }, + { title: "WS_TAX_HEADER", value: result.Calculation?.[0]?.taxAmount }, + ]; + setSessionBillFormData(cloneDeep(result.Calculation[0])); + setBillDetails(result?.Calculation?.[0]); + setValues(values); + fields.billDetails = result?.Calculation; + setSessionFormData(fields); + showPopUp(false); + }) + .catch((e) => { + setShowToast({ isError: true, isWarning: false, key: "error", message: e?.response?.data?.Errors[0]?.message ? t(`${e?.response?.data?.Errors[0]?.code}`) : t("PT_COMMON_ADD_REBATE_PENALITY") }); + }); + } + } else { + setShowToast({ isError: false, isWarning: true, key: "warning", message: t("ERR_WS_ENTER_ATLEAST_ONE_FIELD") }); + } + } + + const selectedValuesData = (value, isDropDownValue = false, e) => { + let values = { ...fields }; + if (isDropDownValue) { + values[`${value}_data`] = e; + values[value] = e.title; + if (e.title == "PT_OTHERS" && value == "adhocPenaltyReason") values[`adhocPenaltyComment`] = ""; + if (e.title == "PT_OTHERS" && value == "adhocRebateReason") values[`adhocRebateComment`] = ""; + } else { + values[value] = e.target.value; + } + setFields(values); + } + + return ( + +
+ {values && + +
+ {values?.map((value, index) => { + return + })} +
+
+
+ + +
+
} + { + wsAdditionalDetails?.additionalDetails?.isAdhocRebate ?
{ + showPopUp(true) + }} + > + {t("WS_PAYMENT_ADD_REBATE_PENALTY")} +
: null + } + {popup && + } + headerBarEnd={ + { + setFields(sessionFormData); + showPopUp(false); + }} />} + actionCancelLabel={t("PT_CANCEL")} + actionCancelOnSubmit={() => { + setFields(sessionFormData); + showPopUp(false); + }} + actionSaveLabel={t("PT_ADD")} + actionSaveOnSubmit={(e) => addAdhocRebatePenality(e)} + hideSubmit={false} + popupStyles={{ overflowY: "auto" }} + > + { +
+ + {t("PT_AD_PENALTY")} + + {t("PT_TX_HEADS")} + +
+ selectedValuesData("adhocPenaltyReason", true, e)} + selected={fields?.adhocPenaltyReason_data || ""} + isPropertyAssess={true} + name={"adhocPenaltyReason_data"} + t={t} + /> +
+ {fields?.adhocPenaltyReason_data?.title === "PT_OTHERS" &&
+ {t("PT_REASON")} +
+ selectedValuesData("adhocPenaltyComment", false, e)} + {...(validation = { + isRequired: true, + pattern: "^[a-zA-Z-.`' ]*$", + type: "text", + title: t("TL_NAME_ERROR_MESSAGE"), + })} + /> +
+
} + {t("PT_HEAD_AMT")} +
+ selectedValuesData("adhocPenalty", false, e)} + {...(validation = { + isRequired: true, + pattern: "^[1-9]+[0-9]*$", + title: t("ERR_DEFAULT_INPUT_FIELD_MSG"), + })} + /> + +
+
+ + {t("PT_AD_REBATE")} + {t("PT_TX_HEADS")} +
+ selectedValuesData("adhocRebateReason", true, e)} + selected={fields?.adhocRebateReason_data || ""} + name={"adhocRebateReason_data"} + isPropertyAssess={true} + t={t} + /> +
+ {fields?.adhocRebateReason_data?.title === "PT_OTHERS" &&
+ {t("PT_REASON")} + selectedValuesData("adhocRebateComment", false, e)} + {...(validation = { + isRequired: true, + pattern: "^[a-zA-Z-.`' ]*$", + type: "text", + title: t("TL_NAME_ERROR_MESSAGE"), + })} + /> +
} + {t("PT_HEAD_AMT")} +
+ selectedValuesData("adhocRebate", false, e)} + {...(validation = { + isRequired: true, + pattern: "^[1-9]+[0-9]*$", + title: t("ERR_DEFAULT_INPUT_FIELD_MSG"), + })} + /> +
+
+
+ }
} + {showToast && + } +
+
+ ) +} + +export default WSFeeEstimation; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WeekDateRange.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WeekDateRange.js new file mode 100644 index 00000000..75069dd7 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/components/WeekDateRange.js @@ -0,0 +1,30 @@ +import React, { useCallback, useState } from "react"; +import { useTranslation } from "react-i18next"; + +const WeekDateRange = (props) => { + const [localSearchParams, setLocalSearchParams] = useState(() => ({})); + const { t } = useTranslation(); + const handleChange = useCallback((data) => { + setLocalSearchParams(() => ({ ...data })); + }, []); + + return ( +
+
+

{props.title}

+
+ +
+
+
+ ); +}; + +export default WeekDateRange; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/AcceptDso.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/AcceptDso.js new file mode 100644 index 00000000..e870f2e9 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/AcceptDso.js @@ -0,0 +1,45 @@ +import React from "react"; +import { Dropdown } from "@egovernments/digit-ui-react-components"; + +export const configAcceptDso = ({ t, dsoData, dso, selectVehicleNo, vehicleNoList, vehicleNo, vehicle, action }) => { + return { + label: { + heading: `ES_FSM_ACTION_TITLE_${action}`, + submit: `CS_COMMON_${action}`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: t("ES_FSM_ACTION_VEHICLE_REGISTRATION_NO"), + isMandatory: true, + type: "dropdown", + populators: ( + + ), + }, + { + label: t("ES_FSM_ACTION_VEHICLE_CAPACITY_IN_LTRS"), + isMandatory: true, + type: "text", + populators: { + name: "capacity", + validation: { + required: true, + }, + }, + disable: true, + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/AssignDso.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/AssignDso.js new file mode 100644 index 00000000..418caf1e --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/AssignDso.js @@ -0,0 +1,115 @@ +import React from "react"; +import { DatePicker, Dropdown, CardLabelError } from "@egovernments/digit-ui-react-components"; + +function todayDate() { + var today = new Date(); + var dd = today.getDate(); + var mm = today.getMonth() + 1; + var yyyy = today.getFullYear(); + + if (dd < 10) { + dd = "0" + dd; + } + + if (mm < 10) { + mm = "0" + mm; + } + + return yyyy + "-" + mm + "-" + dd; +} + +function getFilteredDsoData(dsoData, vehicle) { + return dsoData?.filter((e) => e.vehicles?.find((veh) => veh?.type == vehicle?.code)); +} + +export const configAssignDso = ({ t, dsoData, dso, selectDSO, vehicleMenu, vehicle, selectVehicle, action }) => { + return { + label: { + heading: `ES_FSM_ACTION_TITLE_${action}`, + submit: `CS_COMMON_${action}`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: t("ES_FSM_ACTION_VEHICLE_TYPE"), + isMandatory: true, + type: "dropdown", + populators: ( + + ), + }, + { + label: t("ES_FSM_ACTION_DSO_NAME"), + isMandatory: true, + type: "dropdown", + populators: ( + + {getFilteredDsoData(dsoData, vehicle) && !getFilteredDsoData(dsoData, vehicle).length ? ( + {t("ES_COMMON_NO_DSO_AVAILABLE_WITH_SUCH_VEHICLE")} + ) : null} + + + ), + }, + { + label: t("ES_FSM_ACTION_VEHICLE_CAPACITY_IN_LTRS"), + isMandatory: true, + type: "text", + populators: { + name: "capacity", + validation: { + required: true, + }, + }, + disable: true, + }, + // { + // label: t("ES_FSM_ACTION_SERVICE_DATE"), + // isMandatory: true, + // type: "date", + // populators: { + // name: "date", + // validation: { + // required: true, + // }, + // min: Digit.Utils.date.getDate(), + // defaultValue: Digit.Utils.date.getDate(), + // }, + // }, + { + label: t("ES_FSM_ACTION_SERVICE_DATE"), + isMandatory: true, + type: "custom", + populators: { + name: "date", + validation: { + required: true, + }, + customProps: { min: Digit.Utils.date.getDate() }, + defaultValue: Digit.Utils.date.getDate(), + component: (props, customProps) => , + }, + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/BPAApproverApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/BPAApproverApplication.js new file mode 100644 index 00000000..ca66865b --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/BPAApproverApplication.js @@ -0,0 +1,77 @@ +import { Dropdown, UploadFile } from "@egovernments/digit-ui-react-components"; +import React from "react"; + +export const configBPAApproverApplication = ({ + t, + action, + approvers, + selectedApprover, + setSelectedApprover, + selectFile, + uploadedFile, + setUploadedFile, + assigneeLabel, + businessService, + error +}) => { + let isRejectOrRevocate = false; + if(action?.action == "REVOCATE" || action?.action == "REJECT" || action.action == "SKIP_PAYMENT" || action?.action == "SEND_BACK_TO_CITIZEN" || action?.action == "APPROVE") { + isRejectOrRevocate = true; + } + + let isCommentRequired = false; + if(action?.action == "REVOCATE" || action?.action == "REJECT") { + isCommentRequired = true; + } + + return { + label: { + heading: `WF_${action?.action}_APPLICATION`, + submit: `WF_${businessService}_${action?.action}`, + cancel: "BPA_CITIZEN_CANCEL_BUTTON", + }, + form: [ + { + body: [ + { + label: action.isTerminateState || isRejectOrRevocate ? null : t(assigneeLabel || `WF_ROLE_${action.assigneeRoles?.[0]}`), + type: "dropdown", + populators: action.isTerminateState || isRejectOrRevocate ? null : ( + + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + isMandatory: isCommentRequired, + populators: { + name: "comments", + }, + }, + { + label: `${t("WF_APPROVAL_UPLOAD_HEAD")}`, + populators: ( + { + setUploadedFile(null); + }} + message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`CS_ACTION_NO_FILEUPLOADED`)} + accept= "image/*, .pdf, .png, .jpeg, .jpg" + iserror={error} + /> + ), + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/BPAREGApproverApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/BPAREGApproverApplication.js new file mode 100644 index 00000000..0bdba14b --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/BPAREGApproverApplication.js @@ -0,0 +1,71 @@ +import { Dropdown, UploadFile } from "@egovernments/digit-ui-react-components"; +import React from "react"; + +export const configBPAREGApproverApplication = ({ + t, + action, + approvers, + selectedApprover, + setSelectedApprover, + selectFile, + uploadedFile, + setUploadedFile, + assigneeLabel, + businessService, + error +}) => { + let checkCondtions = true; + if (action?.action == "SENDBACKTOCITIZEN") checkCondtions = false; + if (action.isTerminateState) checkCondtions = false; + + return { + label: { + heading: `WF_${action?.action}_APPLICATION`, + submit: `WF_${businessService?.toUpperCase()}_${action?.action}`, + cancel: "WF_EMPLOYEE_BPAREG_CANCEL", + }, + form: [ + { + body: [ + { + label: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_LABEL"), + placeholder: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + type: "dropdown", + populators: !checkCondtions ? null : ( + + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + { + label: t("BPA_APPROVAL_CHECKLIST_BUTTON_UP_FILE"), + populators: ( + { + setUploadedFile(null); + }} + message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`CS_ACTION_NO_FILEUPLOADED`)} + accept= "image/*, .pdf, .png, .jpeg, .jpg" + iserror={error} + /> + ) + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/CompleteApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/CompleteApplication.js new file mode 100644 index 00000000..a4c7c96b --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/CompleteApplication.js @@ -0,0 +1,46 @@ +import React from "react"; +import { DatePicker } from "@egovernments/digit-ui-react-components"; + +export const configCompleteApplication = ({ t, vehicle, applicationCreatedTime = 0, action }) => ({ + label: { + heading: `ES_FSM_ACTION_TITLE_${action}`, + submit: `CS_COMMON_${action}`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: t("ES_FSM_ACTION_DESLUGED_DATE_LABEL"), + isMandatory: true, + type: "custom", + populators: { + name: "desluged", + validation: { + required: true, + }, + defaultValue: Digit.Utils.date.getDate(), + customProps: { + min: Digit.Utils.date.getDate(applicationCreatedTime), + max: Digit.Utils.date.getDate(), + }, + component: (props, customProps) => , + }, + }, + { + label: t("ES_FSM_ACTION_WASTE_VOLUME_LABEL"), + type: "text", + isMandatory: true, + populators: { + name: "wasteCollected", + validation: { + required: true, + validate: (value) => parseInt(value) <= parseInt(vehicle.capacity), + }, + error: `${t("ES_FSM_ACTION_INVALID_WASTE_VOLUME")} ${vehicle?.capacity} ${t("CS_COMMON_LITRES")}`, + }, + }, + ], + }, + ], +}); diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/NOCApproverApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/NOCApproverApplication.js new file mode 100644 index 00000000..12922b05 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/NOCApproverApplication.js @@ -0,0 +1,79 @@ +import { Dropdown, UploadFile } from "@egovernments/digit-ui-react-components"; +import React from "react"; + +export const configNOCApproverApplication = ({ + t, + action, + approvers, + selectedApprover, + setSelectedApprover, + selectFile, + uploadedFile, + setUploadedFile, + assigneeLabel, + businessService, + error +}) => { + + let isCommentRequired = false; + if(action?.action == "REVOCATE" || action?.action == "REJECT") { + isCommentRequired = true; + } + + let isRejectOrRevocate = false; + if(action?.action == "APPROVE" || action?.action == "REJECT" || action.action == "AUTO_APPROVE" || action.action == "AUTO_REJECT") { + isRejectOrRevocate = true; + } + + return { + label: { + heading: `WF_${action?.action}_APPLICATION`, + submit: `WF_${businessService}_${action?.action}`, + cancel: "CORE_LOGOUTPOPUP_CANCEL", + }, + form: [ + { + body: [ + { + label: action.isTerminateState || isRejectOrRevocate ? null : t(assigneeLabel || `WF_ROLE_${action.assigneeRoles?.[0]}`), + type: "dropdown", + populators: action.isTerminateState || isRejectOrRevocate ? null : ( + + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + isMandatory: isCommentRequired, + populators: { + name: "comments", + }, + }, + { + label: `${t("WF_APPROVAL_UPLOAD_HEAD")}`, + populators: ( + { + setUploadedFile(null); + }} + showHint={true} + message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`CS_ACTION_NO_FILEUPLOADED`)} + accept= "image/*, .pdf, .png, .jpeg, .jpg" + iserror={error} + /> + ), + }, + ], + }, + ], + }; +}; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/PTApproverApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/PTApproverApplication.js new file mode 100644 index 00000000..afcc6a19 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/PTApproverApplication.js @@ -0,0 +1,66 @@ +import { Dropdown, UploadFile } from "@egovernments/digit-ui-react-components"; +import React from "react"; + +export const configPTApproverApplication = ({ + t, + action, + approvers, + selectedApprover, + setSelectedApprover, + selectFile, + uploadedFile, + setUploadedFile, + assigneeLabel, + businessService, +}) => { + return { + label: { + heading: `WF_${action?.action}_APPLICATION`, + submit: `WF_${businessService}_${action?.action}`, + cancel: "ES_PT_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: action.isTerminateState || action?.action === "SENDBACKTOCITIZEN" ? null : t(assigneeLabel || `WF_ROLE_${action.assigneeRoles?.[0]}`), + // isMandatory: !action.isTerminateState, + type: "dropdown", + populators: action.isTerminateState || action?.action === "SENDBACKTOCITIZEN" ? null : ( + + ), + }, + { + label: t("ES_PT_ACTION_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + { + label: `${t("ES_PT_ATTACH_FILE")}${action.docUploadRequired ? " *" : ""}`, + populators: ( + { + setUploadedFile(null); + }} + showHint={true} + hintText={t("PT_ATTACH_RESTRICTIONS_SIZE")} + message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`ES_PT_ACTION_NO_FILEUPLOADED`)} + /> + ), + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/PTAssessProperty.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/PTAssessProperty.js new file mode 100644 index 00000000..dd04037a --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/PTAssessProperty.js @@ -0,0 +1,26 @@ +import React from "react"; +import { RadioButtons } from "@egovernments/digit-ui-react-components"; + +export const configPTAssessProperty = ({ t, action, financialYears, selectedFinancialYear, setSelectedFinancialYear }) => { + return { + label: { + heading: `WF_${action.action}_APPLICATION`, + submit: `WF_PT.CREATE_${action.action}`, + cancel: "ES_PT_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: t("ES_PT_FINANCIAL_YEARS"), + isMandatory: true, + type: "radio", + populators: ( + + ), + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/ReassignDso.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/ReassignDso.js new file mode 100644 index 00000000..132a5bc6 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/ReassignDso.js @@ -0,0 +1,101 @@ +import React from "react"; +import { Dropdown } from "@egovernments/digit-ui-react-components"; + +function getFilteredDsoData(dsoData, vehicle) { + return dsoData?.filter((e) => e.vehicles?.find((veh) => veh?.type == vehicle?.code)); +} + +export const configReassignDSO = ({ + t, + dsoData, + dso, + selectDSO, + vehicleMenu, + vehicle, + selectVehicle, + reassignReasonMenu, + reassignReason, + selectReassignReason, + action, + showReassignReason, +}) => ({ + label: { + heading: `ES_FSM_ACTION_TITLE_${action}`, + submit: `CS_COMMON_${action}`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + ...(showReassignReason + ? [ + { + label: t("ES_FSM_ACTION_REASSIGN_REASON"), + type: "dropdown", + isMandatory: true, + populators: ( + + ), + }, + ] + : []), + { + label: t("ES_FSM_ACTION_VEHICLE_TYPE"), + isMandatory: vehicle ? false : true, + type: "dropdown", + populators: ( + + ), + }, + { + label: t("ES_FSM_ACTION_DSO_NAME"), + isMandatory: true, + type: "dropdown", + populators: ( + + ), + }, + { + label: t("ES_FSM_ACTION_VEHICLE_CAPACITY_IN_LTRS"), + type: "text", + populators: { + name: "capacity", + validation: { + required: true, + }, + }, + disable: true, + }, + { + label: t("ES_FSM_ACTION_SERVICE_DATE"), + isMandatory: true, + type: "date", + populators: { + name: "date", + validation: { + required: true, + }, + min: Digit.Utils.date.getDate(), + defaultValue: Digit.Utils.date.getDate(), + }, + }, + ], + }, + ], +}); diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/RejectApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/RejectApplication.js new file mode 100644 index 00000000..a18bdaf1 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/RejectApplication.js @@ -0,0 +1,31 @@ +import React from "react"; +import { Dropdown } from "@egovernments/digit-ui-react-components"; + +export const configRejectApplication = ({ t, rejectMenu, setReason, reason, action }) => { + return { + label: { + heading: `ES_FSM_ACTION_TITLE_${action}`, + submit: `CS_COMMON_${action}`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: t(`ES_FSM_ACTION_${action.toUpperCase()}_REASON`), + type: "dropdown", + populators: , + isMandatory: true, + }, + { + label: t("ES_FSM_ACTION_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/TLApproverApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/TLApproverApplication.js new file mode 100644 index 00000000..23b20e5b --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/TLApproverApplication.js @@ -0,0 +1,83 @@ +import { Dropdown, UploadFile } from "@egovernments/digit-ui-react-components"; +import React from "react"; + +export const configTLApproverApplication = ({ + t, + action, + approvers, + selectedApprover, + setSelectedApprover, + selectFile, + uploadedFile, + setUploadedFile, + assigneeLabel, + businessService, +}) => { + let checkCondtions = true; + if (action?.action == "SENDBACKTOCITIZEN" || action?.action == "APPROVE") checkCondtions = false; + if (action.isTerminateState) checkCondtions = false; + + return { + label: { + heading: `WF_${action?.action}_APPLICATION`, + submit: `WF_${businessService?.toUpperCase()}_${action?.action}`, + cancel: "WF_EMPLOYEE_NEWTL_CANCEL", + }, + form: [ + { + body: [ + { + label: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_LABEL"), + placeholder: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + // isMandatory: false, + type: "dropdown", + populators: !checkCondtions ? null : ( + + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + { + label: t("TL_APPROVAL_CHECKLIST_BUTTON_UP_FILE"), + populators: ( + { + setUploadedFile(null); + }} + message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`CS_ACTION_NO_FILEUPLOADED`)} + /> + ) + }, + // { + // label: action.docUploadRequired ? t("ES_PT_UPLOAD_FILE") : null, + // populators: action.docUploadRequired ? ( + // { + // setUploadedFile(null); + // }} + // message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`ES_PT_ACTION_NO_FILEUPLOADED`)} + // /> + // ) : null, + // }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/WSApproverApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/WSApproverApplication.js new file mode 100644 index 00000000..2f5f2d45 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/WSApproverApplication.js @@ -0,0 +1,73 @@ +import { Dropdown, UploadFile } from "@egovernments/digit-ui-react-components"; +import React from "react"; + +export const configWSApproverApplication = ({ + t, + action, + approvers, + selectedApprover, + setSelectedApprover, + selectFile, + uploadedFile, + setUploadedFile, + assigneeLabel, + businessService, + error +}) => { + let checkCondtions = true; + if (action?.action?.includes("SEND_BACK") || action?.action == "APPROVE_FOR_CONNECTION") checkCondtions = false; + if (action.isTerminateState) checkCondtions = false; + + return { + label: { + heading: `WF_${action?.action}_APPLICATION`, + submit: `WF_${businessService?.toUpperCase()}_${action?.action}`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_LABEL"), + placeholder: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + // isMandatory: false, + type: "dropdown", + populators: !checkCondtions ? null : ( + + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + { + label: t("WS_APPROVAL_CHECKLIST_BUTTON_UP_FILE"), + populators: ( + { + setUploadedFile(null); + }} + message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`CS_ACTION_NO_FILEUPLOADED`)} + error={error} + iserror={error} + /> + ) + }, + ], + }, + ], + }; +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/WSDisconnectApplication.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/WSDisconnectApplication.js new file mode 100644 index 00000000..5acdcebe --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/WSDisconnectApplication.js @@ -0,0 +1,89 @@ +import { Dropdown, UploadFile, DatePicker } from "@egovernments/digit-ui-react-components"; +import React from "react"; + +export const configWSDisConnectApplication = ({ + t, + action, + approvers, + selectedApprover, + setSelectedApprover, + selectFile, + uploadedFile, + setUploadedFile, + assigneeLabel, + businessService, + error +}) => { + let checkCondtions = true, isDatePickerDisplay = false; + if (action?.action?.includes("SEND_BACK") || action?.action == "APPROVE_FOR_DISCONNECTION" || action?.action == "RESUBMIT_APPLICATION") checkCondtions = false; + if (action.isTerminateState) checkCondtions = false; + if (action?.action == "EXECUTE_DISCONNECTION" || action?.action == "DISCONNECTION_EXECUTED") isDatePickerDisplay = true; + + + return { + label: { + heading: `WF_${action?.action}_APPLICATION`, + submit: `WF_${businessService?.toUpperCase()}_${action?.action}`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_LABEL"), + placeholder: !checkCondtions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + // isMandatory: false, + type: "dropdown", + populators: !checkCondtions ? null : ( + + ), + }, + isDatePickerDisplay && { + label: t("ES_FSM_ACTION_SERVICE_DATE"), + isMandatory: isDatePickerDisplay ? true : false, + type: "custom", + populators: isDatePickerDisplay ? { + name: "date", + validation: { + required: true, + }, + // customProps: { max: Digit.Utils.date.getDate() }, + defaultValue: Digit.Utils.date.getDate(), + component: (props, customProps) => , + } : null, + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + { + label: t("WS_APPROVAL_CHECKLIST_BUTTON_UP_FILE"), + populators: ( + { + setUploadedFile(null); + }} + message={uploadedFile ? `1 ${t(`ES_PT_ACTION_FILEUPLOADED`)}` : t(`CS_ACTION_NO_FILEUPLOADED`)} + error={error} + iserror={error} + /> + ) + }, + ], + }, + ], + }; +}; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configApproveModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configApproveModal.js new file mode 100644 index 00000000..03beb885 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configApproveModal.js @@ -0,0 +1,53 @@ +import { Dropdown } from '@egovernments/digit-ui-react-components'; +import React, { useState } from 'react' + +const configApproveModal = ({ + t, + action +}) => { + if(action?.action === 'ADMINSANCTION'){ + return { + label: { + heading: `WORKS_APPROVE_ESTIMATE`, + submit: `WORKS_APPROVE_ESTIMATE`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ] + } + ] + } + + }else + return { + label: { + heading: `WORKS_APPROVE_LOI`, + submit: `WORKS_APPROVE_LOI`, + cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ] + } + ] + } +} + +export default configApproveModal \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceApproveModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceApproveModal.js new file mode 100644 index 00000000..06a29a26 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceApproveModal.js @@ -0,0 +1,27 @@ + +const configAttendanceApproveModal = ({ t, action }) => { + if (action?.applicationStatus === "APPROVED") { + return { + label: { + heading: t("ATM_PROCESSINGMODAL_HEADER"), + submit: t("ATM_FORWARD_FOR_APPROVAL"), + cancel: t("CS_COMMON_CANCEL"), + }, + form: [ + { + body: [ + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ], + }, + ] + }; + } +}; + +export default configAttendanceApproveModal; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceCheckModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceCheckModal.js new file mode 100644 index 00000000..374219cc --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceCheckModal.js @@ -0,0 +1,93 @@ +const configAttendanceCheckModal = ({ + t, + action, + businessService, + approvers, + selectedApprover, + setSelectedApprover, + designation, + selectedDesignation, + setSelectedDesignation, + department, + selectedDept, + setSelectedDept, + approverLoading = false, +}) => { + let checkConditions = true; + if (action.isTerminateState) checkConditions = false; + + if (designation?.length === 0 || department?.length === 0) return {}; + + if (action?.applicationStatus === "ATTENDANCE_CHECKED") { + return { + label: { + heading: t("ATM_PROCESSINGMODAL_HEADER"), + submit: t("ATM_FORWARD_FOR_CHECK"), + cancel: t("WORKS_CANCEL"), + }, + form: [ + { + body: [ + { + isMandatory: true, + key: "department", + type: "radioordropdown", + label: !checkConditions ? null : t("ATM_APPROVER_DEPT"), + disable: false, + populators: { + name: "department", + optionsKey: "i18nKey", + error: "Department is required", + required: true, + options: department, + }, + }, + { + isMandatory: true, + key: "designation", + type: "radioordropdown", + label: !checkConditions ? null : t("ATM_APPROVER_DESIGNATION"), + disable: false, + populators: { + name: "designation", + optionsKey: "i18nKey", + error: "Designation is required", + required: true, + options: designation, + }, + }, + { + isMandatory: true, + key: "approvers", + type: "radioordropdown", + label: !checkConditions ? null : t("WORKS_APPROVER"), + disable: false, + populators: { + name: "approvers", + optionsKey: "nameOfEmp", + error: "Designation is required", + required: true, + options: approvers, + }, + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ], + }, + ], + defaultValues: { + department: "", + designation: "", + approvers: "", + comments: "", + }, + }; + } +}; + +export default configAttendanceCheckModal; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceRejectModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceRejectModal.js new file mode 100644 index 00000000..c732127a --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configAttendanceRejectModal.js @@ -0,0 +1,61 @@ +import { LabelFieldPair,CardLabel} from '@egovernments/digit-ui-react-components'; +import React from 'react' + +const configAttendanceRejectModal = ({ + t, + empDepartment, + empDesignation, + empName +}) => { + + const fieldLabelStyle = { + "display" : "grid", + "gridTemplateColumns" : "60% 1fr" + }; + + return { + label: { + heading: t("ATM_PROCESSINGMODAL_HEADER"), + submit: t("ATM_CONFIRM_REJECT"), + cancel: t("CS_COMMON_CANCEL"), + }, + form: [ + { + body: [ + { + withoutLabel:true, + populators: + {t("ATM_DEPARTMENT")} + {empDepartment} + , + }, + { + withoutLabel:true, + populators: + {t("ATM_DESIGNATION")} + {empDesignation} + , + }, + { + withoutLabel:true, + populators: + {t("ATM_REJECTED_BY")} + {empName} + , + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + key: "org_name", + populators: { + name: "comments", + }, + }, + ] + } + ] + } + +} + +export default configAttendanceRejectModal \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configCheckModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configCheckModal.js new file mode 100644 index 00000000..c267eb9f --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configCheckModal.js @@ -0,0 +1,105 @@ +import { Dropdown,Loader } from '@egovernments/digit-ui-react-components'; +import React,{useState} from 'react' + +const configCheckModal = ({ + t, + action, + businessService, + approvers, + selectedApprover, + setSelectedApprover, + designation, + selectedDesignation, + setSelectedDesignation, + department, + selectedDept, + setSelectedDept, + approverLoading=false, +}) => { + + let checkConditions = true + if (action.isTerminateState) checkConditions = false; + + if(designation?.length===0 || department?.length===0) return {} + + return { + label: { + heading: `WORKS_CHECK_FORWARD`, + submit: `WORKS_FORWARD_FOR_APPROVAL`, + cancel: "WORKS_CANCEL", + }, + form: [ + { + body:[ + { + label: !checkConditions ? null : t("WORKS_APPROVER_DEPT"), + placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + isMandatory: true, + type: "goToDefaultCase", + populators: !checkConditions ? null : ( + { + setSelectedDept(val) + setSelectedApprover("") + //setValue() + }} + selected={selectedDept} + t={t} + /> + ), + }, + { + label: !checkConditions ? null : t("WORKS_APPROVER_DESIGNATION"), + //placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + isMandatory: true, + type: "goToDefaultCase", + populators: !checkConditions ? null : ( + { + setSelectedDesignation(val) + setSelectedApprover("") + //resetting approver dropdown when dept/designation changes + }} + selected={selectedDesignation} + t={t} + /> + ), + }, + { + label: !checkConditions ? null : t("WORKS_APPROVER"), + //placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + isMandatory: true, + type: "goToDefaultCase", + populators: !checkConditions ? null : ( + approverLoading ? : + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ] + } + ] + } +} + +export default configCheckModal \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configRejectModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configRejectModal.js new file mode 100644 index 00000000..ae4be5af --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configRejectModal.js @@ -0,0 +1,127 @@ +import { Dropdown,LabelFieldPair,CardLabel} from '@egovernments/digit-ui-react-components'; +import React, { useState } from 'react' + +const configRejectModal = ({ + t, + action, + rejectReasons, + selectedReason, + setSelectedReason, + loiNumber, + department, + estimateNumber +}) => { + + let checkConditions = true + if (action.isTerminateState) checkConditions = false; + + if(rejectReasons?.length === 0) return {} + if(loiNumber){ + return { + label: { + heading: `WORKS_REJECT_LOI`, + submit: `WORKS_REJECT_LOI`, + //cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + withoutLabel:true, + populators: + {t("WORKS_DEPARTMENT")} + {"ENGG"} + , + }, + { + //label: t("WORKS_LOI_ID"), + //type: "text", + withoutLabel: true, + populators: + {t("WORKS_LOI_ID")} + {loiNumber} + + }, + { + label: !checkConditions ? null : t("WORKS_REJECT_REASON"), + //placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + // isMandatory: false, + type: "goToDefaultCase", + populators: !checkConditions ? null : ( + + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ] + } + ] + } + }else{ + return { + label: { + heading: `WORKS_REJECT_ESTIMATE`, + submit: `WORKS_REJECT_ESTIMATE`, + //cancel: "CS_COMMON_CANCEL", + }, + form: [ + { + body: [ + { + withoutLabel:true, + populators: + {t("WORKS_DEPARTMENT")} + {"ENGG"} + , + }, + { + //label: t("WORKS_LOI_ID"), + //type: "text", + withoutLabel: true, + populators: + {t("WORKS_ESTIMATE_ID")} + {estimateNumber} + + }, + { + label: !checkConditions ? null : t("WORKS_REJECT_REASON"), + //placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + // isMandatory: false, + type: "goToDefaultCase", + populators: !checkConditions ? null : ( + + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ] + } + ] + } + + } +} + +export default configRejectModal \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillApproveModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillApproveModal.js new file mode 100644 index 00000000..cd01fdc4 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillApproveModal.js @@ -0,0 +1,57 @@ +import React from 'react' +import { LabelFieldPair,CardLabel} from '@egovernments/digit-ui-react-components'; + +const configViewBillApprovalModal = ({ + t, +}) => { + const fieldLabelStyle = { + "display" : "grid", + "gridTemplateColumns" : "60% 1fr" + }; + return { + label: { + heading: t("EXP_PROCESSINGMODAL_HEADER"), + submit: t("EXP_FORWARD_FOR_APPROVAL"), + cancel: t("CS_COMMON_CANCEL"), + }, + form: [ + { + body: [ + { + withoutLabel:true, + populators: + {t("EXP_DEPARTMENT")} + Engineering + , + }, + { + withoutLabel:true, + populators: + {t("EXP_DESIGNATION")} + Junior Engineer + , + }, + { + withoutLabel:true, + populators: + {t("EXP_APPROVER")} + {"RASHMI"} + , + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ], + }, + ], + defaultValues: { + comments: "", + }, + }; +} + +export default configViewBillApprovalModal \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillCheckModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillCheckModal.js new file mode 100644 index 00000000..53204b28 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillCheckModal.js @@ -0,0 +1,107 @@ +import { Dropdown, Loader } from '@egovernments/digit-ui-react-components'; +import React, { useState } from 'react' + +const configViewBillCheckModal = ({ + t, + approvers, + selectedApprover, + setSelectedApprover, + designation, + selectedDesignation, + setSelectedDesignation, + department, + selectedDept, + setSelectedDept, + approverLoading = false, +}) => { + + let checkConditions = true + + + if (designation?.length === 0 || department?.length === 0) return {} + + return { + label: { + heading: t("EXP_FORWARD_BILL_FOR_APPROVAL"), + submit: t("EXP_FORWARD_BILL_FOR_APPROVAL"), + cancel: t("CS_COMMON_CANCEL"), + }, + form: [ + { + body: [ + { + label: !checkConditions ? null : t("WORKS_APPROVER_DEPT"), + placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + isMandatory: true, + type: "goToDefaultCase", + populators: !checkConditions ? null : ( + { + setSelectedDept(val) + setSelectedApprover("") + //setValue() + }} + selected={selectedDept} + t={t} + /> + ), + }, + { + label: !checkConditions ? null : t("WORKS_APPROVER_DESIGNATION"), + //placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + isMandatory: true, + type: "goToDefaultCase", + name: "designation", + populators: !checkConditions ? null : ( + { + setSelectedDesignation(val) + setSelectedApprover("") + //resetting approver dropdown when dept/designation changes + }} + selected={selectedDesignation} + t={t} + /> + ), + }, + { + label: !checkConditions ? null : t("WORKS_APPROVER"), + //placeholder: !checkConditions ? null : t("WF_ASSIGNEE_NAME_PLACEHOLDER"), + isMandatory: true, + type: "goToDefaultCase", + populators: !checkConditions ? null : ( + approverLoading ? : + ), + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ] + } + ] + } +} + +export default configViewBillCheckModal; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillRejectModal.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillRejectModal.js new file mode 100644 index 00000000..716d6179 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/configViewBillRejectModal.js @@ -0,0 +1,59 @@ +import React from 'react' +import { LabelFieldPair,CardLabel} from '@egovernments/digit-ui-react-components'; + +const configViewBillRejectModal = ({ + t, +}) => { + + const fieldLabelStyle = { + "display" : "grid", + "gridTemplateColumns" : "60% 1fr" + }; + + return { + label: { + heading: t("EXP_PROCESSINGMODAL_HEADER"), + submit: t("EXP_CONFIRM_REJECT"), + cancel: t("CS_COMMON_CANCEL"), + }, + form: [ + { + body: [ + { + withoutLabel:true, + populators: + {t("EXP_DEPARTMENT")} + Engineering + , + }, + { + withoutLabel:true, + populators: + {t("EXP_DESIGNATION")} + Junior Engineer + , + }, + { + withoutLabel:true, + populators: + {t("EXP_REJECTED_BY")} + {"RASHMI"} + , + }, + { + label: t("WF_COMMON_COMMENTS"), + type: "textarea", + populators: { + name: "comments", + }, + }, + ] + } + ], + defaultValues : { + comments : "", + } + } +} + +export default configViewBillRejectModal \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/index.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/index.js new file mode 100644 index 00000000..a736b8ed --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/config/index.js @@ -0,0 +1,47 @@ +import { configAssignDso } from "./AssignDso"; +import { configCompleteApplication } from "./CompleteApplication"; +import { configReassignDSO } from "./ReassignDso"; +import { configRejectApplication } from "./RejectApplication"; +import { configAcceptDso } from "./AcceptDso"; +import { configPTApproverApplication } from "./PTApproverApplication"; +import { configPTAssessProperty } from "./PTAssessProperty"; +import { configTLApproverApplication } from "./TLApproverApplication"; +import { configBPAREGApproverApplication } from "./BPAREGApproverApplication"; +import { configBPAApproverApplication } from "./BPAApproverApplication"; +import { configNOCApproverApplication } from "./NOCApproverApplication"; +import { configWSApproverApplication } from "./WSApproverApplication"; +import { configWSDisConnectApplication } from "./WSDisconnectApplication"; +import configCheckModal from "./configCheckModal" +import configApproveModal from "./configApproveModal" +import configRejectModal from "./configRejectModal" +import configAttendanceApproveModal from "./configAttendanceApproveModal"; +import configAttendanceCheckModal from "./configAttendanceCheckModal"; +import configAttendanceRejectModal from "./configAttendanceRejectModal"; +import configViewBillApproveModal from "./configViewBillApproveModal"; +import configViewBillCheckModal from "./configViewBillCheckModal"; +import configViewBillRejectModal from "./configViewBillRejectModal"; + +export { + configAttendanceRejectModal, + configAttendanceCheckModal, + configAttendanceApproveModal, + configCheckModal, + configApproveModal, + configRejectModal, + configAssignDso, + configCompleteApplication, + configReassignDSO, + configRejectApplication, + configAcceptDso, + configPTApproverApplication, + configPTAssessProperty, + configTLApproverApplication, + configBPAREGApproverApplication, + configBPAApproverApplication, + configNOCApproverApplication, + configWSApproverApplication, + configWSDisConnectApplication, + configViewBillRejectModal, + configViewBillCheckModal, + configViewBillApproveModal +}; diff --git a/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/index.js b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/index.js new file mode 100644 index 00000000..feb622ab --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/modules/templates/ApplicationDetails/index.js @@ -0,0 +1,368 @@ +import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useQueryClient } from "react-query"; +import { format } from "date-fns"; + +import { Loader } from "@egovernments/digit-ui-react-components"; + +import ActionModal from "./Modal"; + +import { useHistory, useParams } from "react-router-dom"; +import ApplicationDetailsContent from "./components/ApplicationDetailsContent"; +import ApplicationDetailsToast from "./components/ApplicationDetailsToast"; +import ApplicationDetailsActionBar from "./components/ApplicationDetailsActionBar"; +import ApplicationDetailsWarningPopup from "./components/ApplicationDetailsWarningPopup"; + +const ApplicationDetails = (props) => { + const tenantId = Digit.ULBService.getCurrentTenantId(); + const state = Digit.ULBService.getStateId(); + const { t } = useTranslation(); + const history = useHistory(); + let { id: applicationNumber } = useParams(); + const [displayMenu, setDisplayMenu] = useState(false); + const [selectedAction, setSelectedAction] = useState(null); + const [showModal, setShowModal] = useState(false); + const [isEnableLoader, setIsEnableLoader] = useState(false); + const [isWarningPop, setWarningPopUp] = useState(false); + const [modify, setModify] = useState(false); + const [saveAttendanceState, setSaveAttendanceState] = useState({ displaySave : false, updatePayload: []}) + + const { + applicationDetails, + showToast, + setShowToast, + isLoading, + isDataLoading, + applicationData, + mutate, + nocMutation, + workflowDetails, + businessService, + closeToast, + moduleCode, + timelineStatusPrefix, + forcedActionPrefix, + statusAttribute, + ActionBarStyle, + MenuStyle, + paymentsList, + showTimeLine = true, + oldValue, + isInfoLabel = false, + clearDataDetails, + noBoxShadow, + sectionHeadStyle, + showActionBar = true + } = props; + + useEffect(() => { + if (showToast) { + workflowDetails.revalidate(); + } + }, [showToast]); + + function onActionSelect(action) { + if (action) { + if(action?.isToast){ + setShowToast({ key: "error", error: { message: action?.toastMessage } }); + setTimeout(closeToast, 5000); + } + else if (action?.isWarningPopUp) { + setWarningPopUp(true); + } else if (action?.redirectionUrll) { + //here do the loi edit upon rejection + if (action?.redirectionUrll?.action === "EDIT_LOI_APPLICATION") { + history.push(`${action?.redirectionUrll?.pathname}`, { data: action?.redirectionUrll?.state }); + } + if (action?.redirectionUrll?.action === "EDIT_ESTIMATE_APPLICATION") { + history.push(`${action?.redirectionUrll?.pathname}`,{ data: action?.redirectionUrll?.state }); + } + + } else if (!action?.redirectionUrl) { + if(action?.action === 'EDIT') setModify(true) + else setShowModal(true); + } else { + history.push({ + pathname: action.redirectionUrl?.pathname, + state: { ...action.redirectionUrl?.state }, + }); + } + } + setSelectedAction(action); + setDisplayMenu(false); + } + + const queryClient = useQueryClient(); + + const closeModal = () => { + setSelectedAction(null); + setShowModal(false); + }; + + const closeWarningPopup = () => { + setWarningPopUp(false); + }; + + const getResponseHeader = (action) => { + + if(action?.includes("CHECK")){ + return t("WORKS_LOI_RESPONSE_FORWARD_HEADER") + } else if (action?.includes("APPROVE")){ + return t("WORKS_LOI_RESPONSE_APPROVE_HEADER") + }else if(action?.includes("REJECT")){ + return t("WORKS_LOI_RESPONSE_REJECT_HEADER") + } + } + + const getResponseMessage = (action,updatedLOI) => { + + if (action?.includes("CHECK")) { + return t("WORKS_LOI_RESPONSE_MESSAGE_CHECK", { loiNumber: updatedLOI?.letterOfIndentNumber,name:"Nipun",designation:"SE" }) + } else if (action?.includes("APPROVE")) { + return t("WORKS_LOI_RESPONSE_MESSAGE_APPROVE", { loiNumber: updatedLOI?.letterOfIndentNumber }) + } else if (action?.includes("REJECT")) { + return t("WORKS_LOI_RESPONSE_MESSAGE_REJECT", { loiNumber: updatedLOI?.letterOfIndentNumber }) + } + } + + const getEstimateResponseHeader = (action) => { + + if(action?.includes("CHECK")){ + return t("WORKS_ESTIMATE_RESPONSE_FORWARD_HEADER") + } else if (action?.includes("TECHNICALSANCATION")){ + return t("WORKS_ESTIMATE_RESPONSE_FORWARD_HEADER") + }else if (action?.includes("ADMINSANCTION")){ + return t("WORKS_ESTIMATE_RESPONSE_APPROVE_HEADER") + }else if(action?.includes("REJECT")){ + return t("WORKS_ESTIMATE_RESPONSE_REJECT_HEADER") + } + } + + const getEstimateResponseMessage = (action,updatedEstimate) => { + + if (action?.includes("CHECK")) { + return t("WORKS_ESTIMATE_RESPONSE_MESSAGE_CHECK", { estimateNumber: updatedEstimate?.estimateNumber,Name:"Super",Designation:"SE",Department:"Health" }) + } else if (action?.includes("TECHNICALSANCATION")) { + return t("WORKS_ESTIMATE_RESPONSE_MESSAGE_CHECK", { estimateNumber: updatedEstimate?.estimateNumber,Name:"Super",Designation:"SE",Department:"Health" }) + } else if (action?.includes("ADMINSANCTION")) { + return t("WORKS_ESTIMATE_RESPONSE_MESSAGE_APPROVE", { estimateNumber: updatedEstimate?.estimateNumber }) + } else if (action?.includes("REJECT")) { + return t("WORKS_ESTIMATE_RESPONSE_MESSAGE_REJECT", { estimateNumber: updatedEstimate?.estimateNumber }) + } + } + + const getAttendanceResponseHeaderAndMessage = (action) => { + let response = {} + if (action?.includes("VERIFY")) { + response.header = t("ATM_ATTENDANCE_VERIFIED") + response.message = t("ATM_ATTENDANCE_VERIFIED_SUCCESS") + } else if (action?.includes("REJECT")) { + response.header = t("ATM_ATTENDANCE_REJECTED") + response.message = t("ATM_ATTENDANCE_REJECTED_SUCCESS") + } else if (action?.includes("APPROVE")) { + response.header = t("ATM_ATTENDANCE_APPROVED") + response.message = t("ATM_ATTENDANCE_APPROVED_SUCCESS") + } + return response + } + + const submitAction = async (data, nocData = false, isOBPS = {}) => { + const performedAction = data?.workflow?.action + setIsEnableLoader(true); + if (mutate) { + setIsEnableLoader(true); + mutate(data, { + onError: (error, variables) => { + setIsEnableLoader(false); + setShowToast({ key: "error", error }); + setTimeout(closeToast, 5000); + }, + onSuccess: (data, variables) => { + setIsEnableLoader(false); + //just history.push to the response component from here and show relevant details + if(data?.letterOfIndents?.[0]){ + const updatedLOI = data?.letterOfIndents?.[0] + const state = { + header:getResponseHeader(performedAction,updatedLOI), + id: updatedLOI?.letterOfIndentNumber, + info: t("WORKS_LOI_ID"), + message: getResponseMessage(performedAction,updatedLOI), + links: [ + { + name: t("WORKS_CREATE_NEW_LOI"), + redirectUrl: `/${window.contextPath}/employee/works/create-loi`, + code: "", + svg: "CreateEstimateIcon", + isVisible:false, + type:"add" + }, + { + name: t("WORKS_GOTO_LOI_INBOX"), + redirectUrl: `/${window.contextPath}/employee/works/LOIInbox`, + code: "", + svg: "CreateEstimateIcon", + isVisible:true, + type:"inbox" + }, + ], + responseData:data, + requestData:variables + } + history.push(`/${window.contextPath}/employee/works/response`, state) + } + if(data?.estimates?.[0]){ + const updatedEstimate = data?.estimates?.[0] + const state = { + header:getEstimateResponseHeader(performedAction,updatedEstimate), + id: updatedEstimate?.estimateNumber, + info: t("WORKS_ESTIMATE_ID"), + message: getEstimateResponseMessage(performedAction,updatedEstimate), + links: [ + { + name: t("WORKS_CREATE_ESTIMATE"), + redirectUrl: `/${window.contextPath}/employee/works/create-estimate`, + code: "", + svg: "CreateEstimateIcon", + isVisible:false, + type:"add" + }, + { + name: t("WORKS_GOTO_ESTIMATE_INBOX"), + redirectUrl: `/${window.contextPath}/employee/works/inbox`, + code: "", + svg: "RefreshIcon", + isVisible:true, + type:"inbox" + }, + ], + responseData:data, + requestData:variables + } + history.push(`/${window.contextPath}/employee/works/response`, state) + } + if (isOBPS?.bpa) { + data.selectedAction = selectedAction; + history.replace(`/${window?.contextPath}/employee/obps/response`, { data: data }); + } + if (isOBPS?.isStakeholder) { + data.selectedAction = selectedAction; + history.push(`/${window?.contextPath}/employee/obps/stakeholder-response`, { data: data }); + } + if (isOBPS?.isNoc) { + history.push(`/${window?.contextPath}/employee/noc/response`, { data: data }); + } + if (data?.Amendments?.length > 0 ){ + //RAIN-6981 instead just show a toast here with appropriate message + //show toast here and return + //history.push("/${window?.contextPath}/employee/ws/response-bill-amend", { status: true, state: data?.Amendments?.[0] }) + + if(variables?.AmendmentUpdate?.workflow?.action.includes("SEND_BACK")){ + setShowToast({ key: "success", label: t("ES_MODIFYSWCONNECTION_SEND_BACK_UPDATE_SUCCESS")}) + } else if (variables?.AmendmentUpdate?.workflow?.action.includes("RE-SUBMIT")){ + setShowToast({ key: "success", label: t("ES_MODIFYSWCONNECTION_RE_SUBMIT_UPDATE_SUCCESS") }) + } else if (variables?.AmendmentUpdate?.workflow?.action.includes("APPROVE")){ + setShowToast({ key: "success", label: t("ES_MODIFYSWCONNECTION_APPROVE_UPDATE_SUCCESS") }) + } + else if (variables?.AmendmentUpdate?.workflow?.action.includes("REJECT")){ + setShowToast({ key: "success", label: t("ES_MODIFYWSCONNECTION_REJECT_UPDATE_SUCCESS") }) + } + return + } + if(data?.musterRolls?.[0]) { + const musterRoll = data?.musterRolls?.[0] + const response = getAttendanceResponseHeaderAndMessage(performedAction) + const state = { + header: response?.header, + message: response?.message, + info: t("ATM_REGISTER_ID_WEEK"), + id: `${musterRoll.registerId} | ${format(new Date(musterRoll.startDate), "dd/MM/yyyy")} - ${format(new Date(musterRoll.endDate), "dd/MM/yyyy")}`, + } + history.push(`/${window.contextPath}/employee/attendencemgmt/response`, state) + } + setShowToast({ key: "success", action: selectedAction }); + clearDataDetails && setTimeout(clearDataDetails, 3000); + setTimeout(closeToast, 5000); + queryClient.clear(); + queryClient.refetchQueries("APPLICATION_SEARCH"); + //push false status when reject + + }, + }); + } + + closeModal(); + }; + + if (isLoading || isEnableLoader) { + return ; + } + + return ( + + {!isLoading ? ( + + + {showModal ? ( + + ) : null} + {isWarningPop ? ( + + ) : null} + + {showActionBar && } + + ) : ( + + )} + + ); +}; + +export default ApplicationDetails; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/.babelrc b/micro-ui/web/micro-ui-internals/packages/ui-components/.babelrc new file mode 100644 index 00000000..e77a2b3d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-react"], + "plugins": ["@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-optional-chaining"] + } \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/.gitignore b/micro-ui/web/micro-ui-internals/packages/ui-components/.gitignore new file mode 100644 index 00000000..1747c795 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/.gitignore @@ -0,0 +1,143 @@ +# Created by https://www.toptal.com/developers/gitignore/api/node,react +# Edit at https://www.toptal.com/developers/gitignore?templates=node,react + +### eGov ### +packages/css/example/index.css +package-lock.json +locales/ +build/ +packages/**/dist/ + +# yarn # +.yarn +.yarnrc.yml + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test +.env*.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist +dist-storybook + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +### react ### +.DS_* +**/*.backup.* +**/*.back.* + +node_modules + +*.sublime* + +psd +thumb +sketch + +# vs code +.vscode/ + +# End of https://www.toptal.com/developers/gitignore/api/node,react \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/main.js b/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/main.js new file mode 100644 index 00000000..3daf2f52 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/main.js @@ -0,0 +1,14 @@ +module.exports = { + stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], + addons: ["@storybook/addon-links", "@storybook/addon-essentials","@storybook/addon-postcss"], + docs: { + autodocs: 'tag', + }, + titlePrefix: 'MyComponents', + features: { + postcss: false, + }, +}; + + + diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/preview-head.html b/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/preview-head.html new file mode 100644 index 00000000..d59ccaf7 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/preview-head.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + +
+ \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/preview.js b/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/preview.js new file mode 100644 index 00000000..043db6e5 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/.storybook/preview.js @@ -0,0 +1,56 @@ +// import "@egovernments/digit-ui-components-css/example/index.css"; +import "@egovernments/digit-ui-components-css/dist/index.css"; +// import { initCoreLibraries } from "@egovernments/digit-ui-libraries-core"; +import { initLibraries } from "@egovernments/digit-ui-libraries"; + +// import '../src/index.css'; +//:point_down: Configures Storybook to log the actions( onArchiveTask and onPinTask ) in the UI. +/** @type { import('@storybook/react').Preview } */ + +export const globalTypes = { + theme: { + description: "Global theme for components", + defaultValue: "light", + toolbar: { + // The label to show for this toolbar item + title: "Theme", + icon: "circlehollow", + // Array of plain string values or MenuItem shape (see below) + items: ["light", "dark"], + // Change title based on selected value + dynamicTitle: true, + }, + }, +}; + +const preview = { + parameters: { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + expanded: true, + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + backgrounds: { + default: "twitter", + values: [ + { + name: "twitter", + value: "#00ACED", + }, + { + name: "facebook", + value: "#3B5998", + }, + ], + }, + }, +}; + +initLibraries().then(() => { + console.info("DIGIT Contant, HOOKS enabled", window?.Digit); +}); + +export default preview; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/CHANGELOG.md b/micro-ui/web/micro-ui-internals/packages/ui-components/CHANGELOG.md new file mode 100644 index 00000000..f7c05137 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/CHANGELOG.md @@ -0,0 +1,473 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +### [0.2.0-beta.8] - 2025-04-03 +## Updates +- Version Update for stability + +### [0.2.0-beta.7] - 2025-03-26 +## Enhancements & New features +## Edit Row data within InboxSearchComposer within rows and with popups based on config +## Added customizers support i.e., we don't need to mention functions in UICustomizations.js we can directly mention within component level + +### [0.2.0-beta.5] - 2025-03-26 +## Fixes +- Fixed Tab Functionality in InboxSearchComposer + +### [0.2.0-beta.3] - 2025-03-20 +## Fixes +- Fixed multiple calls issue in InboxSearchLinks +- Fixed onSubmit function for FilterCard + +### [0.2.0-beta.2] - 2025-03-13 +## Enhancements +- Multiselect Dropdown now supports adding limit for chips and onClick function + +## New Changes Added +- InboxSearchComposer now supports footer actions +- Updated the config structure for results table - inbox and search screens + + +## [0.2.0-beta.1] - 2025-03-06 +## New Components Added +- ResultsDataTableWrapper and ResultsDataTable components were added +- Integrated InboxSearchComposer with ResultsDataTableWrapper + +## Enhancements in Multiselectdropdown +- Limiting chips to be shown functionality +- Frozen Data functionality +- Searchable functionality for nested multiselect variant + +## Other Changes +- Added onClose function as a prop in SidePanel + +## [0.2.0] - 2025-02-19 +### New Components Added + +## Atoms +- Accordion +- ActionButton +- AlertCard +- BackLink +- BreadCrumb +- Button +- CheckBox +- Chip +- Divider +- Dropdown +- Panels +- FileUpload +- Loader +- MultiselectDropdown +- OTPInput +- RadioButton +- SelectionTag +- Stepper +- Switch +- Tab +- Tag +- TextBlock +- TextInput +- Timeline +- Toast +- Toggle +- Tooltip + +## Molecules +- AccordionList +- PopUp +- Card (Basic,FormCard,SummaryCard) +- BottomSheet +- ButtonGroup +- Header +- SidePanel +- PanelCard +- FilterCard +- Footer +- Hamburger +- LandingPageCard +- MenuCard +- MetricCard +- SideNav +- TableMolecule +- TimelineMolecule +- TooltipWrapper + +## MoleculeGroup +- LandingPageWrapper +- MenuCardWrapper + +### New Changes Added +- Added external link support in LandingPageCards +- Added external link support in BreadCrumbs +- Added Spacers, Colors, Typography library +- Added Icons +- Added Animations +- Added Error Message Component. +- Added Info Button Component. +- Added RemoveableTag Component. +- Added Uploader Component With Three Varinats UploadFile,UploadPopup and UploadImage. +- Supporting multiple variants in Dropdown and MultiSelectDropdown components + + +## [0.0.2-beta.66] - 2025-02-13 +### New Changes +- Added id prop for checkox input + +## [0.0.2-beta.65] - 2025-01-27 +### New Changes +- ViewCard is renamed as SummaryCard +- ViewCardFieldPair is renamed as SummaryCardFieldPair +- Header is renamed as HeaderComponent +- TopBar is renamed as Header +- Hamburger is renamed as HamburgerButton +- MobileSideNav is renamed as Hamburger +- LoaderScreen Component is removed +- LoaderComponent is renamed as Loader + +## [0.0.2-beta.60] - 2024-12-26 +### New Changes +- SelectionCard Component is renamed as SelectionTag Component +- AccordionWrapper Molecule is renamed as AccordionList +- Sidebar Molecule is renamed as SideNav +- MobileSideBar Molecule is renamed as MobileSideNav +- SlideOverMenu Molecule is renamed as SidePanel +- InfoCard Component is renamed as AlertCard +- Uploader Component is renamed as FileUpload +- ActionBar Component is renamed as Footer + +## [0.0.2-beta.56] - 2024-11-16 +### New Changes +- Added id for every field use with digit-ui-libraries with v1.8.5 for proper integartion + +## [0.0.2-beta.54] - 2024-11-16 +### New Changes +- Fixed Navigation redirection for landing page card if it is an external url. + + +## [0.0.2-beta.51] - 2024-11-06 +### New Changes +- ButtonsGroup has been renamed as ButtonGroup + +## [0.0.2-beta.50] - 2024-10-29 +### New Changes +- Updated Breadcrumb crumb.path property to crumb.internalLink or crumb.externalLink + +## [0.0.2-beta.46] - 2024-10-11 +### New Changes +- Added MaterialUI Icons,Updated Colors and Spacers Stories + +## [0.0.2-beta.44] - 2024-10-07 +### New Changes +- Added NestedTable, FilterCard and FormCards + +## [0.0.2-beta.42] - 2024-09-23 +### New Changes +- Added Table Molecule + +## [0.0.2-beta.41] - 2024-09-19 +### New Changes +- Added OTPInput + +## [0.0.2-beta.40] - 2024-09-18 +### New Changes +- Added ChipsKey for Multiselectdropdown and configuration for close icon in chips + +## [0.0.2-beta.39] - 2024-09-12 +### New Changes +- Added Tab Component and other changes + +## [0.0.2-beta.38] - 2024-09-12 +### fixes +- Css version fix + +## [0.0.2-beta.37] - 2024-09-06 +### New Changes +- Css version fix + +## [0.0.2-beta.36] - 2024-09-06 +### New Changes +- Updated SelectionCard Component + +## [0.0.2-beta.35] - 2024-09-06 +### New Changes +- Added LandingPageCard,MenuCard Molecules + +## [0.0.2-beta.34] - 2024-09-05 +### New Changes +- Updated Accordion with animation + +## [0.0.2-beta.33] - 2024-09-04 +### New Changes +- Added BottomSheet Draggable Functionality + +## [0.0.2-beta.32] - 2024-09-04 +### New Changes +- Updated Tooltip with header and description + +## [0.0.2-beta.28] - 2024-08-29 +### New Changes +- Updated Sidebar and added AccordionWrapper + +## [0.0.2-beta.27] - 2024-08-27 +### New Changes +- Fixed MobileSidebar issue + +## [0.0.2-beta.26] - 2024-08-27 +### New Changes +- Changed Classname for Submitbar disabled + +## [0.0.2-beta.25] - 2024-08-22 +### New Changes +- Updated Sidebar,SVGs,Added Spacers and Accordion + +## [0.0.2-beta.24] - 2024-08-16 +### New Changes +- Added Switch Component + +## [0.0.2-beta.22] - 2024-08-07 +### New Changes +- Fixes on usgae of utils + +## [0.0.2-beta.22] - 2024-08-07 +### New Changes +- Updated Tooltip Component + +## [0.0.2-beta.21] - 2024-08-02 +### New Changes +- Added Tag Component + +## [0.0.2-beta.20] - 2024-07-30 +### New Changes +- Added Error State for Timeline, SelectionCard Component + +## [0.0.2-beta.18] - 2024-07-24 +### New Changes +- Fixed header dropdown selection + +## [0.0.2-beta.17] - 2024-07-23 +### New Changes +- Updated multiselectdropdown + +## [0.0.2-beta.16] - 2024-07-22 +### New Changes +- Updated prop for Menu + +## [0.0.2-beta.15] - 2024-07-18 +### New Changes +- Added translation for option label + +## [0.0.2-beta.14] - 2024-07-16 +### New Changes +- Added Sidebar and Hamburger +- Updated Colors as constants + + +## [0.0.2-beta.13] - 2024-07-08 +### New Changes +- Updated Button OnClick and added digit footer images + +## [0.0.2-beta.12] - 2024-07-05 +### New Changes +- Updated Button + + +## [0.0.2-beta.11] - 2024-07-04 +### New Changes +- Added ActionBar, Header, ActionButton variant for Button +- Updated Timeline Molecule + +## [0.0.2-beta.10] - 2024-06-28 +### New Changes +- Added Card Variants + +## [0.0.2-beta.9] - 2024-06-25 +### New Changes +- Updated Uploader preview + +## [0.0.2-beta.8] - 2024-06-24 +### New Changes +- Added Title prop for Button + +## [0.0.2-beta.7] - 2024-06-24 +### New Changes +- Added ViewMore button for Timeline Molecule. + +## [0.0.2-beta.6] - 2024-06-19 +### New Changes +- Added BreadCrumb Component. + +## [0.0.2-beta.5] - 2024-06-17 +### New Changes +- Added Timeline Molecule. + +## [0.0.2-beta.4] - 2024-06-15 +### Changed +- fix: Fixed prop for the document upload. + +## [0.0.2-beta.3] - 2024-06-14 +### Changed +- Updated Storybook +- Modified BackButton as BackLink + +## [0.0.2-beta.1] - 2024-06-04 +### Changed +- Updated Popup Classname +- Added InfoCard Header Classname + +## [0.0.2] - 2024-06-03 +- New components and enhancements for old components + +### New Changes + +- Added Error Message Component. +- Added Info Button Component. +- Added Panels Component. +- Added Popup Component With Two Variants defualt and alert. +- Added RemoveableTag Component. +- Added Stepper Component. +- Added TextBlock Component. +- Added Timeline Component. +- Added Uploader Component With Three Varinats UploadFile,UploadPopup and UploadImage. +- Added PanelCard Molecule. + +### Enhancements + +- Updated Button Component Styles. +- Updated Dropdown Component Styles and Added SelectAll Option. +- Updated InfoCard Component Styles. +- Added Animation for Toast. +- Added new prop named type for Toast replacing the separate props for `info`, `warning`, and `error`. +- Updated Typography with lineHeight +- Updated Color Typography + +## [0.0.1-beta.32] - YYYY-MM-DD +### Changed +- Updated Panel Success Animation + +## [0.0.1-beta.31] - YYYY-MM-DD +### Added +- New prop named `activeSteps` in Stepper + +## [0.0.1-beta.30] - YYYY-MM-DD +### Changed +- Updated Panel Animation Styles + +## [0.0.1-beta.29] - YYYY-MM-DD +### Added +- PopUp, Panels, and Panel Cards + +## [0.0.1-beta.28] - YYYY-MM-DD +### Added +- `restrictSelection` prop in MultiSelectDropdown + +## [0.0.1-beta.27] - YYYY-MM-DD +### Added +- Uploader variants and its CSS + +## [0.0.1-beta.26] - YYYY-MM-DD +### Changed +- Updated Toast Usage + +## [0.0.1-beta.25] - YYYY-MM-DD +### Changed +- Updated RemoveableTag component to have error + +## [0.0.1-beta.24] - YYYY-MM-DD +### Changed +- Updated numeric type to disable input and use only buttons +- Made date and time fields clickable + +## [0.0.1-beta.23] - YYYY-MM-DD +### Added +- New props `showIcon`, `truncateMessage`, and `maxLength` to ErrorMessage component + +## [0.0.1-beta.22] - YYYY-MM-DD +### Changed +- `Toast` component now has a new prop `type`, replacing the separate props for `info`, `warning`, and `error` + +## [0.0.1-beta.21] - YYYY-MM-DD +### Added +- `categorySelectAllState` in the nestedmultiselect variant of MultiSelectDropdown + +## [0.0.1-beta.20] - YYYY-MM-DD +### Changed +- Updated MultiSelectDropdown `categoryselectall` functionality +- Added key navigation for dropdown options + +## [0.0.1-beta.19] - YYYY-MM-DD +### Changed +- Made CheckBox more customizable +- Added custom color for Button + +## [0.0.1-beta.18] - YYYY-MM-DD +### Changed +- Updated dropdown option labels + +## [0.0.1-beta.17] - YYYY-MM-DD +### Changed +- Updated Toast info variant CSS +- Updated category option CSS + +## [0.0.1-beta.16] - YYYY-MM-DD +### Added +- Error boundary atom + +## [0.0.1-beta.15] - YYYY-MM-DD +### Added +- Info variant for Toast + +## [0.0.1-beta.14] - YYYY-MM-DD +### Changed +- Updated dropdown options label to use `optionsKey` + +## [0.0.1-beta.13] - YYYY-MM-DD +### Changed +- Updated nested and tree dropdown variant + +## [0.0.1-beta.12] - YYYY-MM-DD +### Changed +- Enhancements of components + +## [0.0.1-beta.11] - YYYY-MM-DD +### Changed +- Updated `mobilenumber` classname + +## [0.0.1-beta.10] - YYYY-MM-DD +### Changed +- Updated header and textinput classnames + +## [0.0.1-beta.9] - YYYY-MM-DD +### Changed +- Updated key to `IS_STRING_MANIPULATED` + +## [0.0.1-beta.8] - YYYY-MM-DD +### Changed +- Updated the string manipulation based on `globalConfig` flag `isStringManipulated` + +## [0.0.1-beta.7] - YYYY-MM-DD +### Changed +- Updated classnames + +## [0.0.1-beta.6] - YYYY-MM-DD +### Changed +- Updated version + +## [0.0.1-beta.5] - YYYY-MM-DD +### Changed +- Modified classnames + +## [0.0.1-beta.4] - YYYY-MM-DD +### Fixed +- Fixed some date issues + +## [0.0.1] - 2024-03-22 +### Added Base version +- Button Component. +- Dropdown Component. +- InfoCard Component. +- Toast. +- Input fields. diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/README.md b/micro-ui/web/micro-ui-internals/packages/ui-components/README.md new file mode 100644 index 00000000..da62ccff --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/README.md @@ -0,0 +1,137 @@ + +# digit-ui-components + +## Install + +```bash +npm install --save @egovernments/digit-ui-components +``` + +## Limitation + +```bash +This Package is more specific to DIGIT-UI's can be used across mission's +``` + +## Usage + +After adding the dependency make sure you have this dependency in + +```bash +frontend/micro-ui/web/package.json +``` + +```json +"@egovernments/digit-ui-components":"0.0.1", +``` + +then navigate to App.js + +```bash + frontend/micro-ui/web/src/App.js +``` + +# Syntax for importing any components + +```jsx +import { SVG } from "@egovernments/digit-ui-components"; + +; +``` + +# Local Development to check storybook +Use Node 14 version + +Step 1 + + ```bash +yarn install +``` + +Step 2 + + ```bash +yarn storybook +``` + +### New Changes + +## [0.0.1-beta.28] - 2024-05-24 + +- Added restrictSelection prop in Multiselectdropdown. If this is sent as true, it restricts any option to get selected. + + - Usage: + ```jsx + + ``` + +### Breaking Changes while migrating from any version below 0.0.1-beta.22 + +## [0.0.1-beta.22] - 2024-05-20 + +- Toast Component: From this version of `ui-components`, the `Toast` component has a new prop named `type`, replacing the separate props for `info`, `warning`, and `error`. + - Old Usage: + ```jsx + + + + ``` + - New Usage: + ```jsx + + + + + ``` + +## Changelog + +### Summary for Version [0.0.2] - 2024-06-03 + +#### New Changes + +- Added Error Message Component. +- Added Info Button Component. +- Added Panels Component. +- Added Popup Component with two variants: `default` and `alert`. +- Added RemoveableTag Component. +- Added Stepper Component. +- Added TextBlock Component. +- Added Timeline Component. +- Added Uploader Component with three variants: `UploadFile`, `UploadPopup`, and `UploadImage`. +- Added PanelCard Molecule. + +#### Enhancements + +- Updated Button Component Styles. +- Updated Dropdown Component Styles and added SelectAll Option. +- Updated InfoCard Component Styles. +- Added Animation for Toast. +- Added new prop `type` for Toast, replacing the separate props for `info`, `warning`, and `error`. +- Updated Typography with lineHeight. +- Updated Color Typography. + +For a detailed changelog, see the [CHANGELOG.md](./CHANGELOG.md) file. + +## Published from DIGIT-UI-LIBRARIES + +DIGIT-UI-LIBRARIES Repo (https://github.com/egovernments/DIGIT-UI-LIBRARIES/tree/master) + +# Contributors + +[nabeelmd-egov] [bhavya-eGov] [nipunarora-eGov] [swathi-egov] [jagankumar-egov] + +# Reference + +Storybook (https://unified-dev.digit.org/storybook/) + +Documentation (https://core.digit.org/guides/developer-guide/ui-developer-guide/digit-ui/ui-components-standardisation/digit-ui-components0.2.0) + +## License + +MIT © [jagankumar-egov](https://github.com/jagankumar-egov) + +![Logo](https://s3.ap-south-1.amazonaws.com/works-dev-asset/mseva-white-logo.png) + diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/docker/Dockerfile b/micro-ui/web/micro-ui-internals/packages/ui-components/docker/Dockerfile new file mode 100644 index 00000000..bdf0891c --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/docker/Dockerfile @@ -0,0 +1,20 @@ +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 yarn install \ + && yarn build-storybook + +FROM nginx:mainline-alpine +ENV WORK_DIR=/var/storybook + +RUN mkdir -p ${WORK_DIR} + +COPY --from=build /app/dist-storybook ${WORK_DIR}/ +COPY --from=build /app/docker/nginx.conf /etc/nginx/conf.d/default.conf \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/docker/nginx.conf b/micro-ui/web/micro-ui-internals/packages/ui-components/docker/nginx.conf new file mode 100644 index 00000000..e7c7c215 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/docker/nginx.conf @@ -0,0 +1,12 @@ +server +{ + listen 80; + underscores_in_headers on; + + location /storybook + { + root /var/; + index index.html index.htm; + try_files $uri $uri/ /storybook/index.html; + } +} \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/package.json b/micro-ui/web/micro-ui-internals/packages/ui-components/package.json new file mode 100644 index 00000000..7a52bf56 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/package.json @@ -0,0 +1,94 @@ +{ + "name": "@egovernments/digit-ui-components", + "version": "0.2.0-studio.1", + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.modern.js", + "source": "src/index.js", + "engines": { + "node": ">=14" + }, + "homepage": "https://unified-dev.digit.org/storybook/", + "author": "Jagankumar ", + "scripts": { + "example": "cd example && npm run start", + "build": "microbundle-crl --compress --no-sourcemap --format cjs", + "start": "microbundle-crl watch --no-compress --format modern,cjs", + "prepare": "yarn build", + "publish:components": "npm publish --tag core-v0.1", + "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 svg-components-$npm_package_version.surge.sh" + }, + "peerDependencies": { + "react": "17.0.2", + "react-dom": "17.0.2", + "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", + "@storybook/blocks":"8.3.5", + "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": "17.0.2", + "react-dom": "17.0.2", + "react-query": "3.6.1", + "react-responsive": "9.0.2", + "react-router-dom": "5.3.0", + "react-scripts": "^4.0.1" + }, + "files": [ + "dist" + ], + "dependencies": { + "react-data-table-component": "7.6.2", + "@egovernments/digit-ui-components-css": "0.2.1", + "@egovernments/digit-ui-libraries": "1.8.11", + "@egovernments/digit-ui-svg-components": "1.0.14", + "@googlemaps/js-api-loader": "1.13.10", + "autoprefixer": "^10.4.15", + "postcss-flexbugs-fixes": "^5.0.2", + "react-date-range": "1.3.0", + "react-hook-form": "6.15.8", + "react-i18next": "11.16.2", + "react-table": "7.7.0", + "react-drag-drop-files": "2.3.10", + "@cyntler/react-doc-viewer": "1.10.3", + "react-webcam":"7.2.0", + "react-lottie":"1.2.4", + "styled-components":"5.0.0" + }, + "resolutions": { + "styled-components": "5.0.0" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "keywords": [ + "digit", + "core", + "components", + "dpg" + ] +} + diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/postcss.config.js b/micro-ui/web/micro-ui-internals/packages/ui-components/postcss.config.js new file mode 100644 index 00000000..fb81ebad --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/postcss.config.js @@ -0,0 +1,8 @@ +module.exports = { + plugins: [ + require('postcss-flexbugs-fixes'), + require('autoprefixer'), + // Add more plugins as needed + ], + }; + \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/public/index.html b/micro-ui/web/micro-ui-internals/packages/ui-components/public/index.html new file mode 100644 index 00000000..6ee18937 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/public/index.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + + DIGIT Component StoryBook + + + + +
+ + + + \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms-groups/CustomDropdown.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms-groups/CustomDropdown.js new file mode 100644 index 00000000..550f629d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms-groups/CustomDropdown.js @@ -0,0 +1,71 @@ +import _ from "lodash"; +import React from "react"; +import { Loader } from "../atoms"; +import RadioButtons from "../atoms/RadioButtons"; +import Dropdown from "../atoms/Dropdown"; + +const CustomDropdown = ({ t, config, inputRef, label, onChange, value, errorStyle, disable, type, additionalWrapperClass = "" }) => { + const master = { name: config?.mdmsConfig?.masterName }; + if (config?.mdmsConfig?.filter) { + master["filter"] = config?.mdmsConfig?.filter; + } + const { isLoading, data } = Digit.Hooks.useCustomMDMS(Digit.ULBService.getStateId(), config?.mdmsConfig?.moduleName, [master], { + select: config?.mdmsConfig?.select + ? Digit.Utils.createFunction(config?.mdmsConfig?.select) + : (data) => { + const optionsData = _.get(data, `${config?.mdmsConfig?.moduleName}.${config?.mdmsConfig?.masterName}`, []); + return optionsData + .filter((opt) => (opt?.hasOwnProperty("active") ? opt.active : true)) + .map((opt) => ({ ...opt, name: `${config?.mdmsConfig?.localePrefix}_${Digit.Utils.locale.getTransformedLocale(opt.code)}` })); + }, + enabled: config?.mdmsConfig ? true : false, + }); + if (isLoading) { + return ; + } + + return ( + + {type === "radio" ? ( + { + onChange(e, config.name); + }} + disable={disable} + selectedOption={value} + defaultValue={value} + t={t} + errorStyle={errorStyle} + additionalWrapperClass={additionalWrapperClass} + innerStyles={config?.innerStyles} + /> + ) : ( + { + onChange(e, config.name); + }} + disable={disable} + selected={value || config.defaultValue} + defaultValue={value || config.defaultValue} + t={t} + errorStyle={errorStyle} + optionCardStyles={config?.optionsCustomStyle} + /> + )} + + ); +}; + +export default CustomDropdown; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms-groups/index.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms-groups/index.js new file mode 100644 index 00000000..4a8e1d5a --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms-groups/index.js @@ -0,0 +1,3 @@ +import CustomDropdown from "./CustomDropdown"; + +export { CustomDropdown }; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Accordion.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Accordion.js new file mode 100644 index 00000000..7b04e90f --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Accordion.js @@ -0,0 +1,186 @@ +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; +import { SVG } from "./SVG"; +import { Colors } from "../constants/colors/colorconstants"; +import { iconRender } from "../utils/iconRender"; +import { Spacers } from "../constants/spacers/spacers"; +import Divider from "./Divider"; +import StringManipulator from "./StringManipulator"; + +const Accordion = ({ + title, + children, + icon, + iconFill, + iconWidth, + iconHeight, + number, + isOpenInitially, + onToggle, + customClassName, + customStyles, + hideCardBorder, + hideDivider, + hideCardBg, + hideBorderRadius, + isClosed, + isChild +}) => { + const [isOpen, setIsOpen] = useState(isOpenInitially); + + const iconColor = Colors.lightTheme.primary[1]; + const toggleIconColor = Colors.lightTheme.text.primary; + const toggleiconSize = Spacers.spacer6; + const iconSize = Spacers.spacer6; + + const toggleAccordion = () => { + setIsOpen(!isOpen); + onToggle && onToggle(!isOpen); + }; + + useEffect(() => { + if (isClosed !== undefined && isClosed) { + setIsOpen(false); + } + }, [isClosed]); + + return ( +
+
+ {icon && ( +
+ {iconRender( + icon, + iconFill || iconColor, + iconWidth || iconSize, + iconHeight || iconSize, + `digit-accordion-icon` + )} +
+ )} + {number && ( +
+ {number} + {"."} +
+ )} +
{StringManipulator("TOSENTENCECASE", title)}
+
+ +
+
+
+ {children} +
+
+ ); +}; + +Accordion.propTypes = { + title: PropTypes.string.isRequired, + icon: PropTypes.string, + iconFill: PropTypes.string, + iconWidth: PropTypes.string, + iconHeight: PropTypes.string, + number: PropTypes.node, + isOpenInitially: PropTypes.bool, + hideCardBorder: PropTypes.bool, + hideDivider: PropTypes.bool, + hideCardBg: PropTypes.bool, + hideBorderRadius: PropTypes.bool, + onToggle: PropTypes.func, + customClassName: PropTypes.string, + customStyles: PropTypes.object, + isClosed: PropTypes.bool, +}; + +Accordion.defaultProps = { + icon: null, + number: null, + isOpenInitially: false, + customClassName: "", + customStyles: {}, + hideCardBorder: false, + hideDivider: false, + hideCardBg: false, + hideBorderRadius: false, + isClosed: false, +}; + +const AccordionList = ({ + children, + allowMultipleOpen = true, + addDivider, + className, + styles, +}) => { + const [openIndex, setOpenIndex] = useState(allowMultipleOpen ? [] : -1); + + const handleToggle = (index) => { + if (allowMultipleOpen) { + setOpenIndex((prevState) => + prevState?.includes(index) + ? prevState?.filter((i) => i !== index) + : [...prevState, index] + ); + } else { + setOpenIndex(index === openIndex ? -1 : index); + } + }; + + useEffect(() => {}, [openIndex]); + + return ( +
+ {React.Children.map(children, (child, index) => ( + + {React.cloneElement(child, { + isClosed: allowMultipleOpen + ? openIndex.length > 0 && !openIndex.includes(index) + : openIndex !== index, + onToggle: () => handleToggle(index), + })} + {addDivider && index < React.Children.count(children) - 1 && ( + + )} + + ))} +
+ ); +}; + +AccordionList.propTypes = { + children: PropTypes.node.isRequired, + allowMultipleOpen: PropTypes.bool, + addDivider: PropTypes.bool, + customClassName: PropTypes.string, + customStyles: PropTypes.object, +}; + +AccordionList.defaultProps = { + allowMultipleOpen: true, + addDivider: false, + customClassName: "", + customStyles: {}, +}; + +export { AccordionList, Accordion }; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ActionLinks.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ActionLinks.js new file mode 100644 index 00000000..dcc282f7 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ActionLinks.js @@ -0,0 +1,19 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const ActionLinks = (props) => ( + + {props.children} + +); + +ActionLinks.propTypes = { + /** custom class of the svg icon */ + className: PropTypes.string, + /** custom style of the svg icon */ + style: PropTypes.object, + /** Click Event handler when icon is clicked */ + children: PropTypes.node, +}; + +export default ActionLinks; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/AlertCard.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/AlertCard.js new file mode 100644 index 00000000..6149323d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/AlertCard.js @@ -0,0 +1,73 @@ +import React from "react"; +import { SVG } from "./SVG"; +import StringManipulator from "./StringManipulator"; +import PropTypes from "prop-types"; +import { Colors} from "../constants/colors/colorconstants"; + +const AlertCard = ({ label, text, variant, style, textStyle, additionalElements, inline, className, headerWrapperClassName,headerClassName}) => { + + const warningIconColor = Colors.lightTheme.alert.warning; + const errorIconColor = Colors.lightTheme.alert.error; + const successIconColor = Colors.lightTheme.alert.success; + const infoIconColor = Colors.lightTheme.alert.info; + + + const getIconAndLabelByVariant = (variant) => { + switch (variant) { + case "warning": + return { icon: , defaultLabel: "Warning" }; + case "success": + return { icon: , defaultLabel: "Success" }; + case "error": + return { icon: , defaultLabel: "Error" }; + default: + return { icon: , defaultLabel: "Info" }; + } + }; + const { icon, defaultLabel } = getIconAndLabelByVariant(variant); + + const hasAdditionalElements = additionalElements && additionalElements.length > 0; + + const displayedLabel = StringManipulator("TOTITLECASE", label) || defaultLabel; + + return ( +
+
+ {icon} +

{displayedLabel}

+
+ {text &&

{StringManipulator("TOSENTENCECASE", text)}

} + {hasAdditionalElements && ( +
+ {additionalElements.map((element, index) => ( +
+ {element} +
+ ))} +
+ )} +
+ ); +}; + +AlertCard.propTypes = { + label: PropTypes.string.isRequired, + text: PropTypes.string, + variant: PropTypes.string, + style: PropTypes.object, + textStyle: PropTypes.object, + additionalElements: PropTypes.arrayOf(PropTypes.node), + inline: PropTypes.bool, +}; + +AlertCard.defaultProps = { + label: "", + text: "", + varinat: "", + style: {}, + textStyle: {}, + additionalElements: [], + inline: false, +}; + +export default AlertCard; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Amount.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Amount.js new file mode 100644 index 00000000..ce55768d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Amount.js @@ -0,0 +1,22 @@ +import React from "react"; +import { formatter } from "../utils/formatter"; +import PropTypes from "prop-types"; +/* 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 ? `${formatter(value, "number")}` : t("ES_COMMON_NA")} +

+ ); +}; + +Amount.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + roundOff: PropTypes.bool, + value: PropTypes.number, +}; + +export default Amount; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Animation.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Animation.js new file mode 100644 index 00000000..c66c1a59 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Animation.js @@ -0,0 +1,20 @@ +import React from 'react'; +import Lottie from 'react-lottie'; + +const Animation = (props) => { + + const defaultOptions = { + loop: props?.loop, + autoplay: props?.autoplay, + animationData: props?.animationData, + renderer: 'svg', + }; + + return ( +
+ +
+ ); +}; + +export default Animation; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/AppContainer.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/AppContainer.js new file mode 100644 index 00000000..e94dd122 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/AppContainer.js @@ -0,0 +1,20 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const AppContainer = (props) => { + return ( + +
+ {props.children} +
+
+ ); +}; + +AppContainer.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + children: PropTypes.node, +}; + +export default AppContainer; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BackLink.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BackLink.js new file mode 100644 index 00000000..19be6386 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BackLink.js @@ -0,0 +1,89 @@ +import React,{useEffect,useState} from "react"; +import { SVG } from "./SVG"; +import { useTranslation } from "react-i18next"; +import PropTypes from "prop-types"; +import { Colors} from "../constants/colors/colorconstants"; + +const BackLink = ({ + style, + className = "", + variant, + onClick, + hideIcon = false, + hideLabel = false, + disabled = false, + iconFill, + label = "" +}) => { + const { t } = useTranslation(); + + const [isMobileView, setIsMobileView] = useState( + window.innerWidth <= 480 + ); + const onResize = () => { + if (window.innerWidth <= 480) { + if (!isMobileView) { + setIsMobileView(true); + } + } else { + if (isMobileView) { + setIsMobileView(false); + } + } + }; + useEffect(() => { + window.addEventListener("resize", onResize); + return () => { + window.removeEventListener("resize", onResize); + }; + }, []); + + const diabledIconColor = Colors.lightTheme.text.disabled; + const iconColor = Colors.lightTheme.primary[2]; + + const icon = + variant === "primary" ? ( + + ) : variant === "secondary" ? ( + + ) : ( + + ); + return ( +
+ {!hideIcon &&
{icon}
} + {!hideLabel && ( +
+ {label || t("CS_COMMON_BACK")} +
+ )} +
+ ); +}; + +BackLink.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + variant: PropTypes.string, + onClick: PropTypes.func, +}; + +export default BackLink; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Banner.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Banner.js new file mode 100644 index 00000000..6f14db5a --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Banner.js @@ -0,0 +1,108 @@ +import React from "react"; +import { SVG } from "./SVG"; +import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; +import { getUserType } from "../utils/digitUtils"; + +const Successful = (props) => { + const { t } = useTranslation(); + const user_type = getUserType(); + + return ( +
+
{props.props.message}
+
+ {props.props.whichSvg === "tick" ? ( +
+ +
+
+
+ ) : ( + 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 = getUserType(); + + return ( +
+
{props.props.message}
+ +

+ {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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BodyContainer.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BodyContainer.js new file mode 100644 index 00000000..2a82ca50 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BodyContainer.js @@ -0,0 +1,18 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const BodyContainer = (props) => { + return ( +
+ {props.children} +
+ ); +}; + +BodyContainer.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + children: PropTypes.node, +}; + +export default BodyContainer; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BreadCrumb.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BreadCrumb.js new file mode 100644 index 00000000..c80e25e4 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BreadCrumb.js @@ -0,0 +1,134 @@ +import React, { useEffect, useState, Fragment } from "react"; +import PropTypes from "prop-types"; +import { Link } from "react-router-dom"; + +const BreadCrumb = (props) => { + const [expanded, setExpanded] = useState(false); + const [crumbsToDisplay, setCrumbsToDisplay] = useState([...props?.crumbs]); + + useEffect(() => { + if (props?.maxItems && props?.crumbs.length > props?.maxItems && !expanded) { + const startCrumbs = props.crumbs.slice(0, props?.itemsBeforeCollapse || Math.ceil(props.maxItems / 2)); + const endCrumbs = props.crumbs.slice( + -1 * (props?.itemsAfterCollapse || Math.floor(props.maxItems / 2)) + ); + + let updatedCrumbs = startCrumbs.concat( + [{ show: true, content: props?.expandText || "..." }], + endCrumbs + ); + setCrumbsToDisplay(updatedCrumbs); + } else { + setCrumbsToDisplay([...props.crumbs]); + } + }, [props.crumbs, props.maxItems, expanded, props.itemsBeforeCollapse, props.itemsAfterCollapse, props?.expandText]); + + function handleRedirect(path) { + const host = window.location.origin; // Dynamically get the base URL + window.location.href = `${host}${path}`; + } + + function isLast(index) { + // Filter crumbs to only include those that are displayed + let validCrumbs = crumbsToDisplay?.filter((crumb) => crumb?.show === true); + + // Check if all crumbs have the same `internalLink` or `externalLink` + const allHaveSameInternalLink = validCrumbs.every((crumb) => crumb.internalLink === validCrumbs[0].internalLink); + const allHaveSameExternalLink = validCrumbs.every((crumb) => crumb.externalLink === validCrumbs[0].externalLink); + + // If all visible crumbs have the same link, determine last crumb by index + if (allHaveSameInternalLink || allHaveSameExternalLink) { + return index === validCrumbs.length - 1; + } + + // Check if the current crumb is the last one in the validCrumbs list + return validCrumbs?.findIndex((ob) => { + const linkToCheck = ob?.externalLink || ob?.internalLink; // Use externalLink if it exists, else internalLink + const currentLink = crumbsToDisplay?.[index]?.externalLink || crumbsToDisplay?.[index]?.internalLink; + return linkToCheck === currentLink; + }) === validCrumbs?.length - 1; + } + + const handleCrumbClick = () => { + setExpanded(!expanded); + }; + + const validCrumbsMain = crumbsToDisplay?.filter((crumb) => crumb?.show === true); + + return ( +
    + {validCrumbsMain?.map((crumb, ci) => { + if (!crumb?.show) return null; + if (crumb?.isBack) + return ( +
  1. + window.history.back()}>{crumb.content} +
  2. + ); + + return ( + +
  3. + {isLast(ci) || (!crumb?.internalLink && !crumb?.externalLink) ? ( + + {crumb?.icon && crumb.icon} + {crumb.content} + + ) : crumb?.externalLink ? ( + handleRedirect(crumb?.externalLink)} + > + {crumb?.icon && crumb.icon} + {crumb.content} + + ) : ( + + {crumb?.icon && crumb.icon} + {crumb.content} + + )} + {!isLast(ci) && ( +
    + {props?.customSeparator ? props?.customSeparator : "/"} +
    + )} +
  4. +
    + ); + })} +
+ ); +}; + +BreadCrumb.propTypes = { + crumbs: PropTypes.array, + className: PropTypes.string, + style: PropTypes.object, + spanStyle: PropTypes.object, + customSeparator: PropTypes.element, + maxItems: PropTypes.number, + itemsAfterCollapse: PropTypes.number, + itemsBeforeCollapse: PropTypes.number, + expandText: PropTypes.string +}; + +export default BreadCrumb; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BreakLine.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BreakLine.js new file mode 100644 index 00000000..05127ebd --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/BreakLine.js @@ -0,0 +1,13 @@ +import React from "react"; +import PropTypes from 'prop-types'; + +const BreakLine = ({ className = "", style = {} }) => { + return
; +}; + +BreakLine.propTypes = { + className: PropTypes.string, + style: PropTypes.object, +}; + +export default BreakLine; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Button.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Button.js new file mode 100644 index 00000000..6e5655f9 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Button.js @@ -0,0 +1,216 @@ +import React, { useState, useRef, useEffect } from "react"; +import PropTypes from "prop-types"; +import StringManipulator from "./StringManipulator"; +import Menu from "./Menu"; +import { Colors } from "../constants/colors/colorconstants"; +import { iconRender } from "../utils/iconRender"; + +const Button = (props) => { + const [dropdownStatus, setDropdownStatus] = useState(false); + const actionRef = useRef(null); + + useEffect(() => { + const handleClickOutside = (event) => { + if (actionRef?.current && !actionRef?.current.contains(event.target)) { + setDropdownStatus(false); + } + }; + + if (dropdownStatus) { + document.addEventListener("mousedown", handleClickOutside); + } else { + document.removeEventListener("mousedown", handleClickOutside); + } + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [dropdownStatus]); + + const diabledIconColor = Colors.lightTheme.text.disabled; + const iconColor = Colors.lightTheme.primary[1]; + const primaryIconColor = Colors.lightTheme.paper.primary; + + //To render the icon + const IconRender = () => { + const iconFill = props.iconFill + ? props.iconFill + : props?.variation === "primary" + ? primaryIconColor + : props?.isDisabled + ? diabledIconColor + : iconColor; + const iconReq = + props?.type === "actionButton" && + props?.showBottom && + dropdownStatus && + !props.icon + ? "ArrowDropUp" + : props?.type === "actionButton" && + props?.showBottom && + !dropdownStatus && + !props?.icon + ? "ArrowDropDown" + : props?.type === "actionButton" && + !props?.showBottom && + dropdownStatus && + !props.icon + ? "ArrowDropDown" + : props?.type === "actionButton" && + !props?.showBottom && + !dropdownStatus && + !props?.icon + ? "ArrowDropUp" + : props?.icon; + let width, height; + + if (props.size === "large") { + width = props.variation === "link" ? "1.25rem" : "1.5rem"; + height = props.variation === "link" ? "1.25rem" : "1.5rem"; + } else if (props.size === "medium") { + width = "1.25rem"; + height = "1.25rem"; + } else if (props.size === "small") { + width = "0.875rem"; + height = "0.875rem"; + } else { + width = "1.5rem"; + height = "1.5rem"; + } + return iconRender( + iconReq, + iconFill, + width, + height, + `digit-button-customIcon ${props?.size ? props?.size : ""} ${ + props?.variation ? props?.variation : "" + }` + ); + }; + + const icon = IconRender(); + + const formattedLabel = props?.label + ? props?.variation === "link" + ? props?.label + : StringManipulator( + "CAPITALIZEFIRSTLETTER", + StringManipulator("TRUNCATESTRING", props?.label, { + maxLength: 64, + }) + ) + : ""; + + const handleActionButtonClick = (e) => { + e.stopPropagation(); + setDropdownStatus(!dropdownStatus); + }; + + const buttonElement = ( + + ); + + return props?.type === "actionButton" ? ( +
+ {buttonElement} + {dropdownStatus && ( +
+ +
+ )} +
+ ) : ( + buttonElement + ); +}; + +Button.propTypes = { + isDisabled: PropTypes.bool, + /** + * ButtonSelector content + */ + label: PropTypes.string.isRequired, + /** + * button border theme + */ + variation: PropTypes.string, + /** + * button icon if any + */ + icon: PropTypes.string, + /** + * click handler + */ + onClick: PropTypes.func.isRequired, + /** + * Custom classname + */ + className: PropTypes.string, + /** + * Custom styles + */ + style: PropTypes.object, + /** + * Custom label style or h2 style + */ + textStyles: PropTypes.object, + /** + * button icon position + */ + isSuffix: PropTypes.bool, + /** + * button size + */ + size: PropTypes.string, +}; + +Button.defaultProps = { + label: "", + variation: "primary", + onClick: () => {}, + size: "large", +}; + +export default Button; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ButtonGroup.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ButtonGroup.js new file mode 100644 index 00000000..e798c41a --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ButtonGroup.js @@ -0,0 +1,76 @@ +import React, { useRef, useEffect, useState } from "react"; +import PropTypes from "prop-types"; +import Button from "./Button"; + +const ButtonGroup = ({ buttonsArray ,sortButtons,equalButtons}) => { + const [isMobileView, setIsMobileView] = React.useState( + window.innerWidth <= 480 + ); + const onResize = () => { + if (window.innerWidth <= 480) { + if (!isMobileView) { + setIsMobileView(true); + } + } else { + if (isMobileView) { + setIsMobileView(false); + } + } + }; + useEffect(() => { + window.addEventListener("resize", () => { + onResize(); + }); + return () => { + window.addEventListener("resize", () => { + onResize(); + }); + }; + }); + + const maxWidth = equalButtons ? Math.max( + ...buttonsArray.map((button) => button.props.label.length * 14.9) + ) : null; + + const updatedButtonsArray = buttonsArray && buttonsArray.length > 1 && equalButtons ? buttonsArray.map((button) => { + const buttonProps = { + ...button.props, + style: { ...(button.props.style || {}), width: `${maxWidth}px` }, + }; + return + ); +}; + +ButtonSelector.propTypes = { + /** + * ButtonSelector content + */ + label: PropTypes.string.isRequired, + /** + * button border theme + */ + theme: PropTypes.string, + /** + * click handler + */ + onSubmit: PropTypes.func, +}; + +ButtonSelector.defaultProps = { + label: "", + theme: "", + onSubmit: undefined, +}; + +export default ButtonSelector; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Card.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Card.js new file mode 100644 index 00000000..de4301f1 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Card.js @@ -0,0 +1,47 @@ +import React, { Children } from "react"; +import PropTypes from "prop-types"; +import { useLocation } from "react-router-dom"; + +const Card = ({ + type, + onClick, + style = {}, + children, + className, + ReactRef, + variant, + ...props +}) => { + // const { pathname } = useLocation(); + // const classname = window?.Digit?.Hooks?.useRouteSubscription(pathname) || ""; + const info = window?.Digit?.UserService?.getUser()?.info || null; + const userType = info?.type || null; + + return ( +
+ {children} +
+ ); +}; + +Card.propTypes = { + type: PropTypes.string, + variant: PropTypes.string, + onClick: PropTypes.func, + style: PropTypes.object, + className: PropTypes.string, + children: PropTypes.node, +}; +export default Card; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardBasedOptions.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardBasedOptions.js new file mode 100644 index 00000000..06b2bece --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardCaption.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardCaption.js new file mode 100644 index 00000000..c7a573e3 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardCaption.js @@ -0,0 +1,11 @@ +import React from "react"; + +const CardCaption = (props) => { + return ( + + ); +}; + +export default CardCaption; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardHeader.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardHeader.js new file mode 100644 index 00000000..3d47c22f --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardHeader.js @@ -0,0 +1,13 @@ +import React from "react"; + +const CardHeader = (props) => { + const variant = props?.variant ? props?.variant : ""; + const className = props?.className ? props?.className : ""; + return ( +
+ {props.children} +
+ ); +}; + +export default CardHeader; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardLabel.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardLabel.js new file mode 100644 index 00000000..5913a7c7 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardLabel.js @@ -0,0 +1,17 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const CardLabel = (props) => { + return ( +

+ {props.children} +

+ ); +}; +CardLabel.propTypes = { + className: PropTypes.string, // An optional string for custom class names. + style: PropTypes.object, // An optional object for custom styles. + children: PropTypes.node.isRequired, // Required prop for the content of the error label. +}; + +export default CardLabel; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardLabelError.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardLabelError.js new file mode 100644 index 00000000..d430959d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardLabelError.js @@ -0,0 +1,18 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const CardLabelError = (props) => { + return ( +

+ {props.children} +

+ ); +}; + +CardLabelError.propTypes = { + className: PropTypes.string, // An optional string for custom class names. + style: PropTypes.object, // An optional object for custom styles. + children: PropTypes.node.isRequired, // Required prop for the content of the error label. +}; + +export default CardLabelError; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardText.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CardText.js new file mode 100644 index 00000000..55fdf33e --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CheckBox.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CheckBox.js new file mode 100644 index 00000000..81459582 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CheckBox.js @@ -0,0 +1,133 @@ +import React, { Fragment } from "react"; +import { SVG } from "./SVG"; +import StringManipulator from "./StringManipulator"; +import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; +import { Colors} from "../constants/colors/colorconstants"; +import { getUserType } from "../utils/digitUtils"; + +const CheckBox = ({ + onChange, + label, + value, + disabled, + ref, + checked, + inputRef, + pageType, + style, + index, + isLabelFirst, + hideLabel, + isIntermediate, + ...props +}) => { + const { t } = useTranslation(); + const userType = pageType || getUserType(); + let styles = props?.styles; + + const sentenceCaseLabel = StringManipulator("TOSENTENCECASE", label); + + const diabledIconColor = Colors.lightTheme.text.disabled; + const iconColor = Colors.lightTheme.primary[1]; + + return ( +
+ {isLabelFirst && !hideLabel ? ( + + ) : null} +
+ +

+ {isIntermediate && !checked ? ( + + ) : ( + + )} +

+
+ {!isLabelFirst && !hideLabel ? ( + + ) : null} +
+ ); +}; + +CheckBox.propTypes = { + /** + * CheckBox content + */ + label: PropTypes.string.isRequired, + /** + * onChange func + */ + onChange: PropTypes.func, + /** + * input ref + */ + ref: PropTypes.func, + userType: PropTypes.string, + hideLabel:PropTypes.bool, + isIntermediate: PropTypes.bool, +}; + +CheckBox.defaultProps = { + label: "Default", + isLabelFirst: false, + onChange: () => console.log("CLICK"), + value: "", + checked: false, + ref: "ww", + // pageType: "EMPLOYEE", + index: 0, + isIntermediate: false, +}; + +export default CheckBox; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Chip.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Chip.js new file mode 100644 index 00000000..8db000b7 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Chip.js @@ -0,0 +1,107 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { SVG } from "./SVG"; +import ErrorMessage from "./ErrorMessage"; +import { Colors} from "../constants/colors/colorconstants"; +import { iconRender } from "../utils/iconRender"; + +const Chip = ({ + className, + text, + onTagClick, + onClick, + extraStyles, + disabled = false, + isErrorTag, + error, + hideClose, + onErrorClick, + iconReq +}) => { + const tagStyles = extraStyles ? extraStyles?.tagStyles : {}; + const textStyles = extraStyles ? extraStyles?.textStyles : {}; + const closeIconStyles = extraStyles ? extraStyles?.closeIconStyles : {}; + const IconColor = Colors.lightTheme.paper.primary; + + const IconRender = (iconReq,isErrorTag) => { + const iconFill = isErrorTag ? "#B91900" : "#787878"; + return iconRender( + iconReq, + iconFill, + "1.25rem", + "1.25rem", + "" + ); + }; + + return ( +
+
+ {iconReq && IconRender(iconReq,isErrorTag)} + + {text} + + { + !hideClose && + + + } +
+ {error && ( +
+ +
+ )} +
+ ); +}; + +Chip.propTypes = { + className: PropTypes.string, + text: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired, + extraStyles: PropTypes.shape({ + tagStyles: PropTypes.object, + textStyles: PropTypes.object, + closeIconStyles: PropTypes.object, + }), + disabled: PropTypes.bool, + isErrorTag: PropTypes.bool, + error: PropTypes.string, + hideClose:PropTypes.bool +}; + + +Chip.defaultProps = { + hideClose:true +}; + + +export default Chip; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CitizenHomeCard.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CitizenHomeCard.js new file mode 100644 index 00000000..f5816206 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CitizenInfoLabel.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CitizenInfoLabel.js new file mode 100644 index 00000000..082e3347 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CitizenInfoLabel.js @@ -0,0 +1,32 @@ +import React from "react"; +import { SVG } from "./SVG"; +import PropTypes from "prop-types"; + +const CitizenInfoLabel = (props) => { + props = props?.props ? props?.props : props; + const showInfo = props?.showInfo ? props?.showInfo : true; + + return ( +
+ {showInfo && ( +
+ +

{props?.info}

+
+ )} +

{props?.text}

+
+ ); +}; +CitizenInfoLabel.propTypes = { + props: PropTypes.object, // An optional object of props. + showInfo: PropTypes.bool, // An optional boolean to control the visibility of the info banner. + className: PropTypes.string, // An optional string for custom class names. + style: PropTypes.object, // An optional object for custom styles. + fill: PropTypes.string, // An optional string for the icon fill color. + textStyle: PropTypes.object, // An optional object for custom text styles. + info: PropTypes.string, // An optional string for the info banner text. + text: PropTypes.string.isRequired, // A required string for the main text content. +}; + +export default CitizenInfoLabel; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CollapseAndExpandGroups.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CollapseAndExpandGroups.js new file mode 100644 index 00000000..840465c9 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CollapseAndExpandGroups.js @@ -0,0 +1,44 @@ +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 = "" }) => { + const { t } = useTranslation(); + const [collapse, setCollapse] = useState(true); + return ( +
+ {groupHeader &&
{t(groupHeader)}
} + {groupElements && ( +
+ {headerLabel} + {headerValue} +
setCollapse((prev) => !prev)} className="digit-icon-toggle "> + {!collapse && ( + + + + )} + {collapse && ( + + + + )} +
+
+ )} +
{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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ConnectingCheckPoints.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ConnectingCheckPoints.js new file mode 100644 index 00000000..f37605fd --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CustomSVG.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CustomSVG.js new file mode 100644 index 00000000..1108423d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/CustomSVG.js @@ -0,0 +1,3607 @@ +import React from "react"; + +const CreateEstimateIcon = ({ className, style = {}, fill = "#C84C0E",width = '18',height ='18' }) => ( + + + +); + +const GotoInboxIcon = ({ className, style = {}, fill = "#C84C0E",width="15",height="13" }) => ( + + + +); + +const ArrowLeft = ({ className,width="19",height="19",fill="black"}) => ( + + + + +); + +const ArrowLeftWhite = ({ className, fill = "white", style = {},width="16",height="16" }) => ( + + + +); +const PrivacyMaskIcon = ({ className, style = {} ,width="22",height="15",fill="#EEEEEE"}) => ( + + + +); + +const ArrowDown = ({ className, onClick, styles, disable,width="18",height="18",fill="black"}) => ( + + + + +); + +const ArrowBack = ({ className, onClick ,width="18",height="18",fill="black"}) => ( + + + + +); + +const ArrowForward = ({ className, onClick,width="18",height = "18",fill ="black" }) => ( + + + + +); + +const ArrowToFirst = ({ className, onClick,width="18",height="18",fill="#505A5F"}) => ( + + + +); + +const ArrowToLast = ({ className, onClick,fill="#505A5F",width="18",height="18" }) => ( + + + +); + +const DownloadPrefixIcon = ({ className, onClick,width="24",height="24",fill="#C84C0E" }) => ( + + + + +); + +const CameraSvg = ({ className, fill="black", width="46",height="42" }) => ( + + + + +); + +const DeleteBtn = ({ className, onClick, fill="white",width="18",height="18" }) => ( + + + + +); + +const SuccessSvg = ({ className,fill="#00703C" ,width="24",height="24"}) => ( + + + + +); + +const ErrorSvg = ({ className,fill="#D4351C" ,width="24",height="24" }) => ( + + + + + +); + +const StarFilled = ({ className, id, onClick, styles, percentage = 100,fill="#C84C0E" ,width="48",height="48" }) => ( + + + + + + + + + + + + + + +); + +const StarEmpty = ({ className, onClick, styles,fill="#C84C0E" ,width="48",height="48" }) => ( + + + + +); + +const DownloadImgIcon = ({width="14",height="17",fill="#C84C0E"}) => ( + + + +); + +const PrevIcon = ({fill="#0B0C0C" ,width="8",height="12"}) => ( + + + +); + +const ViewsIcon = ({fill="#C84C0E" ,width="22",height="16"}) => ( + + + +); + +const DocumentIcon = ({fill="#C84C0E" ,width="100",height="100",onClick}) => ( + + + +); + +const DocumentIconSolid = ({fill="#FFFFFF" ,width="24",height="24"}) => ( + + + + +); + +const SurveyIconSolid = ({fill="#FFFFFF" ,width="24",height="24"}) => ( + + + + +); + +const PMBIcon = ({fill="#C84C0E" ,width="32",height="16"}) => ( + + + +); + +const PMBIconSolid = ({fill="#FFFFFF" ,width="24",height="24"}) => ( + + + + + + + + + + +); + +const EventsIconSolid = ({fill="#FFFFFF" ,width="24",height="24"}) => ( + + + + +); + +const DustbinIcon = ({fill="#C84C0E" ,width="14",height="18"}) => ( + + + +); + +const ImageIcon = ({fill="#000000" ,width="24",height="24"}) => ( + + + + +); + +// const DocumentSVG = ({className}) => < path d = "M0 0h24v24H0V0z" fill = "none" /> +// < path d = "M8 16h8v2H8zm0-4h8v2H8zm6-10H6c-1.1 0-2 .9-2 2v16c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z" /> +// + +// const PDFSvg = ({className, width = 100, height = 100, style, viewBox="0 0 34 34" }) => +// +// + +const DocumentSVG = ({fill="#505A5F" ,width="80",height="80",onClick}) => ( + + + +); + +const PDFSvg = ({ + className, + width = 80, + height = 80, + style = { + background: "#f6f6f6", + padding: "8px", + boxShadow: "0px 2px 0px #d6d5d3", + borderRadius: "4px", + }, + viewBox = "0 0 80 80", + fill="#505A5F" +}) => ( + + + +); + +const SearchIconSvg = ({ className, onClick,fill="#C84C0E" ,width="24",height="24" }) => ( + + + + +); + +const CheckSvg = ({ className, style = {},fill="#C84C0E" ,width="24",height="24" }) => ( + + + + +); + +const RoundedCheck = ({ className,fill="#FFFFFF" ,width="24",height="24" }) => ( + + + + +); + +const Calender = ({ className, onClick,fill="black" ,width="24",height="24" }) => ( + + + + +); + +const Phone = ({ className, fillcolor, style,fill="#C84C0E" ,width="24",height="24" }) => ( + + + + +); + +const FilterSvg = ({ className,style,onClick,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +const SortSvg = ({ className,fill="#505A5F" ,width="24",height="16" }) => ( + + + +); + +const Close = ({ className, style,fill="#9E9E9E" ,width="24",height="24" }) => ( + +); + +const Feedback = ({ className,fill="#C84C0E" ,width="24",height="24" }) => ( + +); + +// Download Icon + +const GetApp = ({ className ,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +const HamburgerIcon = ({ className, styles ,fill="#C84C0E" ,width="24",height="24" }) => ( + +); + +export const HomeIcon = ({ className, styles,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +export const LanguageIcon = ({ className, styles,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +export const LogoutIcon = ({ className, styles,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +const CalendarIcon = (props,fill="black" ,width="24",height="24") => ( + + + + +); + +const SortDown = (style,onClick,fill="#C84C0E" ,width="24",height="24") => ( + + + + +); + +const SortUp = (style,onClick,fill="#C84C0E" ,width="24",height="24") => ( + + + + +); + +const ArrowRightInbox = ({ style,fill="#C84C0E" ,width="20",height="14" }) => ( + + + +); + +const ShippingTruck = ({ className, styles,fill="#C84C0E" ,width="24",height="24" }) => ( + + + + +); + +function CloseSvg({ onClick,fill="#C84C0E" ,width="24",height="24" }) { + return ( + + + + + ); +} + +const UpwardArrow = ({ rotate = 0, marginRight = 0,fill="#00703C" ,width="11",height="16" }) => ( + + + +); + +const DownwardArrow = (props,fill="#E54D42" ,width="24",height="24") => ( + +); + +const DownloadIcon = ({ styles, className, onClick, fill = "#505A5F",width="19",height="24" }) => ( + + + +); + +const GenericFileIcon = ({fill="#505A5F" ,width="80",height="100"}) => ( + + + +); + +const ExternalLinkIcon = ({fill="#C84C0E" ,width="18",height="18"}) => ( + + + +); + +const PrimaryDownlaodIcon = ({fill="#C84C0E" ,width="24",height="24"}) => ( + + + +); + +const Ellipsis = ({ className, onClick,fill="#B1B4B6" ,width="4",height="16" }) => ( + + + +); + +const Poll = ({fill="#C84C0E" ,width="40",height="40"}) => ( + + + + +); + +const Details = ({fill="#505A5F" ,width="21",height="16"}) => ( + + + +); + +const FilterIcon = ({ onClick,fill="#505A5F" ,width="22",height="22" }) => ( + + + +); + +const RefreshIcon = ({fill="#0B0C0C" ,width="16",height="22"}) => ( + + + +); + +const RefreshSVG = ({fill="#505A5F" ,width="17",height="17"}) => ( + + + +); + +const PrintIcon = ({fill="#505A5F" ,width="20",height="18"}) => ( + + + +); +function PropertyHouse({ className, styles,fill="#FFFFFF" ,width="24",height="24" }) { + return ( + + + + + ); +} + +const InfoBannerIcon = ({ fill = "#3498DB", styles,width="20",height="20" }) => { + return ( + + + + ); +}; +const ShareIcon = ({ styles, className, fill = "#505A5F" ,width="18",height="20"}) => ( + + + +); + +const RupeeIcon = ({ className,fill="#C84C0E" ,width="48",height="48" }) => ( + + + +); + +const ComplaintIcon = ({ className, styles,fill="#FFFFFF" ,width="48",height="48" }) => ( + + + +); + +const DropIcon = ({ className, styles,fill="#FFFFFF" ,width="28",height="34" }) => ( + + + +); + +const Person = (style,fill="white" ,width="24",height="24") => ( + + + + +); + +const WhatsappIcon = ({fill="#C84C0E" ,width="24",height="24"}) => ( + + + +); + +const EmailIcon = ({fill="#C84C0E" ,width="20",height="16"}) => ( + + + +); + +const CaseIcon = ({ className, styles,fill="#FFFFFF" ,width="24",height="24" }) => ( + + + +); + +const TLIcon = ({ className, styles,fill="#FFFFFF" ,width="24",height="24" }) => ( + + + +); + +const PersonIcon = ({ className, styles,fill="#FFFFFF" ,width="24",height="24" }) => ( + + + +); + +const ReceiptIcon = ({fill="white" ,width="24",height="24"}) => ( + + + + +); + +const AnnouncementIcon = ({width="28",height="28",fill="#C84C0E"}) => ( + + + +); + +const PTIcon = ({ className, styles,fill="#FFFFFF" ,width="34",height="30" }) => ( + + + +); + +const OBPSIcon = ({ className, styles,fill="#FFFFFF" ,width="34",height="30" }) => ( + + + +); + +const OBPSIconSolidBg = ({fill="white" ,width="34",height="30"}) => ( + + + +); + +const CitizenTruck = ({ className,fill="#C84C0E" ,width="40",height="40" }) => ( + + + +); + +const FSMIcon = ({ className, styles,fill="#FFFFFF" ,width="40",height="40" }) => ( + + + +); + +const EDCRIcon = ({ className,fill="#C84C0E" ,width="30",height="32" }) => ( + + + +); + +const BPAIcon = ({ className,fill="#C84C0E" ,width="32",height="32" }) => ( + + + + + + + +); + +const BPAHomeIcon = ({ className, styles,fill="#FFFFFF" ,width="34",height="30" }) => ( + + + +); + +const HelpIcon = ({fill="#C84C0E" ,width="24",height="18"}) => ( + + + +); +const EventCalendar = ({fill="#C84C0E" ,width="24",height="27"}) => { + return ( + + + + ); +}; + +const NotificationBell = ({fill="white" ,width="16",height="20"}) => ( + + + +); + +const MapMarker = ({fill="#505A5F" ,width="10",height="14"}) => ( + + + +); + +const Clock = ({fill="#505A5F" ,width="16",height="16"}) => ( + + + +); + +const TickMark = ({ fill = "white",width="14",height="11" }) => ( + + + +); + +const EditIcon = ({ style,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +const SearchIcon = ({ className,fill="#505A5F" ,width="18",height="18" }) => ( + + + +); + +const DeleteIcon = ({ style, fill,width="14",height="18" }) => ( + + + +); + +const CreateLoiIcon = ({ style, fill = "#C84C0E",width="18",height="18" }) => ( + + + +); + +const WSICon = ({ className, styles,fill="#FFFFFF" ,width="28",height="34" }) => ( + + + +); + +const ArrowVectorDown = ({ className, styles,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +const ArrowDirection = ({ className, styles,fill="#C84C0E" ,width="16",height="16" }) => ( + + + +); + +const CameraIcon = ({fill="#C84C0E" ,width="40",height="40"}) => ( + + + + +); +const RemoveIcon = ({fill="#C84C0E" ,width="24",height="30"}) => ( + + + +); + +const GalleryIcon = ({fill="#C84C0E" ,width="40",height="34"}) => ( + + + +); + +const EditPencilIcon = ({ className, width = 18, height = 18 ,fill="#505A5F"}) => ( + + + +); +const AddressBookIcon = ({ styles, className,fill="#B1B4B6",width="20",height="24" }) => ( + + + +); + +const LocationIcon = ({ styles, className ,fill="#B1B4B6",width="14",height="20"}) => ( + + + +); +const CollectionsBookmarIcons = ({ styles, className,fill="#FFFFFF" ,width="22",height="28" }) => ( + + + +); + +const FinanceChartIcon = ({ styles, className ,fill="#FFFFFF" ,width="30",height="30"}) => ( + + + +); + +const CollectionIcon = ({ styles, className,fill="#FFFFFF" ,width="24",height="27" }) => ( + + + +); + +const BillsIcon = ({ styles, className,fill="#FFFFFF", width="24",height="27" }) => ( + + + +); + +const MCollectIcon = ({ styles, className,fill="#FFFFFF" ,width="37",height="35" }) => ( + + + +); + +const PGRIcon = ({ styles, className,fill="#FFFFFF" ,width="35",height="39" }) => ( + + + +); +const FirenocIcon = ({ styles, className,fill="#FFFFFF" ,width="35",height="39" }) => ( + + + +); +const BirthIcon = ({ styles, className,fill="#FFFFFF" ,width="35",height="39" }) => ( + + + +); +const DeathIcon = ({ styles, className,fill="#FFFFFF" ,width="35",height="39" }) => ( + + + +); +const ErrorIcon = ({ className,fill="#FFFFFF" ,width="20",height="20" }) => ( + + + +); +const DownloadBtnCommon = ({fill="#C84C0E" ,width="112",height="32"}) => ( + + + + +); + +const PrintBtnCommon = ({fill="#505A5F" ,width="41",height="41"}) => ( + + + +); + +const WhatsappIconGreen = ({ className, styles ,fill="#25D366" ,width="24",height="24"}) => ( + + + +); + +const HelpLineIcon = ({ className, styles,fill="#0B0C0C" ,width="24",height="18" }) => ( + + + +); + +const ServiceCenterIcon = ({ className, styles,fill="#0B0C0C" ,width="24",height="24" }) => ( + + + + + + + +); + +const TimerIcon = ({ className, styles ,fill="#C84C0E" ,width="20",height="20"}) => ( + + + +); + +const RupeeSymbol = ({ className, styles,fill="#C84C0E" ,width="13",height="18" }) => ( + + + +); + +const ValidityTimeIcon = ({ className, styles,fill="#C84C0E" ,width="21",height="18" }) => ( + + + +); + +const AddIcon = ({ styles, className, fill = "white" ,width="14",height="14"}) => ( + + + +); + +const UploadIcon = ({ + styles, + className, + fill = "white", + height = "64", + width = "64", +}) => ( + + + + + + + + + + +); + +const DeleteIconv2 = ({ + styles, + className, + fill = "#C84C0E", + height = "24", + width = "24", +}) => ( + + + + + + + + + + +); + +const InfoIconOutline = ({ + styles, + className, + fill = "#505A5F", + height = "20", + width = "20", +}) => ( + + + +); + +const FileIcon = ({ + styles, + className, + fill = "white", + height = "24", + width = "24", +}) => ( + + + + + + + + + + +); + +const SubtractIcon = ({ styles, className, fill = "white",width="12",height="14" }) => ( + + + +); + +const AddNewIcon = ({ style,fill="#C84C0E" ,width="24",height="24" }) => ( + + + +); + +const ViewReportIcon = ({fill="#C84C0E" ,width="30",height="30"}) => ( + + + +); + +const InboxIcon = ({fill="#C84C0E" ,width="30",height="30"}) => ( + + + +); + +const ArrowCollapseUp = ({fill="#0B0C0C",width="13",height="8"}) => ( + + + +); + +const ArrowCollapseDown = ({fill="#0B0C0C",width="12",height="8"}) => ( + + + +); + +const AddFilled = ({ style = {} ,width="15",height="15",fill="#C84C0E"}) => ( + + + +); + +const NoResultsFoundIcon = ({fill="#C84C0E",width="336",height="262"}) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const WorksMgmtIcon = ({ fill = "white" ,width="34",height="36"}) => ( + + + + +); + +const BioMetricIcon = ({ fill = "#C84C0E" ,width="30",height="34"}) => ( + + + +); + +const AddFileFilled = ({ className = "", fill = "#C84C0E", style = {} ,width="19",height="18"}) => ( + + + +); + +const LocateIcon = ({ className = "" ,width="22",height="22",fill="#505A5F"}) => ( + + + +); + +const ProjectIcon = ({ className = "", fill = "white", style = {},width="28",height="22" }) => ( + + + +); +const EstimateIcon = ({ className = "", fill = "none", style = {},width="28",height="31" }) => ( + + + + + +); +const OrganisationIcon = ({ className = "", fill = "none", style = {},width="32",height="32" }) => ( + + + +); +const WageseekerIcon = ({ className = "", fill = "none", style = {} ,width="32",height="26"}) => ( + + + +); +const ContractIcon = ({ className = "", fill = "none", style = {} ,width="24",height="27"}) => ( + + + + + + + + + + + + +); +const DashboardIcon = ({ className = "", fill = "none", style = {},width="24",height="24" }) => ( + + + +); +const HelperIcon = ({ className = "", fill = "none", style = {},width="32", height="32" }) => ( + + + + + + + + + + +); +const AttendanceIcon = ({ className = "", fill = "none", style = {},width="32",height="32" }) => ( + + + + + + + + + +); +const HRIcon = ({ className = "", fill = "white", style = {},width="28",height="28" }) => ( + + + +); +const MuktaHomeIcon = ({ className = "", fill = "white", style = {} ,width="28",height="23"}) => ( + + + +); +const DoubleTickIcon = ({ className = "", fill = "#C84C0E", style = {},width,height }) => ( + + + +); +const InfoIcon = ({ className = "", fill = "none", style = {},width,height }) => ( + + + +); +const PaymentIcon = ({ className = "", fill = "none", style = {},width,height }) => ( + + + + + + + + + + +); + +const HistoryIcon = ({ className = "", fill = "#C84C0E", style = {},width,height }) => ( + + + + + + + + + +); + +const WarningIcon = ({ className = "", fill = "#C84C0E", style = {},width,height }) => ( + + + + + + + + + + +); + +const AttentionListIcon = ({ className = "", fill = "#C84C0E", style = {},width="36",height="36" }) => ( + + + +); + +const XlsxFile = ({ className = "", fill = "none", style = {},width="38",height="38",onClick }) => ( + + + + + + + + + + + +); + +const DocFile = ({ className = "", fill = "none", styles = {},width="33",height="36" ,onClick}) => ( + + + + + + + +); +const PdfFile = ({ className = "", fill = "none", style = {},width="33",height="36",onClick }) => ( + + + + + + +); +const JpgFile = ({ className = "", fill = "none", style = {} ,width="33",height="36",onClick}) => ( + + + + + + +); + +const PngFile = ({ className = "", fill = "none", style = {} ,width="34",height="36",onClick}) => ( + + + + + + +); + +const DocUpload = ({ className = "", fill = "none", styles,width="100",height="100" }) => ( + + + + + + + + + + + +); + +const DocXlsxUpload = ({ className = "", fill = "none", styles,width="100",height="100" }) => ( + + + + + + + + + + + + + + +); + +const DocdocUpload = ({ className = "", fill = "none", styles,width="100",height="100" }) => ( + + + + + + + + + + +); + +const DocPdfUpload = ({ className = "", fill = "none", styles ,width="100",height="100"}) => ( + + + + + + + + + +); + +const ProfileIcon = ({ className, styles,width="32",height="32" }) => ( + + + + + +); + +const ExpenditureIcon = BillsIcon; + +const AddIconNew = ({ + width = "24", + height = "24", + fill = "#0B0C0C", + className = "", + style = {}, + ...props +}) => ( + + + +); + +const PlaceholderSvg = ({width="800",height="800",fill}) => ( + + + + +); + +export const CustomSVG = { + PlaceholderSvg, + ProfileIcon, + AnnouncementIcon, + ReceiptIcon, + CreateEstimateIcon, + GotoInboxIcon, + ArrowLeft, + ArrowDown, + CameraSvg, + DeleteBtn, + DownloadIcon, + Ellipsis, + SuccessSvg, + ErrorSvg, + StarFilled, + StarEmpty, + SearchIconSvg, + CheckSvg, + RoundedCheck, + Calender, + Phone, + FilterSvg, + SortSvg, + Close, + Feedback, + GetApp, + HamburgerIcon, + ArrowBack, + ArrowForward, + ArrowRightInbox, + SortDown, + SortUp, + ShippingTruck, + CloseSvg, + CalendarIcon, + UpwardArrow, + DownwardArrow, + Poll, + FilterIcon, + RefreshIcon, + RefreshSVG, + Details, + PrintIcon, + PropertyHouse, + PrimaryDownlaodIcon, + InfoBannerIcon, + ShareIcon, + RupeeIcon, + ComplaintIcon, + DropIcon, + Person, + WhatsappIcon, + EmailIcon, + DocumentIcon, + DocumentIconSolid, + EventsIconSolid, + SurveyIconSolid, + PMBIconSolid, + DustbinIcon, + ExternalLinkIcon, + DownloadImgIcon, + ViewsIcon, + PrevIcon, + DocumentSVG, + ArrowToFirst, + ArrowToLast, + DownloadPrefixIcon, + CaseIcon, + PersonIcon, + PTIcon, + OBPSIcon, + OBPSIconSolidBg, + CitizenTruck, + FSMIcon, + EDCRIcon, + BPAIcon, + BPAHomeIcon, + HelpIcon, + NotificationBell, + MapMarker, + Clock, + EventCalendar, + ImageIcon, + TickMark, + PDFSvg, + EditIcon, + SearchIcon, + DeleteIcon, + CreateLoiIcon, + PMBIcon, + GenericFileIcon, + ArrowLeftWhite, + WSICon, + ArrowVectorDown, + ArrowDirection, + CameraIcon, + RemoveIcon, + GalleryIcon, + EditPencilIcon, + AddressBookIcon, + LocationIcon, + CollectionsBookmarIcons, + FinanceChartIcon, + CollectionIcon, + MCollectIcon, + PGRIcon, + TLIcon, + BillsIcon, + ErrorIcon, + DownloadBtnCommon, + PrintBtnCommon, + WhatsappIconGreen, + HelpLineIcon, + ServiceCenterIcon, + TimerIcon, + RupeeSymbol, + ValidityTimeIcon, + AddIcon, + SubtractIcon, + AddNewIcon, + ViewReportIcon, + InboxIcon, + PrivacyMaskIcon, + FirenocIcon, + BirthIcon, + DeathIcon, + ArrowCollapseUp, + ArrowCollapseDown, + AddFilled, + AddFileFilled, + LocateIcon, + /* Works Management */ + NoResultsFoundIcon, + WorksMgmtIcon, + BioMetricIcon, + MuktaHomeIcon, + HRIcon, + ProjectIcon, + EstimateIcon, + ContractIcon, + AttendanceIcon, + WageseekerIcon, + OrganisationIcon, + HelperIcon, + DashboardIcon, + ExpenditureIcon, + DoubleTickIcon, + InfoIcon, + PaymentIcon, + HistoryIcon, + WarningIcon, + AttentionListIcon, + UploadIcon, + FileIcon, + DeleteIconv2, + InfoIconOutline, + XlsxFile, + JpgFile, + PdfFile, + DocFile, + PngFile, + DocUpload, + DocXlsxUpload, + DocPdfUpload, + DocdocUpload, + AddIconNew, +}; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/DatePicker.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/DatePicker.js new file mode 100644 index 00000000..edf5ca0b --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/DatePicker.js @@ -0,0 +1,45 @@ +import React, { useState, useRef } from "react"; +import PropTypes from "prop-types"; +import { getUserType } from "../utils/digitUtils"; + +const DatePicker = (props) => { + const dateInp = useRef(); + const isCitizen = getUserType() === "citizen" ? true : false; + + const selectDate = (e) => { + const date = e.target.value; + props?.onChange?.(date); + }; + + 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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/DisplayPhotos.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/DisplayPhotos.js new file mode 100644 index 00000000..8a306edd --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/DisplayPhotos.js @@ -0,0 +1,45 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { SVG } from "./SVG"; +import getFileTypeFromFileStoreURL from "../utils/getFileTypeFromFileStoreURL"; + +const ImageOrPDFIcon = ({ source, index, last = false, onClick }) => { + return 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/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Divider.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Divider.js new file mode 100644 index 00000000..98c4c437 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Divider.js @@ -0,0 +1,13 @@ +import React from "react"; +import PropTypes from 'prop-types'; + +const Divider = ({ className = "", style = {}, variant}) => { + return
; +}; + +Divider.propTypes = { + className: PropTypes.string, + style: PropTypes.object, +}; + +export default Divider; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Dropdown.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Dropdown.js new file mode 100644 index 00000000..1412d04c --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Dropdown.js @@ -0,0 +1,690 @@ +import PropTypes from "prop-types"; +import React, { useEffect, useRef, useState } from "react"; +import { SVG } from "./SVG"; +import TreeSelect from "./TreeSelect"; +import { CustomSVG } from "./CustomSVG"; +import Menu from "./Menu"; +import { Colors } from "../constants/colors/colorconstants"; +import { iconRender } from "../utils/iconRender"; +import { getUserType } from "../utils/digitUtils"; +import StringManipulator from "./StringManipulator"; + +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); + // the dropdown searchablility is made configurable through isSearchable prop + if (props.isSearchable) { + props.setFilter(e.target.value); + } + } + + function broadcastToOpen() { + if (!props.disable) { + props.dropdownDisplay(true); + } + } + + function broadcastToClose() { + props.dropdownDisplay(false); + } + + const replaceDotWithColon = (inputString) => { + if ( + props?.variant === "nesteddropdown" || + (props?.variant === "treedropdown" && inputString) + ) { + const updatedInputString = inputString.replace(/\./g, ": "); + return updatedInputString; + } + return inputString; + }; + + /* 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") { + if (props.addProps.length === 1) { + props.addProps.selectOption(0); + } + else { + 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} + title={props.showToolTip ? replaceDotWithColon(value) : undefined} + /> + ); +}; + +const translateDummy = (text) => { + return text; +}; + +const Dropdown = (props) => { + const user_type = getUserType(); + const [dropdownStatus, setDropdownStatus] = useState(false); + const [menuStatus, setMenuStatus] = useState(false); + const [selectedOption, setSelectedOption] = useState( + props.selected ? props.selected : null + ); + const [filterVal, setFilterVal] = useState(""); + const [isActive, setIsActive] = useState(-1); + const [forceSet, setforceSet] = useState(0); + const [optionIndex, setOptionIndex] = useState(-1); + const optionRef = useRef(null); + const dropdownComponentRef = useRef(null); + const menuRef = useRef(null); + const selectorRef = useRef(null); + const hasCustomSelector = props.customSelector ? true : false; + const t = props.t || translateDummy; + + + const scrollIntoViewIfNeeded = () => { + if (dropdownComponentRef.current) { + const rect = dropdownComponentRef.current.getBoundingClientRect(); + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + + // Check if the component is outside the viewport + const isOutsideViewport = + rect.top < 0 || rect.left < 0 || rect.bottom > viewportHeight || rect.right > viewportWidth; + + if (isOutsideViewport) { + // Scroll to make the component visible + dropdownComponentRef.current.scrollIntoView({ + behavior: "smooth", // Optional: smooth scrolling + block: "center", // Scroll to the center vertically + inline: "center", // Scroll to the center horizontally + }); + } + } + }; + + useEffect(() => { + scrollIntoViewIfNeeded(); + }, []); // Runs on mount + + + useEffect(() => { + setSelectedOption(props.selected); + }, [props.selected]); + + function dropdownSwitch() { + if (!props.disabled) { + var current = dropdownStatus; + if (!current) { + document.addEventListener("mousedown", handleClick, false); + } + setDropdownStatus(!current); + props?.onBlur?.(); + } + } + + function menuSwitch(){ + if(!props.disabled){ + var current = menuStatus; + if (!current) { + document.addEventListener("mousedown", handleClickOutside, false); + } + setMenuStatus(!current); + props?.onBlur?.(); + } + } + + function handleClickOutside(e) { + if (!menuRef.current || !menuRef.current.contains(e.target)) { + if(selectorRef?.current && selectorRef?.current.contains(e.target)){ + return ; + } + else{ + document.removeEventListener("mousedown", handleClickOutside, false); + setMenuStatus(false); + } + } + } + + 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); + setDropdownStatus(false); + } + } + + 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) { + const optionsToSelect = + props.variant === "nesteddropdown" || props.variant === "treedropdown" + ? flattenedOptions + : filteredOption; + onSelect(optionsToSelect[ind]); + } + + if (props.isBPAREG && selectedOption) { + let isSelectedSameAsOptions = + props.option?.filter((ob) => ob?.code === selectedOption?.code)?.length > + 0; + if (!isSelectedSameAsOptions) setSelectedOption(null); + } + + const inputBorderColor = Colors.lightTheme.generic.inputBorder; + const dividerColor = Colors.lightTheme.generic.divider; + const primaryColor = Colors.lightTheme.paper.primary; + + const IconRender = (iconReq, isActive) => { + const iconFill = isActive ? primaryColor : inputBorderColor; + return iconRender( + iconReq, + iconFill, + "1.25rem", + "1.25rem", + "" + ); + }; + + const flattenOptions = (options) => { + let flattened = []; + + const flattenNestedOptions = (nestedOptions) => { + nestedOptions.forEach((nestedOption) => { + flattened.push(nestedOption); + if (nestedOption.options) { + flattenNestedOptions(nestedOption.options); + } + }); + }; + + const parentOptionsWithChildren = options.filter( + (option) => option.options && option.options.length > 0 + ); + + parentOptionsWithChildren.forEach((option) => { + if (option.options) { + flattened.push(option); + flattenNestedOptions(option.options); + } else { + flattened.push(option); + } + }); + + return flattened; + }; + + const flattenedOptions = flattenOptions(filteredOption); + + const renderOption = (option, index) => { + const handleMouseDown = (e) => { + if (e.button === 0) setIsActive(index); + }; + const handleMouseUp = () => { + setIsActive(-1); + }; + + return ( +
onSelect(option)} + onMouseDown={handleMouseDown} + onMouseUp={handleMouseUp} + > + {props?.variant === "profiledropdown" || + props?.variant === "profilenestedtext" ? ( +
+ {!option?.profileIcon && ( + + )} +
+ ) : null} +
+
+ {props?.showIcon && + option?.icon && + IconRender(option?.icon, index === isActive)} + {props.isPropertyAssess ? ( +
+ {props.t + ? props.t(option[props?.optionKey]) + : option[props?.optionKey]} +
+ ) : ( + + {StringManipulator("TOSENTENCECASE", props.t + ? props.t(option[props?.optionKey]) + : option[props?.optionKey])} + + )} +
+ {(props.variant === "nestedtextdropdown" || + props.variant === "profilenestedtext") && + option.description && ( +
{StringManipulator("TOSENTENCECASE", option.description)}
+ )} +
+
+ ); + }; + + const optionsToRender = + props.variant === "nesteddropdown" || props.variant === "treedropdown" + ? flattenedOptions + : filteredOption; + + const parentOptionsWithChildren = filteredOption.filter( + (option) => option.options && option.options.length > 0 + ); + + const renderOptions = () => { + return optionsToRender.map((option, index) => { + if (option.options) { + return ( +
+
+ {props.variant === "treedropdown" && + option.options.length > 0 && ( + + )} + {StringManipulator("TOSENTENCECASE",t(option[props?.optionKey]))} +
+
+ ); + } else { + return renderOption(option, index); + } + }); + }; + return ( +
+ {(hasCustomSelector || props?.profilePic) && ( +
+ {props?.profilePic && ( + + {typeof props?.profilePic === "string" + ? props?.profilePic?.[0]?.toUpperCase() + : props?.profilePic} + + )} + {!props?.profilePic && props?.customSelector} + {props?.showArrow && ( + + + + )} +
+ )} + + {!hasCustomSelector && !props?.profilePic && ( +
+ + {props.showSearchIcon ? null : ( + + )} + {props.showSearchIcon ? ( + + ) : null} +
+ )} + {(hasCustomSelector || props?.profilePic) && menuStatus && ( +
+ +
+ )} + {!hasCustomSelector && !props?.profilePIc && dropdownStatus ? ( + props.optionKey ? ( +
+ {props.variant === "treedropdown" ? ( + + ) : ( + renderOptions() + )} + {(props.variant === "nesteddropdown" + ? flattenedOptions + : filteredOption) && + (props.variant === "nesteddropdown" + ? flattenedOptions + : filteredOption + ).length === 0 && ( +
{}} + > + { {t("NO_RESULTS_FOUND")}} +
+ )} +
+ ) : ( +
+ {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, + isSearchable: true, +}; + +export default Dropdown; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ErrorBoundary.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ErrorBoundary.js new file mode 100644 index 00000000..075b977b --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ErrorBoundary.js @@ -0,0 +1,36 @@ +import Toast from "./Toast"; +import React, { Component } from 'react'; + +class ErrorBoundary extends Component { + state = { + hasError: false, + error: null, + errorInfo: null + }; + + componentDidCatch(error, errorInfo) { + // Log the error to an error reporting service + console.error('Error caught by ErrorBoundary:', error, errorInfo); + this.setState({ + hasError: true, + error: error, + errorInfo: errorInfo + }); + } + + render() { + if (this?.state?.hasError) { + // Render fallback UI + return ( +
+ {this?.state?.error?.toString() && } + {this?.props?.children} +
+ ); + } + // Render children normally + return this?.props?.children; + } +} + +export default ErrorBoundary; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ErrorMessage.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ErrorMessage.js new file mode 100644 index 00000000..77d388fc --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/ErrorMessage.js @@ -0,0 +1,55 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { SVG } from "./SVG"; +import StringManipulator from "./StringManipulator"; +import { Colors} from "../constants/colors/colorconstants"; + +const ErrorMessage = ({ + wrapperClassName = "", + wrapperStyles = {}, + showIcon, + iconStyles = {}, + message, + className = "", + style = {}, + truncateMessage, + maxLength, +}) => { + + const IconColor = Colors.lightTheme.alert.error; + + return ( +
+ {showIcon && ( +
+ +
+ )} +
+ {truncateMessage + ? StringManipulator( + "TOSENTENCECASE", + StringManipulator("TRUNCATESTRING", message, { + maxLength: maxLength || 256, + }) + ) + : StringManipulator("TOSENTENCECASE", message)} +
+
+ ); +}; + +ErrorMessage.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + message: PropTypes.string, + showIcon: PropTypes.bool, + truncateMessage: PropTypes.bool, +}; + +export default ErrorMessage; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/FileUpload.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/FileUpload.js new file mode 100644 index 00000000..e6bc285d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/FileUpload.js @@ -0,0 +1,553 @@ +import React, { useEffect, useRef, useState, Fragment } from "react"; +import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; +import ErrorMessage from "./ErrorMessage"; +import StringManipulator from "./StringManipulator"; +import Chip from "./Chip"; +import { SVG } from "./SVG"; +import UploadWidget from "./UploadWidget"; +import UploadImage from "./UploadImage"; +import Button from "./Button"; +import { Colors} from "../constants/colors/colorconstants"; +import { CustomSVG } from "./CustomSVG"; +import { getUserType } from "../utils/digitUtils"; + +const getRandomId = () => { + return Math.floor((Math.random() || 1) * 139); +}; + +const FileUpload = (props) => { + const { t } = useTranslation(); + const inpRef = useRef(); + const user_type = getUserType(); + const [buttonLabel, setButtonLabel] = useState("Upload"); + const [inputLabel, setInputLabel] = useState(""); + const [uploadedFilesCount, setUploadedFilesCount] = useState(0); + const [uploadedFiles, setUploadedFiles] = useState([]); + const [previews, setPreviews] = useState([]); + const [errors, setErrors] = useState([]); + + const handleFileUpload = async (e) => { + const files = props.variant === "uploadField" ? e.target.files : e; + const newErrors = []; + if (files.length > 0) { + const acceptedFiles = []; + for (let i = 0; i < files.length; i++) { + const file = files[i]; + const { isValid, error } = validateFile(file, props); + if (isValid) { + acceptedFiles.push(file); + } else { + newErrors.push({ file, error }); + } + } + let newFiles; + if (props.variant === "uploadImage" || props.variant === "uploadWidget") { + newFiles = files; + } else { + newFiles = props?.multiple ? [...uploadedFiles, ...files] : [files[0]]; + } + setUploadedFiles(newFiles); + setUploadedFilesCount(newFiles.length); + setErrors([...errors, ...newErrors]); + } + + if (props?.onUpload) { + const uploadResult = await props?.onUpload(uploadedFiles); + if (uploadResult && uploadResult.length !== 0) { + for (const { file, error } of uploadResult) { + const fileIndex = newErrors.findIndex((item) => item.file === file); + if (fileIndex !== -1) { + newErrors[fileIndex].error = error; + } else { + newErrors.push({ file, error }); + } + } + } + } + }; + + const validateFile = (file, props) => { + let isValid = true; + let error = ""; + const maxFileSize = props.validations?.maxSizeAllowedInMB; + const minFileSize = props.validations?.minSizeRequiredInMB; + const acceptedImageTypes = [ + "image/png", + ".png", + ".jpeg", + ".jpg", + "image/jpeg", + "image/jpg", + ]; + + if (maxFileSize && Math.round(file?.size / 1024 / 1024) > maxFileSize) { + isValid = false; + error = "File size exceeds the maximum allowed size"; + } else if ( + minFileSize && + Math.round(file?.size / 1024 / 1024) < minFileSize + ) { + isValid = false; + error = "File size is below the minimum required size"; + } + + if ( + props.variant === "uploadImage" && + !acceptedImageTypes.includes(file.type) + ) { + isValid = false; + error = "File type is not accepted"; + } + + return { isValid, error }; + }; + + const handleButtonClick = () => { + inpRef.current.click(); + }; + + const handleFileRemove = (fileToRemove) => { + if (!Array.isArray(uploadedFiles)) { + setUploadedFiles([]); + setUploadedFilesCount(0); + setErrors([]); + } else { + const updatedFiles = uploadedFiles.filter( + (file) => file !== fileToRemove + ); + const updatedErrors = errors.filter( + (error) => error.file !== fileToRemove + ); + setUploadedFiles(updatedFiles); + setUploadedFilesCount(updatedFiles.length); + setErrors(updatedErrors); + } + props?.removeTargetedFile && props?.removeTargetedFile(fileToRemove); + }; + + const handleFileDownload = (file) => { + if (file && file?.url) { + window.location.href = file?.url; + } + }; + + const generatePreview = (file) => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onload = (e) => { + const result = e.target.result; + resolve(result); + }; + reader.readAsDataURL(file); + }); + }; + + useEffect(() => { + const uploadFiles = async () => { + if (props?.onUpload) { + const uploadResult = await props?.onUpload(uploadedFiles); + if (uploadResult && uploadResult.length !== 0) { + setErrors((prevErrors) => { + const newErrors = []; + uploadResult.forEach(({ file, error }) => { + const existingErrorIndex = prevErrors.findIndex((item) => item.file === file); + if (existingErrorIndex !== -1) { + prevErrors[existingErrorIndex].error = error; + } else { + newErrors.push({ file, error }); + } + }); + return [...prevErrors, ...newErrors]; + }); + } + } + }; + if (uploadedFiles.length > 0) { + uploadFiles(); + } + }, [uploadedFiles,props?.onUpload]); + + useEffect(() => { + setButtonLabel( + !props.multiple && uploadedFilesCount > 0 ? "Re-Upload" : "Upload" + ); + }, [uploadedFilesCount, props.multiple]); + + useEffect(() => { + setInputLabel( + uploadedFilesCount !== 0 ? `${uploadedFilesCount} Uploaded` : "" + ); + }, [uploadedFilesCount]); + + useEffect(() => { + const generatePreviews = async () => { + const previewsArray = []; + for (const file of uploadedFiles) { + if (file instanceof Blob) { + const preview = await generatePreview(file); + if (preview) { + const fileErrors = errors.filter((error) => error.file === file); + previewsArray.push({ + file, + preview, + error: fileErrors.length > 0 ? fileErrors[0].error : null, + }); + } else { + console.error("Failed to generate preview for:", file); + } + } else { + const blob = new Blob([file], { type: file?.type }); + const preview = await generatePreview(blob); + if (preview) { + const fileErrors = errors.filter((error) => error.file === file); + previewsArray.push({ + file, + preview, + error: fileErrors.length > 0 ? fileErrors[0].error : null, + }); + } else { + console.error("Failed to generate preview for:", file); + } + console.error("Invalid file object:", file); + } + } + setPreviews(previewsArray); + }; + + generatePreviews(); + + return () => { + setPreviews([]); + }; + }, [uploadedFiles]); + + const showHint = props?.showHint || false; + + const showLabel = props?.showLabel || false; + + const { fileUrl, fileName = "Unknown File" } = Digit.Hooks.useQueryParams(); + + const changeToBlobAndCreateUrl = (file) => { + if (!file) return null; + const blob = new Blob([file], { type: file?.type }); + return URL.createObjectURL(blob); + }; + + const documents = fileUrl + ? [{ uri: fileUrl, fileName }] + : uploadedFiles.map((file) => ({ + uri: changeToBlobAndCreateUrl(file), + fileName: file?.name || fileName, + })); + + const handleFileClick = (index, file) => { + const url = changeToBlobAndCreateUrl(file); + window.open(url, "_blank"); + }; + + const primaryColor = Colors.lightTheme.paper.primary; + const errorColor = Colors.lightTheme.alert.error; + + const getFileUploadIcon = (fileType, isError) => { + switch (fileType) { + case "application/pdf": + return ( + + ); + case "application/vnd.ms-excel": + case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": + case "application/excel": + case "application/x-excel": + case "application/x-msexcel": + return ( + + ); + case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": + case "application/msword": + return ( + + ); + default: + return ( + + ); + } + }; + + const renderVariant = () => { + switch (props.variant) { + case "uploadWidget": + return ( + + + + ); + case "uploadImage": + return ( + + + + ); + case "uploadField": + default: + return ( + +
+
+ + +
+
+ {props?.showAsTags && ( +
+ {uploadedFiles?.map((file, index) => { + const fileErrors = errors.filter( + (error) => error.file === file + ); + const isError = fileErrors.length > 0; + return ( + { + e.stopPropagation(); + handleFileRemove(file); + }} + isErrorTag={isError} + error={fileErrors[0]?.error} + onTagClick={() => handleFileClick(index, file)} + onErrorClick={(e) => e.stopPropagation()} + /> + ); + })} +
+ )} + {props?.showAsPreview && ( +
+ {uploadedFiles.map((file, index) => { + const fileErrors = errors.filter( + (error) => error.file === file + ); + const isError = fileErrors.length > 0; + + return ( + +
1 ? " multiple" : "single" + } ${file?.type.startsWith("image/") ? "imageFile" : ""} ${isError ? "error" : ""}`} + > +
{ + handleFileClick(index, file); + }} + > + {file?.type.startsWith("image/") ? ( + {`Preview + ) : ( + getFileUploadIcon(file?.type, isError) + )} +
+
{ + handleFileClick(index, file); + }} + >
+
+ {file?.name && !isError ? file?.name : ""} +
+ { + handleFileRemove(file); + }} + className={`digit-uploader-close-icon ${ + isError ? "error" : "" + }`} + > + + + {fileErrors[0]?.error && ( + + )} +
+
+ ); + })} +
+ )} +
+ ); + } + }; + + return ( + +
+ {showLabel &&

{t(props?.label)}

} + {renderVariant()} + {props?.iserror && ( + + )} + {showHint && ( +

+ {StringManipulator( + "toSentenceCase", + StringManipulator("truncateString", t(props?.hintText), { + maxLength: 256, + }) + )} +

+ )} +
+
+ ); +}; + +FileUpload.propTypes = { + hintText: PropTypes.string, + showHint: PropTypes.bool, + label: PropTypes.string, + showLabel: PropTypes.bool, + showAsTags: PropTypes.bool, + showAsPreview: PropTypes.bool, + customClass: PropTypes.string, + uploadedFiles: PropTypes.arrayOf( + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])) + ), + disableButton: PropTypes.bool, + buttonType: PropTypes.string, + onUpload: PropTypes.func, + removeTargetedFile: PropTypes.func, + onDelete: PropTypes.func, + iserror: PropTypes.string, + disabled: PropTypes.bool, + inputStyles: PropTypes.object, + multiple: PropTypes.bool, + accept: PropTypes.string, + id: PropTypes.string, + showDownloadButton: PropTypes.bool, + showReUploadButton: PropTypes.bool, +}; + +FileUpload.defaultProps = { + disableButton: false, +}; + +export default FileUpload; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Footer.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Footer.js new file mode 100644 index 00000000..16b642c5 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Footer.js @@ -0,0 +1,76 @@ +import React,{useState,useEffect} from "react"; +import PropTypes from "prop-types"; + +const Footer = (props) => { + + const [isMobileView, setIsMobileView] = useState(window.innerWidth <= 480); + const onResize = () => { + if (window.innerWidth <= 480) { + if (!isMobileView) { + setIsMobileView(true); + } + } else { + if (isMobileView) { + setIsMobileView(false); + } + } + }; + useEffect(() => { + window.addEventListener("resize", () => { + onResize(); + }); + return () => { + window.removeEventListener("resize", () => { + onResize(); + }); + }; + }); + + const hasActionFields = props?.actionFields?.length > 0; + const allowedActionFields = hasActionFields + ? props?.actionFields.slice(0, props?.maxActionFieldsAllowed || 5) + : []; + const sortedActionFields = [...allowedActionFields].sort((a, b) => { + const typeOrder = { primary: 3, secondary: 2, tertiary: 1 }; + const getTypeOrder = (button) => + typeOrder[(button.props.variation || "").toLowerCase()]; + return getTypeOrder(a) - getTypeOrder(b); + }); + const finalActionFields = props?.sortActionFields + ? isMobileView + ? sortedActionFields.reverse() + : sortedActionFields + : allowedActionFields; + + + + return ( +
+ {hasActionFields && ( +
+ {finalActionFields.map((field, index) => ( +
+ {field} +
+ ))} +
+ )} + {props?.children} +
+ ); +}; + +Footer.propTypes = { + /** custom class of the svg icon */ + className: PropTypes.string, + /** custom style of the svg icon */ + style: PropTypes.object, +}; + +export default Footer; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Hamburger.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Hamburger.js new file mode 100644 index 00000000..910cd06d --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Hamburger.js @@ -0,0 +1,357 @@ +import React, { useState,Fragment ,useRef,useEffect} from "react"; +import { useTranslation } from "react-i18next"; +import PropTypes from "prop-types"; +import { SVG } from "./SVG"; +import { CustomSVG } from "./CustomSVG"; +import Button from "./Button"; +import TextInput from "./TextInput"; +import { Colors } from "../constants/colors/colorconstants"; +import { iconRender } from "../utils/iconRender"; +import { Spacers } from "../constants/spacers/spacers"; + +const Hamburger = ({ + items, + profileName, + profileNumber, + theme, + className, + styles, + hideUserManuals, + userManualLabel, + profile, + usermanuals, + onSelect, + onLogout, + reopenOnLogout, + closeOnClickOutside, + onOutsideClick +}) => { + const { t } = useTranslation(); + const [searchTerms, setSearchTerms] = useState({}); + const [selectedItem, setSelectedItem] = useState({}); + const [expandedItems, setExpandedItems] = useState({}); + const [openUserManuals, setOpenUserManuals] = useState(false); + const [showHamburger,setShowHamburger] = useState(true); + const sidebarRef = useRef(null); + + const iconSize = Spacers.spacer6; + + useEffect(() => { + if (!closeOnClickOutside && !onOutsideClick) return; + + const handleClickOutside = (event) => { + if (sidebarRef.current && !sidebarRef.current.contains(event.target)) { + if (onOutsideClick) { + onOutsideClick(event); + } + if (closeOnClickOutside) { + setShowHamburger(false); + } + } + }; + + document.addEventListener("mousedown", handleClickOutside); + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [closeOnClickOutside, onOutsideClick]); + + + const handleItemClick = (item, index, parentIndex) => { + setSelectedItem({ item: item, index: index, parentIndex: parentIndex }); + onSelect && onSelect({ item: item, index: index, parentIndex: parentIndex }); + }; + + const handleSearchChange = (index, value) => { + setSearchTerms((prev) => ({ + ...prev, + [index]: value, + })); + }; + + const onLogoutClick = () => { + setShowHamburger(false); + onLogout && onLogout(); + onLogout && reopenOnLogout && setShowHamburger(true); + } + + const filterItems = (items, searchTerm) => { + return items?.filter((item) => { + if (item?.label?.toLowerCase().includes(searchTerm.toLowerCase())) { + return true; + } + if (item?.children) { + item.children = filterItems(item?.children, searchTerm); + return item?.children.length > 0; + } + return false; + }); + }; + + const darkThemeIconColor = Colors.lightTheme.paper.primary; + const lightThemeIconColor = Colors.lightTheme.primary[2]; + + const renderSearch = (index) => ( +
+ handleSearchChange(index, e.target.value)} + placeholder="Search" + autoFocus={true} + iconFill={theme === "dark" ? darkThemeIconColor : lightThemeIconColor} + > +
+ ); + + const handleArrowClick = (item, index, parentIndex) => { + if (item?.children) { + setExpandedItems((prev) => ({ + ...prev, + [index]: !prev[index], + })); + } + else { + handleItemClick(item, index, parentIndex); + } + }; + + const userManualsToShow = + usermanuals && usermanuals.length > 0 + ? usermanuals + : [ + { + label: "Help", + icon: "Home", + }, + { + label: "Settings", + icon: "Settings", + }, + ]; + + const Icon = (icon,className) =>{ + return ( + iconRender( + icon, + theme === "light" ? lightThemeIconColor : darkThemeIconColor, + iconSize, + iconSize, + className + ) + ) + } + const renderItems = (items, parentIndex = -1) => items?.map((item, index) => { + const currentIndex = parentIndex >= 0 ? `${parentIndex}-${index}` : index; + const isExpanded = expandedItems[currentIndex]; + const isTopLevel = parentIndex === -1; + return ( + <> +
+
handleArrowClick(item, currentIndex, parentIndex)} + tabIndex={0} + > + {item?.icon && Icon(item?.icon,"digit-msb-icon")} + {{item?.label}} + {item?.children && ( + + {isExpanded ? ( + + ) : ( + + )} + + )} +
+
+ {item?.children && isExpanded && ( +
+ {item?.isSearchable && renderSearch(currentIndex)} + {filterItems(item?.children, searchTerms[currentIndex] || "") + .length > 0 ? ( + renderChildItems( + filterItems(item?.children, searchTerms[currentIndex] || ""), + currentIndex, + false + ) + ) : ( +
{t("No Results Found")}
+ )} +
+ )} + + ); + }); + + const renderChildItems = (items, parentIndex = -1, isUserManual) => + items?.map((item, index) => { + const currentIndex = parentIndex >= 0 ? `${parentIndex}-${index}` : index; + const isExpanded = expandedItems[currentIndex]; + const icon = item?.icon ? Icon(item?.icon,"digit-icon-msb") : null; + return ( + <> +
+
handleItemClick(item, currentIndex, parentIndex)} + tabIndex={0} + > + {icon} + {/* {item.icon && Icon(item.icon, "digit-icon-msb")} */} + { + + {item?.label} + + } + {item?.children && ( + { + e.stopPropagation(); + handleArrowClick(item, currentIndex, parentIndex); + }} + > + {isExpanded ? ( + + ) : ( + + )} + + )} +
+
+
+ {item?.children && isExpanded && ( +
+ {renderChildItems(item?.children, currentIndex)} +
+ )} +
+ + ); + }); + + const filteredItems = filterItems(items, searchTerms["root"] || ""); + + return showHamburger ? ( +
+
+ {!profile && } + {profile && ( + Profile + )} +
+
{profileName}
+
+ {profileNumber} +
+
+
+
{renderItems(filteredItems)}
+ {!hideUserManuals && ( +
+
setOpenUserManuals(!openUserManuals)} + > + + { + + } + + + {t(userManualLabel) || t("UserManuals")} + +
+
+ )} + { + openUserManuals && ( + renderChildItems(userManualsToShow,-1,true) + ) + } +
+
+
+ ) : null; +}; + +Hamburger.propTypes = { + items: PropTypes.arrayOf( + PropTypes.shape({ + path: PropTypes.string, + icon: PropTypes.node.isRequired, + label: PropTypes.string.isRequired, + }) + ).isRequired, + profileName: PropTypes.string, + profileNumber: PropTypes.string, + isSearchable:PropTypes.bool, + userManualLabel:PropTypes.string, + reopenOnLogout:PropTypes.bool +}; + +export default Hamburger; \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HamburgerButton.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HamburgerButton.js new file mode 100644 index 00000000..75ad91b9 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HamburgerButton.js @@ -0,0 +1,10 @@ +import React from "react"; +import { CustomSVG } from "./CustomSVG"; + +const HamburgerButton = ({ handleClick, color ,className}) => ( +
+ +
+); + +export default HamburgerButton; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Header.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Header.js new file mode 100644 index 00000000..8c905f31 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Header.js @@ -0,0 +1,160 @@ +import React, { useEffect, useState, Fragment } from "react"; +import PropTypes from "prop-types"; +import Hamburger from "./Hamburger"; +import { IMAGES} from "../constants/images/images"; +import { Colors} from "../constants/colors/colorconstants"; + +const Header = ({ + img, + className, + style, + theme, + setImageToLeft, + onImageClick, + onLogoClick, + onHamburgerClick, + props, + logo, + ulb, + actionFields, +}) => { + const [isMobileView, setIsMobileView] = useState(window.innerWidth <= 768); + const onResize = () => { + if (window.innerWidth <= 768) { + if (!isMobileView) { + setIsMobileView(true); + } + } else { + if (isMobileView) { + setIsMobileView(false); + } + } + }; + useEffect(() => { + window.addEventListener("resize", () => { + onResize(); + }); + return () => { + window.addEventListener("resize", () => { + onResize(); + }); + }; + }); + + const getImageUrl = (imageKey) => { + return IMAGES[imageKey] ; + }; + + const digitImg = img || (theme === "dark" ? getImageUrl('DIGIT_DARK') : getImageUrl('DIGIT_LIGHT')); + const darkThemeColor = Colors.lightTheme.paper.primary; + const lightThemeColor = Colors.lightTheme.text.primary; + + if (isMobileView) { + return ( +
+ +
+ Powered by DIGIT onImageClick()} + width={"80px"} + height={"19px"} + /> +
+
+ {ulb} +
+
+
+ ); + } + + return ( +
+ {!setImageToLeft && ( +
+ {logo && ( +
+ Logo onLogoClick()} + width={props?.logoWidth || "32px"} + height={props?.logoHeight || "32px"} + /> +
+ )} +
{ulb}
+
+ )} + {setImageToLeft && ( +
+ Powered by DIGIT onImageClick()} + width={"80px"} + height={"19px"} + /> +
+ )} +
+ {actionFields && ( + <> + {actionFields.map((field, index) => ( +
+ {field} +
+ ))} + + )} + { + (!setImageToLeft) && ( + Powered by DIGIT onImageClick()} + width={"80px"} + height={"19px"} + /> + ) + } +
+
+ ); +}; +Header.propTypes = { + img: PropTypes.string, + className: PropTypes.string, + style: PropTypes.object, + theme: PropTypes.string, + setImageToLeft: PropTypes.bool, + onImageClick: PropTypes.func, + onLogoClick: PropTypes.func, + onHamburgerClick: PropTypes.func, + props: PropTypes.object, + logo: PropTypes.string, +}; +Header.defaultProps = { + img: undefined, +}; +export default Header; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HeaderBar.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HeaderBar.js new file mode 100644 index 00000000..ae8effe4 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HeaderBar.js @@ -0,0 +1,26 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const HeaderBar = (props) => { + return ( +
+ {props.start ?
{props.start}
: null} + {props.main ?
{props.main}
: null} + {props.end ?
{props.end}
: null} +
+ ); +}; + +HeaderBar.propTypes = { + start: PropTypes.any, + main: PropTypes.any, + end: PropTypes.any, +}; + +HeaderBar.defaultProps = { + start: "", + main: "", + end: "", +}; + +export default HeaderBar; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HeaderComponent.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HeaderComponent.js new file mode 100644 index 00000000..2b040f15 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HeaderComponent.js @@ -0,0 +1,18 @@ +import React from "react"; +import PropTypes from "prop-types"; + +const HeaderComponent = (props) => { + return ( +
+ {props.children} +
+ ); +}; + +HeaderComponent.propTypes = { + className: PropTypes.string, + styles: PropTypes.object, + children: PropTypes.node, +}; + +export default HeaderComponent; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HomeFooter.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HomeFooter.js new file mode 100644 index 00000000..d47b00b1 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HomeFooter.js @@ -0,0 +1,22 @@ +import React from "react"; + +function HomeFooter(props) { + const info = window?.Digit?.UserService?.getUser()?.info || null; + const userType = info?.type || null; + const additionalClassname = userType === "EMPLOYEE" ? "employee" : "citizen"; + + return ( +
+ Powered by DIGIT { + window.open(window?.globalConfigs?.getConfig?.("DIGIT_HOME_URL"), "_blank").focus(); + }} + /> +
+ ); +} + +export default HomeFooter; diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HorizontalNav.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HorizontalNav.js new file mode 100644 index 00000000..430369ae --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/HorizontalNav.js @@ -0,0 +1,39 @@ +import React, {useState} from 'react' +import { useTranslation } from 'react-i18next' + +const HorizontalNav = ({ configNavItems, activeLink, setActiveLink, showNav = false, children, customStyle = {}, customClassName = "", inFormComposer = true, navClassName = "", navStyles = {} }) => { + const { t } = useTranslation() + + const setActive = (item) => { + setActiveLink(item.name) + } + + const MenuItem = ({ item }) => { + let itemComponent = item.code; + + const Item = () => ( + +
{t(itemComponent)}
+
+ ); + + return ( + + ); + }; + return ( +
+ {showNav &&
+ {configNavItems?.map((item, index) => ( +
setActive(item)}> + +
+ ))} +
+ } + {children} +
+ ) +} + +export default HorizontalNav \ No newline at end of file diff --git a/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Iframe.js b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Iframe.js new file mode 100644 index 00000000..0772beb1 --- /dev/null +++ b/micro-ui/web/micro-ui-internals/packages/ui-components/src/atoms/Iframe.js @@ -0,0 +1,16 @@ +import React from "react"; + +const Iframe = (props) => { + return ( +