From 88de9320718435a9573cd09a692d6f7012d3e1d3 Mon Sep 17 00:00:00 2001 From: Eric Darchis Date: Mon, 11 Sep 2023 22:23:54 +0200 Subject: [PATCH 001/111] Customise to CAMU --- src/components/RequireAuth.js | 3 ++- src/pages/LoginPage.js | 2 +- src/translations/en.json | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index 3c099b01..c5dfb6b5 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -189,7 +189,8 @@ const RequireAuth = (props) => { )} - } /> + CAMU + diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js index b5ab8d7d..6979e888 100644 --- a/src/pages/LoginPage.js +++ b/src/pages/LoginPage.js @@ -79,7 +79,7 @@ const LoginPage = ({ logo }) => { - {formatMessage("appName")} + {formatMessage("core.displayAppName")} diff --git a/src/translations/en.json b/src/translations/en.json index 756a2b38..36b4f299 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -12,6 +12,7 @@ "core.roleManagement.null": "Any", "core.roleManagement.true": "True", "core.roleManagement.false": "False", + "core.displayAppName": "CAMU", "core.roleManagement.createButton.tooltip": "Create new Role", "core.roleManagement.role.page.title": "Role Details {label}", "core.roleManagement.requiredFieldsEmptyError": "* These fields are required", From bb2c77ff3628e8912bc0245473729b1bda0101bf Mon Sep 17 00:00:00 2001 From: Eric Darchis Date: Mon, 25 Sep 2023 23:28:09 +0200 Subject: [PATCH 002/111] Add graphqlMutationLegacy() for sync call The graphqlWithVariables had a method to wait for the result but not the legacy graphql (with a plain query rather than a variable) --- src/actions.js | 22 +++++++++++++++++++--- src/index.js | 4 ++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/actions.js b/src/actions.js index 870848fd..da30c249 100644 --- a/src/actions.js +++ b/src/actions.js @@ -147,7 +147,7 @@ export function prepareMutation(operation, input, params = {}) { return { operation, variables, clientMutationId: params.clientMutationId }; } -export function waitForMutation(clientMutationId) { +export function waitForMutation(clientMutationId, additionalRequest = "") { return async (dispatch) => { let attempts = 0; let res; @@ -166,6 +166,7 @@ export function waitForMutation(clientMutationId) { clientMutationId jsonContent error + ${additionalRequest} } } } @@ -186,7 +187,7 @@ export function waitForMutation(clientMutationId) { }; } -export function graphqlMutation(mutation, variables, type = "CORE_TRIGGER_MUTATION", params = {}, wait = true) { +export function graphqlMutation(mutation, variables, type = "CORE_TRIGGER_MUTATION", params = {}, wait = true, additionalRequest = "") { let clientMutationId; if (variables?.input) { clientMutationId = uuid.uuid(); @@ -197,11 +198,26 @@ export function graphqlMutation(mutation, variables, type = "CORE_TRIGGER_MUTATI if (clientMutationId) { dispatch(fetchMutation(clientMutationId)); if (wait) { - return dispatch(waitForMutation(clientMutationId)); + return dispatch(waitForMutation(clientMutationId, additionalRequest)); } else { return response?.payload?.data; } } + }; +} + +export function graphqlMutationLegacy(payload, type = "CORE_TRIGGER_MUTATION", params = {}, wait = true, additionalRequest = "") { + if (wait && !params.clientMutationId) { + console.error("graphqlMutationLegacy cannot wait with a specified clientMutationId"); + } + return async (dispatch) => { + const response = await dispatch(graphql(payload, type, params)); + dispatch(fetchMutation(params.clientMutationId)); + if (wait) { + return dispatch(waitForMutation(params.clientMutationId, additionalRequest)); + } else { + return response?.payload?.data; + } return response; }; } diff --git a/src/index.js b/src/index.js index 84495292..ec3b18d7 100644 --- a/src/index.js +++ b/src/index.js @@ -50,7 +50,9 @@ import { apiHeaders, graphql, graphqlMutation, + graphqlMutationLegacy, graphqlWithVariables, + waitForMutation, journalize, coreAlert, coreConfirm, @@ -169,6 +171,8 @@ export { graphql, graphqlWithVariables, graphqlMutation, + graphqlMutationLegacy, + waitForMutation, journalize, fetchMutation, prepareMutation, From 7f0205b9134445349892cfed90107f5ad6ef751e Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 26 Sep 2023 16:10:36 +0530 Subject: [PATCH 003/111] component changes --- src/components/generics/Picker.js | 2 +- src/components/inputs/SelectInput.js | 2 +- src/components/inputs/TextInput.js | 2 +- src/pickers/AdDatePicker.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/generics/Picker.js b/src/components/generics/Picker.js index dbfdc1c1..d51de1ce 100644 --- a/src/components/generics/Picker.js +++ b/src/components/generics/Picker.js @@ -22,7 +22,7 @@ import FakeInput from "../inputs/FakeInput"; const styles = (theme) => ({ label: { - color: theme.palette.primary.main, + color: theme.palette.text.primary, }, dialogTitle: theme.dialog.title, dialogContent: theme.dialog.content, diff --git a/src/components/inputs/SelectInput.js b/src/components/inputs/SelectInput.js index 1784d9a1..e13eca64 100644 --- a/src/components/inputs/SelectInput.js +++ b/src/components/inputs/SelectInput.js @@ -8,7 +8,7 @@ import _ from "lodash-uuid"; const styles = (theme) => ({ label: { - color: theme.palette.primary.main, + color: theme.palette.text.primary, }, }); diff --git a/src/components/inputs/TextInput.js b/src/components/inputs/TextInput.js index fc62a55f..04d7a687 100644 --- a/src/components/inputs/TextInput.js +++ b/src/components/inputs/TextInput.js @@ -6,7 +6,7 @@ import { formatMessage } from "../../helpers/i18n"; const styles = (theme) => ({ label: { - color: theme.palette.primary.main, + color: theme.palette.text.primary, }, }); diff --git a/src/pickers/AdDatePicker.js b/src/pickers/AdDatePicker.js index 45e685f8..52f46ce8 100644 --- a/src/pickers/AdDatePicker.js +++ b/src/pickers/AdDatePicker.js @@ -8,7 +8,7 @@ import { formatMessage, toISODate } from "../helpers/i18n"; const styles = (theme) => ({ label: { - color: theme.palette.primary.main, + color: theme.palette.text.primary, }, }); From 28d9fff3ffc02ebb52bff7c424b763ae33f81930 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Sat, 30 Sep 2023 20:32:14 +0530 Subject: [PATCH 004/111] style cahnges --- src/components/generics/Searcher.js | 4 ++-- src/components/generics/Table.js | 4 ++-- src/components/inputs/AutoSuggestion.js | 4 +++- src/components/inputs/Autocomplete.js | 4 +++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index 8aa3b26f..ddd664b5 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -35,7 +35,7 @@ const styles = (theme) => ({ }, paper: theme.paper.body, paperHeader: theme.paper.header, - paperHeaderTitle: theme.paper.title, + paperHeaderTitle: theme.paper.headerTitles, paperHeaderMessage: theme.paper.message, paperHeaderAction: { paddingInline: 5, @@ -430,7 +430,7 @@ class Searcher extends Component { /> )} {!!contributionKey && } - + {errorItems ? ( diff --git a/src/components/generics/Table.js b/src/components/generics/Table.js index 16a6b8f7..0b9c501a 100644 --- a/src/components/generics/Table.js +++ b/src/components/generics/Table.js @@ -203,7 +203,7 @@ class Table extends Component { )} {!!localPreHeaders && localPreHeaders.length > 0 && ( - + {localPreHeaders.map((h, idx) => { if (headerSpans.length > idx && !headerSpans[idx]) return null; @@ -221,7 +221,7 @@ class Table extends Component { )} {!!localHeaders && localHeaders.length > 0 && ( - + {localHeaders.map((h, idx) => { if (headerSpans.length > idx && !headerSpans[idx]) return null; diff --git a/src/components/inputs/AutoSuggestion.js b/src/components/inputs/AutoSuggestion.js index 8fb30beb..1782354a 100644 --- a/src/components/inputs/AutoSuggestion.js +++ b/src/components/inputs/AutoSuggestion.js @@ -16,7 +16,9 @@ const styles = (theme) => ({ }, header: theme.table.title, label: { - color: theme.palette.primary.main, + // color: theme.palette.primary.main, + color: theme.palette.text.primary, + }, textField: { width: "100%", diff --git a/src/components/inputs/Autocomplete.js b/src/components/inputs/Autocomplete.js index 49d6e776..540a0e58 100644 --- a/src/components/inputs/Autocomplete.js +++ b/src/components/inputs/Autocomplete.js @@ -8,7 +8,9 @@ import { useModulesManager } from "../../helpers/modules"; const styles = (theme) => ({ label: { - color: theme.palette.primary.main, + // color: theme.palette.primary.main, + color: theme.palette.text.primary, + }, }); From 26b4429c63d33215ccb65dfd0bcb71441cf36992 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Thu, 5 Oct 2023 13:42:04 +0530 Subject: [PATCH 005/111] add checkbox color --- src/actions.js | 1 + src/components/RoleHeadPanel.js | 2 ++ src/components/generics/Searcher.js | 1 + src/pages/Roles.js | 13 +++++++------ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/actions.js b/src/actions.js index da30c249..05ce5e3d 100644 --- a/src/actions.js +++ b/src/actions.js @@ -229,6 +229,7 @@ export function fetch(config) { ...config, headers: { "Content-Type": "application/json", + // 'ngrok-skip-browser-warning': 'true', ...config.headers, }, }, diff --git a/src/components/RoleHeadPanel.js b/src/components/RoleHeadPanel.js index 67b6b40d..2927db67 100644 --- a/src/components/RoleHeadPanel.js +++ b/src/components/RoleHeadPanel.js @@ -70,6 +70,7 @@ class RoleHeadPanel extends FormPanel { label={formatMessage(intl, "core", "roleManagement.isSystem")} control={ this.updateAttribute("isSystem", event.target.checked)} disabled @@ -82,6 +83,7 @@ class RoleHeadPanel extends FormPanel { label={formatMessage(intl, "core", "roleManagement.isBlocked")} control={ this.updateAttribute("isBlocked", event.target.checked)} disabled={!!isReadOnly} diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index ddd664b5..a6729c2b 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -32,6 +32,7 @@ import Table from "./Table"; const styles = (theme) => ({ root: { width: "100%", + margin:24 }, paper: theme.paper.body, paperHeader: theme.paper.header, diff --git a/src/pages/Roles.js b/src/pages/Roles.js index a8eca93b..370f048a 100644 --- a/src/pages/Roles.js +++ b/src/pages/Roles.js @@ -122,6 +122,7 @@ class RawRoleFilter extends Component { label={formatMessage(intl, "core", "roleManagement.showHistory")} control={ this._onChangeFilter("showHistory", event.target.checked)} /> @@ -189,12 +190,12 @@ class Roles extends Component { language === null ? role.name : language === LANGUAGE_EN - ? role.name - : role.altLanguage === null - ? role.name - : role.altLanguage, - (role) => (role.isSystem !== null ? : ""), - (role) => (role.isBlocked !== null ? : ""), + ? role.name + : role.altLanguage === null + ? role.name + : role.altLanguage, + (role) => (role.isSystem !== null ? : ""), + (role) => (role.isBlocked !== null ? : ""), (role) => (!!role.validityFrom ? formatDateFromISO(modulesManager, intl, role.validityFrom) : ""), (role) => (!!role.validityTo ? formatDateFromISO(modulesManager, intl, role.validityTo) : ""), ]; From 6ca79e816f70a7f56a10ddd73a1749f5c39b6c67 Mon Sep 17 00:00:00 2001 From: olewandowski1 <109145288+olewandowski1@users.noreply.github.com> Date: Wed, 23 Aug 2023 12:24:00 +0200 Subject: [PATCH 006/111] OP-1481: change type of number inputs, hide up/down arrow keys (#148) --- src/components/inputs/NumberInput.js | 2 +- src/components/inputs/TextInput.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/NumberInput.js b/src/components/inputs/NumberInput.js index f687e907..bfa9fa56 100644 --- a/src/components/inputs/NumberInput.js +++ b/src/components/inputs/NumberInput.js @@ -30,7 +30,7 @@ class NumberInput extends Component { }; render() { const { intl, module = "core", min = null, max = null, value, error, displayZero = false, displayNa = false, decimal = false, ...others } = this.props; - let inputProps = { ...this.props.inputProps, type: "tel" }; // We use "tel" instead of "number" to hide up/down arrows + let inputProps = { ...this.props.inputProps, type: "number" }; let err = error; if (min !== null) { diff --git a/src/components/inputs/TextInput.js b/src/components/inputs/TextInput.js index 04d7a687..dbe5f963 100644 --- a/src/components/inputs/TextInput.js +++ b/src/components/inputs/TextInput.js @@ -8,6 +8,20 @@ const styles = (theme) => ({ label: { color: theme.palette.text.primary, }, + // NOTE: This is used to hide the increment/decrement arrows from the number input + numberInput: { + '& input[type=number]': { + '-moz-appearance': 'textfield' + }, + '& input[type=number]::-webkit-outer-spin-button': { + '-webkit-appearance': 'none', + margin: 0 + }, + '& input[type=number]::-webkit-inner-spin-button': { + '-webkit-appearance': 'none', + margin: 0 + } + }, }); class TextInput extends Component { @@ -62,6 +76,7 @@ class TextInput extends Component { return ( Date: Sun, 22 Oct 2023 18:57:00 +0530 Subject: [PATCH 007/111] hide version and help icon --- src/components/RequireAuth.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index c5dfb6b5..306e7756 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -195,7 +195,7 @@ const RequireAuth = (props) => { - {modulesManager.getOpenIMISVersion()} + {/* {modulesManager.getOpenIMISVersion()} */} @@ -210,7 +210,7 @@ const RequireAuth = (props) => {
- + {/* */} {isOpen && ( From c87024c7aed0324058a4f12839017cfcac14d9be Mon Sep 17 00:00:00 2001 From: Rishav Johari <101561606+RishavWtt@users.noreply.github.com> Date: Sun, 22 Oct 2023 18:58:57 +0530 Subject: [PATCH 008/111] translation --- src/translations/en.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/translations/en.json b/src/translations/en.json index 36b4f299..b7981c66 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -37,15 +37,15 @@ "core.Autocomplete.openText": "Open", "core.Autocomplete.closeText": "Close", "core.Autocomplete.placeholder": "Search...", - "core.LoginPage.username.label": "Username", - "core.LoginPage.password.label": "Password", + "core.LoginPage.username.label": "Nom d'utilisateur", + "core.LoginPage.password.label": "Mot de passe", "core.LoginPage.loginBtn": "Log In", "core.LoginPage.authError": "The password or the username you've entered is incorrect.", "core.LoginPage.pageTitle": "Log In", "core.LoginPage.forgotPassword": "Forgot Password ?", "core.ForgotPasswordPage.pageTitle": "Forgot Password ?", "core.ForgotPasswordPage.submitBtn": "Submit", - "core.ForgotPasswordPage.username.label": "Username", + "core.ForgotPasswordPage.username.label": "Nom d'utilisateur", "core.ForgotPasswordPage.recoverTitle": "Recover your account", "core.ForgotPasswordPage.explanationMessage": "Enter your username to be able to recover your account. En e-mail with the instructions will be sent to your e-mail address.", "core.ForgotPasswordPage.contactAdministrator": "If you do not receive an e-mail, please check with your administrator.", From e62f430d5e4d6f9a4baa33d03f900f61aa934fa7 Mon Sep 17 00:00:00 2001 From: Rishav Johari <101561606+RishavWtt@users.noreply.github.com> Date: Mon, 23 Oct 2023 12:29:10 +0530 Subject: [PATCH 009/111] french locallization --- src/translations/en.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/translations/en.json b/src/translations/en.json index b7981c66..5a29ffba 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -39,16 +39,13 @@ "core.Autocomplete.placeholder": "Search...", "core.LoginPage.username.label": "Nom d'utilisateur", "core.LoginPage.password.label": "Mot de passe", - "core.LoginPage.loginBtn": "Log In", + "core.LoginPage.loginBtn": "Connexion", "core.LoginPage.authError": "The password or the username you've entered is incorrect.", "core.LoginPage.pageTitle": "Log In", - "core.LoginPage.forgotPassword": "Forgot Password ?", - "core.ForgotPasswordPage.pageTitle": "Forgot Password ?", + "core.LoginPage.forgotPassword": "Mot de passe oublié ?", + "core.ForgotPasswordPage.pageTitle": "Mot de passe oublié ?", "core.ForgotPasswordPage.submitBtn": "Submit", "core.ForgotPasswordPage.username.label": "Nom d'utilisateur", - "core.ForgotPasswordPage.recoverTitle": "Recover your account", - "core.ForgotPasswordPage.explanationMessage": "Enter your username to be able to recover your account. En e-mail with the instructions will be sent to your e-mail address.", - "core.ForgotPasswordPage.contactAdministrator": "If you do not receive an e-mail, please check with your administrator.", "core.ForgotPasswordPage.done": "Done ! Check your inbox and click on the verification link to reset your password.", "core.SetPasswordPage.pageTitle": "Set a new Password", "core.SetPasswordPage.username.label": "Username", @@ -61,5 +58,8 @@ "core.exportSearchResult.tooltip": "Export result", "LanguagePicker.label": "Language", "core.Language.null": "", - "core.NumberInput.notApplicable": "N/A" + "core.NumberInput.notApplicable": "N/A", + "core.ForgotPasswordPage.recoverTitle": "Récupérer votre compte", + "core.ForgotPasswordPage.explanationMessage": "Saisissez votre nom d'utilisateur pour pouvoir récupérer votre compte. Un e-mail contenant les instructions sera envoyé à votre adresse e-mail.", + "core.ForgotPasswordPage.contactAdministrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur." } From 4c69b1dfabe152c1b819b39d06d16a0b848b75d5 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Thu, 26 Oct 2023 15:25:52 +0530 Subject: [PATCH 010/111] loginpage --- src/pages/LoginPage.js | 171 ++++++++++++++++++++++++++------------- src/translations/en.json | 1 + 2 files changed, 117 insertions(+), 55 deletions(-) diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js index 6979e888..fe570e4e 100644 --- a/src/pages/LoginPage.js +++ b/src/pages/LoginPage.js @@ -1,7 +1,7 @@ import React, { useMemo, useState, useEffect } from "react"; import { useHistory } from "../helpers/history"; import { makeStyles } from "@material-ui/styles"; -import { Button, Box, Grid, Paper, LinearProgress } from "@material-ui/core"; +import { Button, Box, Grid, Paper, LinearProgress, Checkbox, FormControlLabel } from "@material-ui/core"; import TextInput from "../components/inputs/TextInput"; import { useTranslations } from "../helpers/i18n"; import { useModulesManager } from "../helpers/modules"; @@ -21,7 +21,7 @@ const useStyles = makeStyles((theme) => ({ justifyContent: "center", alignItems: "center", }, - paper: theme.paper.paper, + paper: theme.paper.loginPaper, logo: { maxHeight: 100, width: 100, @@ -62,7 +62,7 @@ const LoginPage = ({ logo }) => { e.preventDefault(); history.push("/forgot_password"); }; - + const MyBackgroundImage = 'openimis-fe-core_js/src/pages/backgroundNewImage.png'; return ( <> {isAuthenticating && ( @@ -70,63 +70,124 @@ const LoginPage = ({ logo }) => { )} -
- - -
- - - - - +
+
+
+ + + + + + + + + {/* {formatMessage("core.displayAppName")} - - - - setCredentials({ ...credentials, username })} - /> - - - setCredentials({ ...credentials, password })} - /> - - {hasError && ( + */} + + {/* + "Insurance Management System" + */} +
CAMUIMS
- {formatMessage("authError")} + setCredentials({ ...credentials, username })} + /> - )} - - - - - - + + setCredentials({ ...credentials, password })} + /> + + {hasError && ( + + {formatMessage("authError")} + + )} + + + + } + /> + +
+ {formatMessage("forgotPassword")} +
+ +
+ + + +
- - - -
+ + + +
+
); }; diff --git a/src/translations/en.json b/src/translations/en.json index 5a29ffba..0cc20850 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -39,6 +39,7 @@ "core.Autocomplete.placeholder": "Search...", "core.LoginPage.username.label": "Nom d'utilisateur", "core.LoginPage.password.label": "Mot de passe", + "core.LoginPage.rememberMe": "Remember Me", "core.LoginPage.loginBtn": "Connexion", "core.LoginPage.authError": "The password or the username you've entered is incorrect.", "core.LoginPage.pageTitle": "Log In", From bb7966605b0cff69e7329e1178544ff2d82d53e2 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Fri, 27 Oct 2023 02:21:54 +0530 Subject: [PATCH 011/111] forgot password screen ui change --- src/pages/ForgotPasswordPage.js | 96 ++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/src/pages/ForgotPasswordPage.js b/src/pages/ForgotPasswordPage.js index f07be3ae..e44206b1 100644 --- a/src/pages/ForgotPasswordPage.js +++ b/src/pages/ForgotPasswordPage.js @@ -7,18 +7,22 @@ import { useTranslations } from "../helpers/i18n"; import { useModulesManager } from "../helpers/modules"; import Helmet from "../helpers/Helmet"; import { useGraphqlMutation } from "../helpers/hooks"; +import ArrowBackIcon from '@material-ui/icons/ArrowBack'; +import { useHistory } from 'react-router-dom'; const useStyles = makeStyles((theme) => ({ container: { position: "absolute", - top: "30%", + top: 0, + bottom: 0, left: 0, right: 0, margin: "auto", display: "flex", justifyContent: "center", + alignItems: "center", }, - paper: theme.paper.paper, + paper: theme.paper.loginPaper, logo: { maxHeight: 100, }, @@ -30,6 +34,7 @@ const ForgotPasswordPage = (props) => { const { formatMessage } = useTranslations("core.ForgotPasswordPage", modulesManager); const [username, setUsername] = useState(); const [isDone, setDone] = useState(false); + const history = useHistory(); const { isLoading, mutate } = useGraphqlMutation( ` mutation resetPassword($input: ResetPasswordMutationInput!) { @@ -51,8 +56,24 @@ const ForgotPasswordPage = (props) => { await setDone(true); }; + const handleBackToLogin = () => { + // Use the history object to navigate to the LoginPage route + history.push('/login'); + }; + return ( <> +
+
@@ -60,15 +81,24 @@ const ForgotPasswordPage = (props) => { {!isDone && ( - -

{formatMessage("recoverTitle")}

+ + - +
{formatMessage("recoverTitle")}
+ {/* +

{formatMessage("recoverTitle")}

+
*/} + {/* {formatMessage("explanationMessage")} {formatMessage("contactAdministrator")} - +
*/} { {formatMessage("submitBtn")} + + +
)} - {isDone &&

{formatMessage("done")}

} + {isDone && + + //

{formatMessage("done")}

+ + + + + + +
An e-mail with Verification link has been sent to your e-mail address.
+
If you do not receive an e-mail, please check with your administrator.
+ + + +
+ }
+
+ ); }; From 52096612ee539909f9d32694a73de805eced5354 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Fri, 27 Oct 2023 12:43:18 +0530 Subject: [PATCH 012/111] Changes for insuree status --- src/components/generics/Form.js | 78 ++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index ca5e96a0..34b87aa2 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -10,12 +10,35 @@ import Contributions from "./Contributions"; import withHistory from "../../helpers/history"; import { withTooltip, formatMessage } from "../../helpers/i18n"; import _ from "lodash"; +import CheckIcon from "@material-ui/icons/Check"; +import CloseIcon from "@material-ui/icons/Close"; +import SendIcon from "@material-ui/icons/Send"; const styles = (theme) => ({ paper: theme.paper.paper, paperHeader: theme.paper.header, paperHeaderAction: theme.paper.action, fab: theme.fab, + fabAbove: { + position: "fixed", + bottom: 20, + right: 8, + zIndex: 2000, + marginBottom: "70px", + }, + fabMargin: { + marginBottom: "140px", + }, + customFab: { + background: "#fff", + border: "2px solid #FF841C", // Your desired border color + color: "#FF841C", // Your desired text/icon color + }, + customFabReject: { + background: "#fff", + border: "2px solid #FF0000", // Your desired border color + color: "#FF0000", // Your desired text/icon color + }, }); class Form extends Component { @@ -69,6 +92,10 @@ class Form extends Component { headPanelContributionsKey, Panels, contributedPanelsKey = null, + hasReject, + allApproved, + approveorreject, + handleDialogOpen, ...others } = this.props; return ( @@ -155,8 +182,57 @@ class Form extends Component { /> )} + {title == "Insuree.title" && this.props.edited?.biometricsStatus ? ( + hasReject ? ( + <> + {withTooltip( +
+ handleDialogOpen("rework", this.props.edited)}> + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + + {withTooltip( +
+ handleDialogOpen("reject", this.props.edited)} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + + ) : allApproved ? ( + <> + {withTooltip( +
+ handleDialogOpen("reject", this.props.edited)} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + {withTooltip( +
+ approveorreject({ ...this.props.edited, status: "APPROVED" })}> + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + + ) : null + ) : null} {!this.state.dirty && - !!add && !save && + !!add && + !save && withTooltip(
From ba590645d491b7456c5bf347eb8a073bea077a05 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Fri, 27 Oct 2023 16:04:55 +0530 Subject: [PATCH 013/111] background image changes --- src/pages/LoginPage.js | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js index fe570e4e..d8575c6d 100644 --- a/src/pages/LoginPage.js +++ b/src/pages/LoginPage.js @@ -30,7 +30,7 @@ const useStyles = makeStyles((theme) => ({ const LOGIN_PAGE_CONTRIBUTION_KEY = "core.LoginPage"; -const LoginPage = ({ logo }) => { +const LoginPage = ({ logo, backgroundImage }) => { const classes = useStyles(); const history = useHistory(); const modulesManager = useModulesManager(); @@ -39,10 +39,42 @@ const LoginPage = ({ logo }) => { const [hasError, setError] = useState(false); const auth = useAuthentication(); const [isAuthenticating, setAuthenticating] = useState(false); + const initialState = localStorage.getItem('rememberMe') === 'true'; + const [rememberMe, setRememberMe] = useState(initialState); + + const handleRememberMeChange = (event) => { + const isChecked = event.target.checked; + setRememberMe(isChecked); + + console.log('Remember Me is checked:', isChecked); + + if (!isChecked) { + // If "Remember Me" is unchecked, clear the saved credentials. + localStorage.removeItem('rememberedUsername'); + localStorage.removeItem('rememberedPassword'); + } else { + // If "Remember Me" is checked, save the username and password. + localStorage.setItem('rememberedUsername', credentials.username); + localStorage.setItem('rememberedPassword', credentials.password); + + console.log('Saved username and password:', credentials.username, credentials.password); + } + + localStorage.setItem('rememberMe', isChecked.toString()); + }; useEffect(() => { if (auth.isAuthenticated) { history.push("/"); + } else { + // If "Remember Me" is checked, retrieve and set the saved credentials. + if (rememberMe) { + const savedUsername = localStorage.getItem('rememberedUsername'); + const savedPassword = localStorage.getItem('rememberedPassword'); + if (savedUsername && savedPassword) { + setCredentials({ username: savedUsername, password: savedPassword }); + } + } } }, []); @@ -62,7 +94,6 @@ const LoginPage = ({ logo }) => { e.preventDefault(); history.push("/forgot_password"); }; - const MyBackgroundImage = 'openimis-fe-core_js/src/pages/backgroundNewImage.png'; return ( <> {isAuthenticating && ( @@ -76,7 +107,7 @@ const LoginPage = ({ logo }) => { }}>
{ } /> @@ -189,7 +222,6 @@ const LoginPage = ({ logo }) => {
- ); -}; + )} export default LoginPage; From 9dedd52741fb5683d66c7e98143940dc24971397 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Fri, 27 Oct 2023 16:26:44 +0530 Subject: [PATCH 014/111] background changes --- src/pages/ForgotPasswordPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ForgotPasswordPage.js b/src/pages/ForgotPasswordPage.js index e44206b1..4d0b4198 100644 --- a/src/pages/ForgotPasswordPage.js +++ b/src/pages/ForgotPasswordPage.js @@ -69,7 +69,7 @@ const ForgotPasswordPage = (props) => { }}>
Date: Sat, 28 Oct 2023 17:03:06 +0530 Subject: [PATCH 015/111] commit form --- src/components/generics/Form.js | 38 ++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 34b87aa2..66162e0a 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -4,6 +4,8 @@ import { injectIntl } from "react-intl"; import { Fab, Grid, Paper, IconButton, Typography, Divider, Tooltip } from "@material-ui/core"; import AddIcon from "@material-ui/icons/Add"; import SaveIcon from "@material-ui/icons/SaveAlt"; +import EmailIcon from '@material-ui/icons/Email'; +import PrintIcon from '@material-ui/icons/Print'; import ChevronLeftIcon from "@material-ui/icons/ChevronLeft"; import FormattedMessage from "./FormattedMessage"; import Contributions from "./Contributions"; @@ -92,12 +94,16 @@ class Form extends Component { headPanelContributionsKey, Panels, contributedPanelsKey = null, + emailButton, + print, + email, hasReject, allApproved, approveorreject, handleDialogOpen, ...others } = this.props; + console.log(this.props.edited_id, "editedsdf") return (
@@ -231,8 +237,7 @@ class Form extends Component { ) : null ) : null} {!this.state.dirty && - !!add && - !save && + !!add && !save && withTooltip(
@@ -253,8 +258,35 @@ class Form extends Component {
, - saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), )} + {(!!this.props.email) ? + withTooltip( +
+ this.save(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} + {(!!this.props.email) ? + withTooltip( +
+ emailButton(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} {!this.state.dirty && !!fab && withTooltip( From 866322a508ea5aaad91e1db4737c48699df45375 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Sat, 28 Oct 2023 21:53:30 +0530 Subject: [PATCH 016/111] status changedbtton access --- src/components/generics/Form.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 34b87aa2..99135e5f 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -183,7 +183,9 @@ class Form extends Component { )} {title == "Insuree.title" && this.props.edited?.biometricsStatus ? ( - hasReject ? ( + (hasReject && (this.props?.edited?.status !== "REJECTED" || this.props?.edited?.status !== "REWORK")) || + !this.props?.edited?.biometricsIsMaster ? ( + // && this.props?.edited?.biometricsIsMaster == false <> {withTooltip(
@@ -206,7 +208,8 @@ class Form extends Component { addTooltip || formatMessage(this.props.intl, module, "addTooltip"), )} - ) : allApproved ? ( + ) : allApproved && this.props.edited.biometricsIsMaster && this.props?.edited?.status !== "APPROVED" ? ( + // && this.props?.edited?.biometricsIsMaster <> {withTooltip(
From e3f302bd94ac02e501080fd2fb432239e9b44caa Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Sun, 29 Oct 2023 12:14:41 +0530 Subject: [PATCH 017/111] change logic of buttons --- src/components/generics/Form.js | 65 ++++++++++++++++----------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index d705c701..ec0b89d0 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -4,8 +4,8 @@ import { injectIntl } from "react-intl"; import { Fab, Grid, Paper, IconButton, Typography, Divider, Tooltip } from "@material-ui/core"; import AddIcon from "@material-ui/icons/Add"; import SaveIcon from "@material-ui/icons/SaveAlt"; -import EmailIcon from '@material-ui/icons/Email'; -import PrintIcon from '@material-ui/icons/Print'; +import EmailIcon from "@material-ui/icons/Email"; +import PrintIcon from "@material-ui/icons/Print"; import ChevronLeftIcon from "@material-ui/icons/ChevronLeft"; import FormattedMessage from "./FormattedMessage"; import Contributions from "./Contributions"; @@ -103,7 +103,6 @@ class Form extends Component { handleDialogOpen, ...others } = this.props; - console.log(this.props.edited_id, "editedsdf") return (
@@ -189,9 +188,7 @@ class Form extends Component { )}
{title == "Insuree.title" && this.props.edited?.biometricsStatus ? ( - (hasReject && (this.props?.edited?.status !== "REJECTED" || this.props?.edited?.status !== "REWORK")) || - !this.props?.edited?.biometricsIsMaster ? ( - // && this.props?.edited?.biometricsIsMaster == false + hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip(
@@ -240,7 +237,8 @@ class Form extends Component { ) : null ) : null} {!this.state.dirty && - !!add && !save && + !!add && + !save && withTooltip(
@@ -263,32 +261,33 @@ class Form extends Component {
, // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), )} - {(!!this.props.email) ? - withTooltip( -
- this.save(this.props.edited)} - > - - -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) : ""} - {(!!this.props.email) ? - withTooltip( -
- emailButton(this.props.edited)} - > - - -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) + {!!this.props.email + ? withTooltip( +
+ this.save(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} + {!!this.props.email + ? withTooltip( +
+ emailButton(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && From 294eeb391c82423f21462db4ab176d4a6e3fcf31 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Tue, 31 Oct 2023 16:37:50 +0530 Subject: [PATCH 018/111] login screen, forgotpassword ui changes --- src/pages/ForgotPasswordPage.js | 12 ++++++------ src/pages/LoginPage.js | 4 ++-- src/translations/en.json | 7 +++++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/pages/ForgotPasswordPage.js b/src/pages/ForgotPasswordPage.js index 4d0b4198..7e41282e 100644 --- a/src/pages/ForgotPasswordPage.js +++ b/src/pages/ForgotPasswordPage.js @@ -78,7 +78,7 @@ const ForgotPasswordPage = (props) => {
- + {!isDone && ( @@ -130,7 +130,7 @@ const ForgotPasswordPage = (props) => { }} onClick={handleBackToLogin} > - Back to Login + {formatMessage("backButton")} @@ -147,16 +147,16 @@ const ForgotPasswordPage = (props) => {
An e-mail with Verification link has been sent to your e-mail address.
+ }}>{formatMessage('done.Verification')}
If you do not receive an e-mail, please check with your administrator.
+ }}>{formatMessage('done.Administrator')}
diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js index d8575c6d..5f8adf65 100644 --- a/src/pages/LoginPage.js +++ b/src/pages/LoginPage.js @@ -117,7 +117,7 @@ const LoginPage = ({ logo, backgroundImage }) => { - + @@ -156,7 +156,7 @@ const LoginPage = ({ logo, backgroundImage }) => { {hasError && ( - {formatMessage("authError")} + {formatMessage("authError")} )} diff --git a/src/translations/en.json b/src/translations/en.json index 0cc20850..11d6b508 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -39,15 +39,18 @@ "core.Autocomplete.placeholder": "Search...", "core.LoginPage.username.label": "Nom d'utilisateur", "core.LoginPage.password.label": "Mot de passe", - "core.LoginPage.rememberMe": "Remember Me", + "core.LoginPage.rememberMe": "Souvenez-vous de moi", "core.LoginPage.loginBtn": "Connexion", "core.LoginPage.authError": "The password or the username you've entered is incorrect.", "core.LoginPage.pageTitle": "Log In", "core.LoginPage.forgotPassword": "Mot de passe oublié ?", "core.ForgotPasswordPage.pageTitle": "Mot de passe oublié ?", - "core.ForgotPasswordPage.submitBtn": "Submit", + "core.ForgotPasswordPage.submitBtn": "CONNEXION", "core.ForgotPasswordPage.username.label": "Nom d'utilisateur", "core.ForgotPasswordPage.done": "Done ! Check your inbox and click on the verification link to reset your password.", + "core.ForgotPasswordPage.done.Verification": "Un e-mail avec un lien de vérification a été envoyé à votre adresse e-mail", + "core.ForgotPasswordPage.done.Administrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur.", + "core.ForgotPasswordPage.backButton": "Retour à la connexion", "core.SetPasswordPage.pageTitle": "Set a new Password", "core.SetPasswordPage.username.label": "Username", "core.SetPasswordPage.password.label": "Password", From 944138d8ddbd266a0a222eb0ed8ae05e0faeda38 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Wed, 1 Nov 2023 12:18:58 +0530 Subject: [PATCH 019/111] tab label change --- src/components/App.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/App.js b/src/components/App.js index cc541ca4..34b98800 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -95,7 +95,7 @@ const App = (props) => { return ( <> - + From e927168cd21f3844013dc8c569c38b28a9b4e802 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Thu, 2 Nov 2023 16:41:16 +0530 Subject: [PATCH 020/111] LoginPage Title, save button icon --- src/components/generics/Form.js | 5 +++-- src/pages/LoginPage.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index ec0b89d0..962dfb75 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -3,7 +3,7 @@ import { withTheme, withStyles } from "@material-ui/core/styles"; import { injectIntl } from "react-intl"; import { Fab, Grid, Paper, IconButton, Typography, Divider, Tooltip } from "@material-ui/core"; import AddIcon from "@material-ui/icons/Add"; -import SaveIcon from "@material-ui/icons/SaveAlt"; +import SaveIcon from "@material-ui/icons/Save"; import EmailIcon from "@material-ui/icons/Email"; import PrintIcon from "@material-ui/icons/Print"; import ChevronLeftIcon from "@material-ui/icons/ChevronLeft"; @@ -101,6 +101,7 @@ class Form extends Component { allApproved, approveorreject, handleDialogOpen, + printButton, ...others } = this.props; return ( @@ -267,7 +268,7 @@ class Form extends Component { this.save(this.props.edited)} + onClick={(e) =>printButton(this.props.edited)} > diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js index 5f8adf65..efe0c563 100644 --- a/src/pages/LoginPage.js +++ b/src/pages/LoginPage.js @@ -133,7 +133,7 @@ const LoginPage = ({ logo, backgroundImage }) => { font: 'normal normal bold 24px/42px Roboto', color: '#333333', marginTop: "10px" - }}>CAMUIMS
+ }}>CAMU IMS
Date: Fri, 3 Nov 2023 12:00:49 +0530 Subject: [PATCH 021/111] date picker localisation changes --- src/actions.js | 30 ++++++++++++++++++------- src/pickers/AdDatePicker.js | 44 ++++++++++++++++++++++++------------- src/translations/en.json | 5 ++++- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/src/actions.js b/src/actions.js index 05ce5e3d..5560fdbf 100644 --- a/src/actions.js +++ b/src/actions.js @@ -28,8 +28,8 @@ const LANGUAGE_FULL_PROJECTION = () => ["name", "code", "sortOrder"]; const MODULEPERMISSION_FULL_PROJECTION = () => ["modulePermsList{moduleName, permissions{permsName, permsValue}}"]; function getApiUrl() { - let _baseApiUrl = process.env.REACT_APP_API_URL ?? '/api'; - if (_baseApiUrl.indexOf('/') !== 0) { + let _baseApiUrl = process.env.REACT_APP_API_URL ?? "/api"; + if (_baseApiUrl.indexOf("/") !== 0) { _baseApiUrl = `/${_baseApiUrl}`; } return _baseApiUrl; @@ -187,7 +187,14 @@ export function waitForMutation(clientMutationId, additionalRequest = "") { }; } -export function graphqlMutation(mutation, variables, type = "CORE_TRIGGER_MUTATION", params = {}, wait = true, additionalRequest = "") { +export function graphqlMutation( + mutation, + variables, + type = "CORE_TRIGGER_MUTATION", + params = {}, + wait = true, + additionalRequest = "", +) { let clientMutationId; if (variables?.input) { clientMutationId = uuid.uuid(); @@ -206,7 +213,13 @@ export function graphqlMutation(mutation, variables, type = "CORE_TRIGGER_MUTATI }; } -export function graphqlMutationLegacy(payload, type = "CORE_TRIGGER_MUTATION", params = {}, wait = true, additionalRequest = "") { +export function graphqlMutationLegacy( + payload, + type = "CORE_TRIGGER_MUTATION", + params = {}, + wait = true, + additionalRequest = "", +) { if (wait && !params.clientMutationId) { console.error("graphqlMutationLegacy cannot wait with a specified clientMutationId"); } @@ -229,7 +242,6 @@ export function fetch(config) { ...config, headers: { "Content-Type": "application/json", - // 'ngrok-skip-browser-warning': 'true', ...config.headers, }, }, @@ -262,6 +274,7 @@ export function login(credentials) { await dispatch(refreshAuthToken()); } const action = await dispatch(loadUser()); + localStorage.setItem("userLanguage", action.payload.i_user.language); return action.type !== "CORE_AUTH_ERR"; }; } @@ -306,6 +319,7 @@ export function logout() { } `; await dispatch(graphqlMutation(mutation, {})); + localStorage.removeItem("userLanguage") return dispatch({ type: "CORE_AUTH_LOGOUT" }); }; } @@ -466,12 +480,12 @@ export function roleNameSetValid() { export function saveCurrentPaginationPage(page, afterCursor, beforeCursor, module) { return (dispatch) => { - dispatch({ type: "CORE_PAGINATION_PAGE", payload: { page, afterCursor, beforeCursor, module} }); + dispatch({ type: "CORE_PAGINATION_PAGE", payload: { page, afterCursor, beforeCursor, module } }); }; } export function clearCurrentPaginationPage() { return (dispatch) => { - dispatch({ type: "CORE_PAGINATION_PAGE_CLEAR" }) - } + dispatch({ type: "CORE_PAGINATION_PAGE_CLEAR" }); + }; } diff --git a/src/pickers/AdDatePicker.js b/src/pickers/AdDatePicker.js index 52f46ce8..bef8f186 100644 --- a/src/pickers/AdDatePicker.js +++ b/src/pickers/AdDatePicker.js @@ -5,6 +5,9 @@ import { injectIntl } from "react-intl"; import { FormControl } from "@material-ui/core"; import { DatePicker as MUIDatePicker } from "@material-ui/pickers"; import { formatMessage, toISODate } from "../helpers/i18n"; +import MomentUtils from "@date-io/moment"; +import { MuiPickersUtilsProvider } from "@material-ui/pickers"; +import "moment/locale/fr"; const styles = (theme) => ({ label: { @@ -49,23 +52,34 @@ class AdDatePicker extends Component { ...otherProps } = this.props; + let userlang = localStorage.getItem("userLanguage"); + let locale = userlang === "fr" ? "fr" : "en"; + moment.locale(locale); return ( - + + + ); } diff --git a/src/translations/en.json b/src/translations/en.json index 0cc20850..fa864f29 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -62,5 +62,8 @@ "core.NumberInput.notApplicable": "N/A", "core.ForgotPasswordPage.recoverTitle": "Récupérer votre compte", "core.ForgotPasswordPage.explanationMessage": "Saisissez votre nom d'utilisateur pour pouvoir récupérer votre compte. Un e-mail contenant les instructions sera envoyé à votre adresse e-mail.", - "core.ForgotPasswordPage.contactAdministrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur." + "core.ForgotPasswordPage.contactAdministrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur.", + "core.datePicker.ok":"OK", + "core.datePicker.cancel":"CANCEL", + "core.datePicker.clear":"CLEAR" } From c44e2c473a87c2c31e331b5a66334951f6b6978b Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Fri, 3 Nov 2023 13:09:02 +0530 Subject: [PATCH 022/111] changes in local storage --- src/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/actions.js b/src/actions.js index 5560fdbf..5ddb09b5 100644 --- a/src/actions.js +++ b/src/actions.js @@ -274,7 +274,7 @@ export function login(credentials) { await dispatch(refreshAuthToken()); } const action = await dispatch(loadUser()); - localStorage.setItem("userLanguage", action.payload.i_user.language); + localStorage.setItem("userLanguage", action?.payload?.i_user?.language); return action.type !== "CORE_AUTH_ERR"; }; } @@ -319,7 +319,7 @@ export function logout() { } `; await dispatch(graphqlMutation(mutation, {})); - localStorage.removeItem("userLanguage") + localStorage.removeItem("userLanguage"); return dispatch({ type: "CORE_AUTH_LOGOUT" }); }; } From c24b98ea6b1a9a634914326fb513a02f17b631aa Mon Sep 17 00:00:00 2001 From: Rishav Johari <101561606+RishavWtt@users.noreply.github.com> Date: Mon, 6 Nov 2023 19:50:50 +0530 Subject: [PATCH 023/111] theme changes --- src/components/generics/Form.js | 44 +++++++++++++------------ src/components/inputs/AutoSuggestion.js | 22 +++++++++++-- src/components/inputs/TextInput.js | 25 +++++++++----- src/pickers/AdDatePicker.js | 13 ++++++-- 4 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 962dfb75..11439fac 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -104,6 +104,7 @@ class Form extends Component { printButton, ...others } = this.props; + // console.log(this.props.edited, "editedsdf") return ( @@ -262,33 +263,34 @@ class Form extends Component {
, // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), )} - {!!this.props.email - ? withTooltip( -
+ {(!!this.props.email && this.props.edited.email != null) ? + withTooltip( +
+
printButton(this.props.edited)} + onClick={(e) => printButton(this.props.edited)} > -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) - : ""} - {!!this.props.email - ? withTooltip( -
- emailButton(this.props.edited)} - > - - -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
+ // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} + {(!!this.props.email && this.props.edited.email != null) ? + withTooltip( +
+ emailButton(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && diff --git a/src/components/inputs/AutoSuggestion.js b/src/components/inputs/AutoSuggestion.js index 1782354a..c9b15769 100644 --- a/src/components/inputs/AutoSuggestion.js +++ b/src/components/inputs/AutoSuggestion.js @@ -252,7 +252,7 @@ class AutoSuggestion extends Component { }; renderSelect = () => { - const { module, withNull, nullLabel, label, required = false, getSuggestionValue } = this.props; + const { module, withNull, nullLabel, label, required = false, getSuggestionValue, readOnly } = this.props; const { suggestions, selected } = this.state; var options = suggestions.map((r) => ({ value: r, label: getSuggestionValue(r) })); if (withNull) { @@ -271,7 +271,7 @@ class AutoSuggestion extends Component { }; renderAutoselect = () => { - const { classes, label, disabled = false, required = false, placeholder, getSuggestionValue } = this.props; + const { classes, label, disabled = false, required = false, placeholder, getSuggestionValue, readOnly } = this.props; const { suggestions, value } = this.state; const inputProps = { className: classes.suggestionInputField, @@ -282,6 +282,7 @@ class AutoSuggestion extends Component { disabled, onChange: this._onAutoselectChange, required, + }; return ( ); }; @@ -309,7 +315,17 @@ class AutoSuggestion extends Component { const { classes, label, readOnly = false, selectThreshold = null } = this.props; const { value, suggestions } = this.state; if (!!readOnly) { - return ; + return ; } if ( !value && diff --git a/src/components/inputs/TextInput.js b/src/components/inputs/TextInput.js index dbe5f963..cc8591e9 100644 --- a/src/components/inputs/TextInput.js +++ b/src/components/inputs/TextInput.js @@ -11,15 +11,15 @@ const styles = (theme) => ({ // NOTE: This is used to hide the increment/decrement arrows from the number input numberInput: { '& input[type=number]': { - '-moz-appearance': 'textfield' + '-moz-appearance': 'textfield' }, '& input[type=number]::-webkit-outer-spin-button': { - '-webkit-appearance': 'none', - margin: 0 + '-webkit-appearance': 'none', + margin: 0 }, '& input[type=number]::-webkit-inner-spin-button': { - '-webkit-appearance': 'none', - margin: 0 + '-webkit-appearance': 'none', + margin: 0 } }, }); @@ -49,7 +49,7 @@ class TextInput extends Component { } } _onChange = (e) => { - let {value} = e.target; + let { value } = e.target; if (this.props.formatInput) { value = this.props.formatInput(value); } @@ -73,17 +73,26 @@ class TextInput extends Component { type, ...others } = this.props; + const inputClass = readOnly ? classes.disabledInput : ''; return ( Date: Tue, 7 Nov 2023 17:04:48 +0530 Subject: [PATCH 024/111] localization --- src/translations/en.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/translations/en.json b/src/translations/en.json index b2749244..f427c4ea 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -39,17 +39,17 @@ "core.Autocomplete.placeholder": "Search...", "core.LoginPage.username.label": "Nom d'utilisateur", "core.LoginPage.password.label": "Mot de passe", - "core.LoginPage.rememberMe": "Souvenez-vous de moi", + "core.LoginPage.rememberMe": "Se souvenir de moi", "core.LoginPage.loginBtn": "Connexion", - "core.LoginPage.authError": "The password or the username you've entered is incorrect.", + "core.LoginPage.authError": "Le mot de passe ou le nom d'utilisateur que vous avez saisi est incorrect", "core.LoginPage.pageTitle": "Log In", "core.LoginPage.forgotPassword": "Mot de passe oublié ?", "core.ForgotPasswordPage.pageTitle": "Mot de passe oublié ?", - "core.ForgotPasswordPage.submitBtn": "CONNEXION", + "core.ForgotPasswordPage.submitBtn": "Soumettre", "core.ForgotPasswordPage.username.label": "Nom d'utilisateur", "core.ForgotPasswordPage.done": "Done ! Check your inbox and click on the verification link to reset your password.", - "core.ForgotPasswordPage.done.Verification": "Un e-mail avec un lien de vérification a été envoyé à votre adresse e-mail", - "core.ForgotPasswordPage.done.Administrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur.", + "core.ForgotPasswordPage.done.Verification": "Un e-mail contenant le lien de vérification a été envoyé à votre adresse e-mail", + "core.ForgotPasswordPage.done.Administrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur", "core.ForgotPasswordPage.backButton": "Retour à la connexion", "core.SetPasswordPage.pageTitle": "Set a new Password", "core.SetPasswordPage.username.label": "Username", From 2e928e9552b7ea116d85c000636ebd76367cdc2c Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Thu, 9 Nov 2023 14:57:14 +0530 Subject: [PATCH 025/111] JournalDrawer Scroll Bar changes --- src/components/JournalDrawer.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/JournalDrawer.js b/src/components/JournalDrawer.js index 25787cdb..2f7c9586 100644 --- a/src/components/JournalDrawer.js +++ b/src/components/JournalDrawer.js @@ -92,6 +92,14 @@ const styles = (theme) => ({ width: "100%", margin: theme.spacing(1), }, + listContainer: { + height: "40vh", + overflowX: "scroll", + overflowY: "scroll", + scrollbarWidth: "none", + "&::-ms-overflow-style": "none", + "&::-webkit-scrollbar": {width: 0, height: 0} + }, }); class Messages extends Component { @@ -323,12 +331,12 @@ class JournalDrawer extends Component { - + {this.state.displayedMutations.map((m, idx) => ( {m.status == 0 && ( - + )} @@ -364,6 +372,7 @@ class JournalDrawer extends Component { )} + {!!m.clientMutationDetails && ( Date: Thu, 9 Nov 2023 18:30:53 +0530 Subject: [PATCH 026/111] disble email and print button when popup appears --- src/components/generics/Form.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 11439fac..51353737 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -102,6 +102,8 @@ class Form extends Component { approveorreject, handleDialogOpen, printButton, + paymentPrint, + success, ...others } = this.props; // console.log(this.props.edited, "editedsdf") @@ -263,14 +265,31 @@ class Form extends Component {
, // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), )} - {(!!this.props.email && this.props.edited.email != null) ? + {(!!this.props.paymentPrint) ? + withTooltip( +
+
+ printButton(this.props.edited)} + > + + +
+
+ // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} + {(!!this.props.email && this.props.edited.email != "") ? withTooltip(
printButton(this.props.edited)} + > @@ -278,11 +297,13 @@ class Form extends Component {
// saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), ) : ""} - {(!!this.props.email && this.props.edited.email != null) ? + {(!!this.props.email && this.props.edited.email != "") ? withTooltip(
emailButton(this.props.edited)} > From 015cd7169ebf98e0ededca96eaf9b1993a0d6cdf Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Mon, 13 Nov 2023 17:42:40 +0530 Subject: [PATCH 027/111] Rework and PEnding approval changes --- src/actions.js | 2 ++ src/components/RequireAuth.js | 56 +++++++++++++++++++++++++++++++-- src/components/generics/Form.js | 6 ++-- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/actions.js b/src/actions.js index 5ddb09b5..e109b134 100644 --- a/src/actions.js +++ b/src/actions.js @@ -275,6 +275,7 @@ export function login(credentials) { } const action = await dispatch(loadUser()); localStorage.setItem("userLanguage", action?.payload?.i_user?.language); + localStorage.setItem("userId", action?.payload?.id); return action.type !== "CORE_AUTH_ERR"; }; } @@ -320,6 +321,7 @@ export function logout() { `; await dispatch(graphqlMutation(mutation, {})); localStorage.removeItem("userLanguage"); + localStorage.removeItem("userId"); return dispatch({ type: "CORE_AUTH_LOGOUT" }); }; } diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index 306e7756..c49145eb 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -1,4 +1,4 @@ -import React, { useMemo } from "react"; +import React, { useMemo, useState, useEffect } from "react"; import withWidth from "@material-ui/core/withWidth"; import { Redirect } from "../helpers/history"; import { alpha, useTheme, makeStyles } from "@material-ui/core/styles"; @@ -23,6 +23,10 @@ import Contributions from "./generics/Contributions"; import FormattedMessage from "./generics/FormattedMessage"; import JournalDrawer from "./JournalDrawer"; import { useBoolean, useAuthentication } from "../helpers/hooks"; +import { useGraphqlQuery } from "@openimis/fe-core"; +import { formatMessageWithValues, withModulesManager, withHistory, historyPush } from "@openimis/fe-core"; +import NotificationsIcon from "@material-ui/icons/Notifications"; +import { useDispatch } from "react-redux"; export const APP_BAR_CONTRIBUTION_KEY = "core.AppBar"; export const MAIN_MENU_CONTRIBUTION_KEY = "core.MainMenu"; @@ -150,6 +154,25 @@ const useStyles = makeStyles((theme) => ({ }, }, }, + iconContainer: { + position: "relative", + cursor: "pointer", + margin: "3px 9px 0 0", + }, + iconBtn: { + position: "absolute", + top: "5", + right: "0", + width: "15px", + height: "15px", + background: "red", + borderRadius: "50%", + marginBottom: "20px", + textAlign: "center", + display: "flex", + justifyContent: "center", + alignItems: "center", + }, })); const RequireAuth = (props) => { @@ -160,7 +183,28 @@ const RequireAuth = (props) => { const classes = useStyles(); const modulesManager = useModulesManager(); const auth = useAuthentication(); - + const [searchString, setSearchString] = useState(); + const dispatch = useDispatch(); + const { isLoading, data, error } = useGraphqlQuery( + ` + query ApproverFamiliesCount { + approverFamiliesCount { + approverFamiliesCount + } + } + `, + { str: searchString }, + ); + useEffect(() => { + if (!!data) { + dispatch({ type: "INSUREE_COUNT_RESP", payload: data }); + } + }, [data]); + const bellIcon = () => { + if (data?.approverFamiliesCount?.approverFamiliesCount > 0) { + historyPush(modulesManager, props.history, "insuree.route.pendingApproval"); + } + }; const isAppBarMenu = useMemo(() => theme.menu.variant.toUpperCase() === "APPBAR", [theme.menu.variant]); if (!auth.isAuthenticated) { @@ -190,7 +234,6 @@ const RequireAuth = (props) => { )} CAMU - @@ -208,7 +251,14 @@ const RequireAuth = (props) => { )}
+
+
+
{data?.approverFamiliesCount?.approverFamiliesCount}
+ +
+
+ {/* */} diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 51353737..dbb7895f 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -102,11 +102,12 @@ class Form extends Component { approveorreject, handleDialogOpen, printButton, + approverData, paymentPrint, success, ...others } = this.props; - // console.log(this.props.edited, "editedsdf") + let userId = localStorage.getItem("userId"); return ( @@ -191,7 +192,8 @@ class Form extends Component { /> )} - {title == "Insuree.title" && this.props.edited?.biometricsStatus ? ( + + {title == "Insuree.title" && this.props.edited?.biometricsStatus && approverData == userId ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( From 55a5ec9f31da969c198205539e8ea2e692ec053a Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Tue, 14 Nov 2023 10:41:46 +0530 Subject: [PATCH 028/111] setPasswordScreen UI Change --- src/pages/SetPasswordPage.js | 32 ++++++++++++++++++++++++++++---- src/translations/en.json | 10 +++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/pages/SetPasswordPage.js b/src/pages/SetPasswordPage.js index abf47b14..f4606d73 100644 --- a/src/pages/SetPasswordPage.js +++ b/src/pages/SetPasswordPage.js @@ -12,7 +12,7 @@ import { useGraphqlMutation } from "../helpers/hooks"; const useStyles = makeStyles((theme) => ({ container: { position: "absolute", - top: "30%", + top: "20%", left: 0, right: 0, margin: "auto", @@ -23,9 +23,12 @@ const useStyles = makeStyles((theme) => ({ logo: { maxHeight: 100, }, + setBox: { + boxShadow: '0px 0px 0px #eee' + } })); -const SetPasswordPage = () => { +const SetPasswordPage = (props) => { const classes = useStyles(); const history = useHistory(); const modulesManager = useModulesManager(); @@ -78,12 +81,32 @@ const SetPasswordPage = () => { return ( <> +
+
- +
- + + + + +
{formatMessage("pageTitle")}
{
+
); }; diff --git a/src/translations/en.json b/src/translations/en.json index f427c4ea..743dfcea 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -51,12 +51,12 @@ "core.ForgotPasswordPage.done.Verification": "Un e-mail contenant le lien de vérification a été envoyé à votre adresse e-mail", "core.ForgotPasswordPage.done.Administrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur", "core.ForgotPasswordPage.backButton": "Retour à la connexion", - "core.SetPasswordPage.pageTitle": "Set a new Password", - "core.SetPasswordPage.username.label": "Username", - "core.SetPasswordPage.password.label": "Password", - "core.SetPasswordPage.confirmPassword.label": "Confirm Password", + "core.SetPasswordPage.pageTitle": "Définir un nouveau mot de passe", + "core.SetPasswordPage.username.label": "Nom d'utilisateur", + "core.SetPasswordPage.password.label": "Mot de passe", + "core.SetPasswordPage.confirmPassword.label": "Confirmer le mot de passe", "core.SetPasswordPage.error": "Unknown error", - "core.SetPasswordPage.submitBtn": "Submit", + "core.SetPasswordPage.submitBtn": "Soumettre", "core.table.resultsLoading": "Loading...", "core.exportSearchResult": "Export search result", "core.exportSearchResult.tooltip": "Export result", From 094d95eba864d6113f7a1d9c2ea38229ad5432a8 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Thu, 16 Nov 2023 20:02:23 +0530 Subject: [PATCH 029/111] Change Date formate --- src/pickers/AdDatePicker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pickers/AdDatePicker.js b/src/pickers/AdDatePicker.js index 32d80a51..5d038b21 100644 --- a/src/pickers/AdDatePicker.js +++ b/src/pickers/AdDatePicker.js @@ -47,7 +47,7 @@ class AdDatePicker extends Component { readOnly = false, required = false, fullWidth = true, - format = "YYYY-MM-DD", + format = "DD-MM-YYYY", reset, ...otherProps } = this.props; From ced9ea72772248bedb9d7a046d5026a3254c0ee5 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Sat, 18 Nov 2023 23:23:55 +0530 Subject: [PATCH 030/111] add edited --- src/components/generics/Form.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index dbb7895f..1b08578a 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -105,6 +105,7 @@ class Form extends Component { approverData, paymentPrint, success, + edited, ...others } = this.props; let userId = localStorage.getItem("userId"); @@ -282,7 +283,9 @@ class Form extends Component {
// saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), ) : ""} - {(!!this.props.email && this.props.edited.email != "") ? + {/* {(!!this.props.email && this.props.edited.email != "") ? */} + {(!!this.props.print && this.props.edited.email != "") ? + withTooltip(
From 4789a8e6b360c96bba416a4ff3b0afef092dc822 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Sun, 19 Nov 2023 17:53:42 +0530 Subject: [PATCH 031/111] change for menu role --- src/index.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index ec3b18d7..ea25e57f 100644 --- a/src/index.js +++ b/src/index.js @@ -87,11 +87,9 @@ import { sort, formatSorter, formatGQLString, - formatNodeQuery + formatNodeQuery, } from "./helpers/api"; -import { - downloadExport -} from "./helpers/downloadExport" +import { downloadExport } from "./helpers/downloadExport"; import { useDebounceCb, usePrevious, @@ -136,14 +134,14 @@ const DEFAULT_CONFIG = { { path: ROUTE_ROLES, component: Roles }, { path: ROUTE_ROLE + "/:role_uuid?", component: Role }, ], - "admin.MainMenu": [ - { - text: , - icon: , - route: "/" + ROUTE_ROLES, - filter: (rights) => rights.includes(RIGHT_ROLE_SEARCH), - }, - ], + // "admin.MainMenu": [ + // { + // text: , + // icon: , + // route: "/" + ROUTE_ROLES, + // filter: (rights) => rights.includes(RIGHT_ROLE_SEARCH), + // }, + // ], }; export const CoreModule = (cfg) => { From 0e4b3de3120683d60039745f48abf6f15722ab47 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Mon, 27 Nov 2023 13:28:55 +0530 Subject: [PATCH 032/111] error boundary changes --- src/helpers/ErrorBoundary.js | 7 +++++-- src/translations/en.json | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/helpers/ErrorBoundary.js b/src/helpers/ErrorBoundary.js index eb7d0f44..6700fdf1 100644 --- a/src/helpers/ErrorBoundary.js +++ b/src/helpers/ErrorBoundary.js @@ -1,4 +1,6 @@ import React from "react"; +import { formatMessage } from "./i18n"; +import { injectIntl } from "react-intl"; class ErrorBoundary extends React.Component { constructor(props) { @@ -17,10 +19,11 @@ class ErrorBoundary extends React.Component { } render() { if (this.state.hasError) { - return

An error was not properly caught. Refer to console log.

; + return

{formatMessage(this.props.intl, "core", "common.errorBoundary")}

; + // return

An error was not properly caught. Refer to console log.

; } return this.props.children; } } -export default ErrorBoundary; +export default injectIntl(ErrorBoundary); diff --git a/src/translations/en.json b/src/translations/en.json index 743dfcea..7f2b403e 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -68,5 +68,6 @@ "core.ForgotPasswordPage.contactAdministrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur.", "core.datePicker.ok":"OK", "core.datePicker.cancel":"CANCEL", - "core.datePicker.clear":"CLEAR" + "core.datePicker.clear":"CLEAR", + "core.common.errorBoundary":"An error was not properly caught. Refer to console log." } From b58b8dc03719c2d058c0ff1904690a3b37f00fb7 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Wed, 29 Nov 2023 23:29:26 +0530 Subject: [PATCH 033/111] added tooltip and disabled approve --- src/components/generics/Form.js | 102 ++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 1b08578a..e067a2c8 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -199,11 +199,15 @@ class Form extends Component { <> {withTooltip(
- handleDialogOpen("rework", this.props.edited)}> + handleDialogOpen("rework", this.props.edited)} + disabled={!!this.state.saving || (!!canSave && !canSave())} + >
, - addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + addTooltip || formatMessage(this.props.intl, module, "reworkTooltip"), )} {withTooltip( @@ -211,11 +215,12 @@ class Form extends Component { handleDialogOpen("reject", this.props.edited)} + disabled={!!this.state.saving || (!!canSave && !canSave())} >
, - addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), )} ) : allApproved && this.props.edited.biometricsIsMaster && this.props?.edited?.status !== "APPROVED" ? ( @@ -226,6 +231,7 @@ class Form extends Component { handleDialogOpen("reject", this.props.edited)} + disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -234,7 +240,11 @@ class Form extends Component { )} {withTooltip(
- approveorreject({ ...this.props.edited, status: "APPROVED" })}> + approveorreject({ ...this.props.edited, status: "APPROVED" })} + disabled={!!this.state.saving || (!!canSave && !canSave())} + >
, @@ -243,6 +253,7 @@ class Form extends Component { ) : null ) : null} + {!this.state.dirty && !!add && !save && @@ -268,55 +279,54 @@ class Form extends Component {
, // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), )} - {(!!this.props.paymentPrint) ? - withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
- // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) : ""} + {!!this.props.paymentPrint + ? withTooltip( +
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} {/* {(!!this.props.email && this.props.edited.email != "") ? */} - {(!!this.props.print && this.props.edited.email != "") ? - - withTooltip( -
-
+ {!!this.props.print && this.props.edited.email != "" + ? withTooltip( +
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} + {!!this.props.email && this.props.edited.email != "" + ? withTooltip( +
printButton(this.props.edited)} - + onClick={(e) => emailButton(this.props.edited)} > - + -
-
- // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) : ""} - {(!!this.props.email && this.props.edited.email != "") ? - withTooltip( -
- emailButton(this.props.edited)} - > - - -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && From 00ec4b19278ba2b91ff19e8ab0ff2875bac4a3c5 Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Fri, 1 Dec 2023 10:22:56 +0530 Subject: [PATCH 034/111] bed request label changes --- src/components/dialogs/AlertDialog.js | 3 ++- src/components/generics/Searcher.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/dialogs/AlertDialog.js b/src/components/dialogs/AlertDialog.js index 1def5383..fa49ea33 100644 --- a/src/components/dialogs/AlertDialog.js +++ b/src/components/dialogs/AlertDialog.js @@ -42,7 +42,8 @@ class AlertDialog extends Component { - {ensureArray(alert.message ?? formatMessage(intl, "core", "FatalError.message")).map( + {/* {ensureArray(alert.message ?? formatMessage(intl, "core", "FatalError.message")).map( */} + {ensureArray(formatMessage(intl, "core", `FatalError.${alert.message}`)) ?? formatMessage(intl, "core", "FatalError.message").map( (message, i) => ( {message} diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index a6729c2b..f4a59c06 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -106,6 +106,7 @@ class SelectionMenu extends Component { ); renderMenu = (entries, contributionKey) => { + console.log('-------', this.openMenu) return ( From 7bfa835f32fed33ee8a7132e13be58b950d2078d Mon Sep 17 00:00:00 2001 From: Rajat Sharma Date: Fri, 1 Dec 2023 10:23:26 +0530 Subject: [PATCH 035/111] remove console log --- src/components/generics/Searcher.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index f4a59c06..a6729c2b 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -106,7 +106,6 @@ class SelectionMenu extends Component { ); renderMenu = (entries, contributionKey) => { - console.log('-------', this.openMenu) return ( From 6bc398d5f0989afe687a543230d6eacb55a142cb Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Fri, 1 Dec 2023 15:58:35 +0530 Subject: [PATCH 036/111] status buttons changes --- src/components/generics/Form.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index e067a2c8..6e5203fd 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -194,7 +194,8 @@ class Form extends Component { )} - {title == "Insuree.title" && this.props.edited?.biometricsStatus && approverData == userId ? ( + {title == "Insuree.title" && this.props.edited?.biometricsStatus ? ( + // {title == "Insuree.title" && this.props.edited?.biometricsStatus && approverData == userId ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( From 9fdf4ece3e3e35b61d6842cf3c7a08fac9dd9370 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Fri, 1 Dec 2023 17:13:49 +0530 Subject: [PATCH 037/111] buttons only for waiting for approval --- src/components/generics/Form.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 6e5203fd..00f70c18 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -194,7 +194,9 @@ class Form extends Component { )} - {title == "Insuree.title" && this.props.edited?.biometricsStatus ? ( + {title == "Insuree.title" && + this.props.edited?.biometricsStatus && + this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( // {title == "Insuree.title" && this.props.edited?.biometricsStatus && approverData == userId ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> From 1f36c9ef70a080ce6a4f08b34bafc292a659bc2f Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Mon, 4 Dec 2023 18:22:44 +0530 Subject: [PATCH 038/111] idle logout implementation --- package.json | 1 + src/components/RequireAuth.js | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/package.json b/package.json index 596f7dac..f7350ea8 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ ], "dependencies": { "history": "^5.2.0", + "react-idle-timer": "^5.7.2", "react-router": "^5.2.1", "react-router-dom": "^5.2.1" } diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index c49145eb..f9356c2b 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -27,6 +27,8 @@ import { useGraphqlQuery } from "@openimis/fe-core"; import { formatMessageWithValues, withModulesManager, withHistory, historyPush } from "@openimis/fe-core"; import NotificationsIcon from "@material-ui/icons/Notifications"; import { useDispatch } from "react-redux"; +import { useIdleTimer } from "react-idle-timer/dist/index.legacy.cjs.js"; // otherwise not building: https://github.com/SupremeTechnopriest/react-idle-timer/issues/350 +import { logout } from "../actions"; export const APP_BAR_CONTRIBUTION_KEY = "core.AppBar"; export const MAIN_MENU_CONTRIBUTION_KEY = "core.MainMenu"; @@ -206,6 +208,19 @@ const RequireAuth = (props) => { } }; const isAppBarMenu = useMemo(() => theme.menu.variant.toUpperCase() === "APPBAR", [theme.menu.variant]); + const idleTimeout = modulesManager.getConf("fe-core", "auth.idleTimeout", Math.floor(30 * 60 * 1000)); // TODO: fix modulesManager - is always empty at this stage, so always using default value + const onIdle = async () => { + await dispatch(logout()); + // history.push("/"); + }; + const { startIdleTimer } = useIdleTimer({ + onIdle: onIdle, + timeout: idleTimeout, + throttle: 500, + }); + useEffect(() => { + startIdleTimer; + }, [startIdleTimer]); if (!auth.isAuthenticated) { return ; From 2362aa316ce24d0fb3c5994d67b8f27409ee3fb2 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Wed, 6 Dec 2023 17:05:25 +0530 Subject: [PATCH 039/111] text capitalize added --- src/components/inputs/TextInput.js | 37 ++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/components/inputs/TextInput.js b/src/components/inputs/TextInput.js index cc8591e9..6c3ce254 100644 --- a/src/components/inputs/TextInput.js +++ b/src/components/inputs/TextInput.js @@ -10,17 +10,17 @@ const styles = (theme) => ({ }, // NOTE: This is used to hide the increment/decrement arrows from the number input numberInput: { - '& input[type=number]': { - '-moz-appearance': 'textfield' + "& input[type=number]": { + "-moz-appearance": "textfield", }, - '& input[type=number]::-webkit-outer-spin-button': { - '-webkit-appearance': 'none', - margin: 0 + "& input[type=number]::-webkit-outer-spin-button": { + "-webkit-appearance": "none", + margin: 0, + }, + "& input[type=number]::-webkit-inner-spin-button": { + "-webkit-appearance": "none", + margin: 0, }, - '& input[type=number]::-webkit-inner-spin-button': { - '-webkit-appearance': 'none', - margin: 0 - } }, }); @@ -71,9 +71,16 @@ class TextInput extends Component { formatInput = null, helperText, type, + capitalize, ...others } = this.props; - const inputClass = readOnly ? classes.disabledInput : ''; + const inputClass = readOnly ? classes.disabledInput : ""; + let transformedValue = this.state.value; + + // Capitalize the value if the capitalize prop is true + // if (capitalize && transformedValue) { + // transformedValue = transformedValue.toUpperCase(); + // } return ( Date: Thu, 7 Dec 2023 18:42:44 +0530 Subject: [PATCH 040/111] changes of idle timeout variable --- src/components/RequireAuth.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index f9356c2b..d3ffd7df 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -208,7 +208,12 @@ const RequireAuth = (props) => { } }; const isAppBarMenu = useMemo(() => theme.menu.variant.toUpperCase() === "APPBAR", [theme.menu.variant]); - const idleTimeout = modulesManager.getConf("fe-core", "auth.idleTimeout", Math.floor(30 * 60 * 1000)); // TODO: fix modulesManager - is always empty at this stage, so always using default value + console.log('process.env.REACT_APP_IDLE_LOGOUT_TIME',Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME)); + const idleTimeout = modulesManager.getConf( + "fe-core", + "auth.idleTimeout", + Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME), + ); // TODO: fix modulesManager - is always empty at this stage, so always using default value const onIdle = async () => { await dispatch(logout()); // history.push("/"); From 80f480f89330a8b4d31d9879e82e2de1bf304f6a Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Fri, 8 Dec 2023 15:29:45 +0530 Subject: [PATCH 041/111] API integration to check assignedprofile before logout --- src/actions.js | 13 +++++++++++++ src/components/LogoutButton.js | 10 +++++++--- src/components/RequireAuth.js | 12 ++++++++---- src/reducer.js | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/actions.js b/src/actions.js index e109b134..b3086bfa 100644 --- a/src/actions.js +++ b/src/actions.js @@ -39,6 +39,7 @@ export const baseApiUrl = getApiUrl(); export function apiHeaders() { let headers = { + // "ngrok-skip-browser-warning": "true", "Content-Type": "application/json", }; return headers; @@ -241,6 +242,7 @@ export function fetch(config) { [RSAA]: { ...config, headers: { + // "ngrok-skip-browser-warning": "true", "Content-Type": "application/json", ...config.headers, }, @@ -326,6 +328,17 @@ export function logout() { }; } +export function CheckAssignedProfile(userID) { + const mutation = `mutation CheckAssignedProfiles { + checkAssignedProfiles(userId:"${userID}") { + status + } + } + `; + return graphql(mutation, "CHECK_ASSIGNED_PROFILE", {}); +} +// } + export function fetchMutation(clientMutationId) { const payload = formatPageQuery( "mutationLogs", diff --git a/src/components/LogoutButton.js b/src/components/LogoutButton.js index 51d3f4f4..d48ae6f5 100644 --- a/src/components/LogoutButton.js +++ b/src/components/LogoutButton.js @@ -3,7 +3,7 @@ import { makeStyles } from "@material-ui/core/styles"; import { useDispatch } from "react-redux"; import { IconButton } from "@material-ui/core"; import { ExitToApp } from "@material-ui/icons"; -import { logout } from "../actions"; +import { CheckAssignedProfile, logout } from "../actions"; import { useHistory } from "../helpers/history"; const useStyles = makeStyles((theme) => ({ @@ -16,9 +16,13 @@ const useStyles = makeStyles((theme) => ({ const LogoutButton = () => { const history = useHistory(); const dispatch = useDispatch(); + const userid = localStorage.getItem("userId"); const onClick = async () => { - await dispatch(logout()); - history.push("/"); + const response = await dispatch(CheckAssignedProfile(userid)); + if (!!response.payload.data.checkAssignedProfiles.status) { + await dispatch(logout()); + history.push("/"); + } }; const classes = useStyles(); diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index d3ffd7df..cdd76cdd 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -28,7 +28,7 @@ import { formatMessageWithValues, withModulesManager, withHistory, historyPush } import NotificationsIcon from "@material-ui/icons/Notifications"; import { useDispatch } from "react-redux"; import { useIdleTimer } from "react-idle-timer/dist/index.legacy.cjs.js"; // otherwise not building: https://github.com/SupremeTechnopriest/react-idle-timer/issues/350 -import { logout } from "../actions"; +import { CheckAssignedProfile, logout } from "../actions"; export const APP_BAR_CONTRIBUTION_KEY = "core.AppBar"; export const MAIN_MENU_CONTRIBUTION_KEY = "core.MainMenu"; @@ -208,14 +208,18 @@ const RequireAuth = (props) => { } }; const isAppBarMenu = useMemo(() => theme.menu.variant.toUpperCase() === "APPBAR", [theme.menu.variant]); - console.log('process.env.REACT_APP_IDLE_LOGOUT_TIME',Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME)); + console.log("process.env.REACT_APP_IDLE_LOGOUT_TIME", Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME)); const idleTimeout = modulesManager.getConf( "fe-core", "auth.idleTimeout", - Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME), + Math.floor(30 * 60 * 1000), + // Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME), ); // TODO: fix modulesManager - is always empty at this stage, so always using default value const onIdle = async () => { - await dispatch(logout()); + const response = await CheckAssignedProfile(); + if (!!response.payload.data.checkAssignedProfiles.status) { + await dispatch(logout()); + } // history.push("/"); }; const { startIdleTimer } = useIdleTimer({ diff --git a/src/reducer.js b/src/reducer.js index 0652844b..5598c3ea 100644 --- a/src/reducer.js +++ b/src/reducer.js @@ -43,6 +43,7 @@ function reducer( afterCursor: null, beforeCursor: null, module: null, + assigned: null, }, action, ) { @@ -358,6 +359,21 @@ function reducer( role: null, roleRights: [], }; + case "CHECK_ASSIGNED_PROFILE_REQ": + return { + ...state, + assigned: null, + }; + case "CHECK_ASSIGNED_PROFILE_RES": + return { + ...state, + assigned: action.payload, + }; + case "CHECK_ASSIGNED_PROFILE_ERR": + return { + ...state, + assigned: null, + }; case "CORE_PAGINATION_PAGE": return { ...state, From 8c22ef855f254de8ac942a3c5be927f26e184e13 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Mon, 11 Dec 2023 12:59:00 +0530 Subject: [PATCH 042/111] idle timeout in variable --- src/components/RequireAuth.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index cdd76cdd..cbc2d2d5 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -207,16 +207,14 @@ const RequireAuth = (props) => { historyPush(modulesManager, props.history, "insuree.route.pendingApproval"); } }; + const isAppBarMenu = useMemo(() => theme.menu.variant.toUpperCase() === "APPBAR", [theme.menu.variant]); + const idleTimeSet = 30 * 60 * 1000; console.log("process.env.REACT_APP_IDLE_LOGOUT_TIME", Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME)); - const idleTimeout = modulesManager.getConf( - "fe-core", - "auth.idleTimeout", - Math.floor(30 * 60 * 1000), - // Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME), - ); // TODO: fix modulesManager - is always empty at this stage, so always using default value + const idleTimeout = modulesManager.getConf("fe-core", "auth.idleTimeout", Math.floor(idleTimeSet)); // TODO: fix modulesManager - is always empty at this stage, so always using default value const onIdle = async () => { - const response = await CheckAssignedProfile(); + const userid = localStorage.getItem("userId"); + const response = await dispatch(CheckAssignedProfile(userid)); if (!!response.payload.data.checkAssignedProfiles.status) { await dispatch(logout()); } From c878320694d2aef88945a9c3e11e412cf1d5cbf4 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Thu, 14 Dec 2023 19:31:15 +0530 Subject: [PATCH 043/111] enable approver role based button --- src/components/generics/Form.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 00f70c18..007b49aa 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -194,10 +194,13 @@ class Form extends Component { )} + {/* {title == "Insuree.title" && + this.props.edited?.biometricsStatus && + this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( */} {title == "Insuree.title" && this.props.edited?.biometricsStatus && + approverData == userId && this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( - // {title == "Insuree.title" && this.props.edited?.biometricsStatus && approverData == userId ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( From a4f1a3562e597a00884bf37c9e1463dd91525ee1 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Tue, 26 Dec 2023 11:32:00 +0545 Subject: [PATCH 044/111] eye icon to show/hide password --- src/pages/LoginPage.js | 285 +++++++++++++++++++++++------------------ 1 file changed, 162 insertions(+), 123 deletions(-) diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js index efe0c563..7509785a 100644 --- a/src/pages/LoginPage.js +++ b/src/pages/LoginPage.js @@ -1,13 +1,26 @@ import React, { useMemo, useState, useEffect } from "react"; import { useHistory } from "../helpers/history"; import { makeStyles } from "@material-ui/styles"; -import { Button, Box, Grid, Paper, LinearProgress, Checkbox, FormControlLabel } from "@material-ui/core"; +import { + Button, + Box, + Grid, + Paper, + LinearProgress, + Checkbox, + FormControlLabel, + IconButton, + InputAdornment, + TextField, +} from "@material-ui/core"; import TextInput from "../components/inputs/TextInput"; import { useTranslations } from "../helpers/i18n"; import { useModulesManager } from "../helpers/modules"; import Helmet from "../helpers/Helmet"; import { useAuthentication } from "../helpers/hooks"; import Contributions from "./../components/generics/Contributions"; +import Visibility from "@material-ui/icons/Visibility"; +import VisibilityOff from "@material-ui/icons/VisibilityOff"; const useStyles = makeStyles((theme) => ({ container: { @@ -26,6 +39,9 @@ const useStyles = makeStyles((theme) => ({ maxHeight: 100, width: 100, }, + inputAdornment: { + backgroundColor: "#0000", // Adjust based on your theme + }, })); const LOGIN_PAGE_CONTRIBUTION_KEY = "core.LoginPage"; @@ -39,28 +55,30 @@ const LoginPage = ({ logo, backgroundImage }) => { const [hasError, setError] = useState(false); const auth = useAuthentication(); const [isAuthenticating, setAuthenticating] = useState(false); - const initialState = localStorage.getItem('rememberMe') === 'true'; + const initialState = localStorage.getItem("rememberMe") === "true"; const [rememberMe, setRememberMe] = useState(initialState); - + const [showPassword, setShowPassword] = useState(false); + const handleClickShowPassword = () => setShowPassword(!showPassword); + const handleMouseDownPassword = () => setShowPassword(!showPassword); const handleRememberMeChange = (event) => { const isChecked = event.target.checked; setRememberMe(isChecked); - - console.log('Remember Me is checked:', isChecked); - + + console.log("Remember Me is checked:", isChecked); + if (!isChecked) { // If "Remember Me" is unchecked, clear the saved credentials. - localStorage.removeItem('rememberedUsername'); - localStorage.removeItem('rememberedPassword'); + localStorage.removeItem("rememberedUsername"); + localStorage.removeItem("rememberedPassword"); } else { // If "Remember Me" is checked, save the username and password. - localStorage.setItem('rememberedUsername', credentials.username); - localStorage.setItem('rememberedPassword', credentials.password); - - console.log('Saved username and password:', credentials.username, credentials.password); + localStorage.setItem("rememberedUsername", credentials.username); + localStorage.setItem("rememberedPassword", credentials.password); + + console.log("Saved username and password:", credentials.username, credentials.password); } - - localStorage.setItem('rememberMe', isChecked.toString()); + + localStorage.setItem("rememberMe", isChecked.toString()); }; useEffect(() => { @@ -69,8 +87,8 @@ const LoginPage = ({ logo, backgroundImage }) => { } else { // If "Remember Me" is checked, retrieve and set the saved credentials. if (rememberMe) { - const savedUsername = localStorage.getItem('rememberedUsername'); - const savedPassword = localStorage.getItem('rememberedPassword'); + const savedUsername = localStorage.getItem("rememberedUsername"); + const savedPassword = localStorage.getItem("rememberedPassword"); if (savedUsername && savedPassword) { setCredentials({ username: savedUsername, password: savedPassword }); } @@ -101,127 +119,148 @@ const LoginPage = ({ logo, backgroundImage }) => { )} -
-
-
- +
+
+
+ - -
- - - - - {/* + + + + + + + {/* {formatMessage("core.displayAppName")} */} - - {/* + + {/* "Insurance Management System" */} -
CAMU IMS
- - setCredentials({ ...credentials, username })} - /> - - - setCredentials({ ...credentials, password })} - /> - - {hasError && ( +
+ CAMU IMS +
- {formatMessage("authError")} + setCredentials({ ...credentials, username })} + /> - )} - - - + setCredentials({ ...credentials, password: event.target.value })} + InputProps={{ + endAdornment: ( + + + {showPassword ? : } + + + ), + }} + /> + + {hasError && ( + + {formatMessage("authError")} + + )} + + + + } + /> + +
+ {formatMessage("forgotPassword")} +
+ - } />
-
- {formatMessage("forgotPassword")} -
- -
- - + + + - -
-
- -
+
+ +
+
-
- )} + ); +}; export default LoginPage; From fd42db775e6f5435c1b040250c52c08729da51b4 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Mon, 8 Jan 2024 17:35:18 +0530 Subject: [PATCH 045/111] date picker changes for months and year --- src/pickers/AdDatePicker.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pickers/AdDatePicker.js b/src/pickers/AdDatePicker.js index 5d038b21..f00f3d57 100644 --- a/src/pickers/AdDatePicker.js +++ b/src/pickers/AdDatePicker.js @@ -49,6 +49,7 @@ class AdDatePicker extends Component { fullWidth = true, format = "DD-MM-YYYY", reset, + monthtrue, ...otherProps } = this.props; let userlang = localStorage.getItem("userLanguage"); @@ -81,7 +82,7 @@ class AdDatePicker extends Component { onChange={this.dateChange} reset={reset} disablePast={disablePast} - views={["year", "month", "date"]} + views={monthtrue?["year", "month"]:["year", "month", "date"]} okLabel={formatMessage(intl, "core", "datePicker.ok")} clearLabel={formatMessage(intl, "core", "datePicker.clear")} cancelLabel={formatMessage(intl, "core", "datePicker.cancel")} From 8ad8cff3e0bc7617ccac84be9cb5b9d4d1f5d166 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Wed, 10 Jan 2024 15:05:20 +0530 Subject: [PATCH 046/111] changes in searcher for reset --- src/components/generics/Searcher.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index a6729c2b..f3df1a72 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -426,6 +426,7 @@ class Searcher extends Component { onChangeFilters={this.onChangeFilters} FilterExt={FilterExt} filterPaneContributionsKey={filterPaneContributionsKey} + reset={this.resetFilters} /> } /> From 887e9c4c6fc342e1a825bd73792a84d49701ea0f Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Mon, 15 Jan 2024 15:43:40 +0530 Subject: [PATCH 047/111] add bg color --- src/components/generics/Searcher.js | 33 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index a6729c2b..2c01e483 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -32,7 +32,7 @@ import Table from "./Table"; const styles = (theme) => ({ root: { width: "100%", - margin:24 + margin: 24 }, paper: theme.paper.body, paperHeader: theme.paper.header, @@ -40,6 +40,7 @@ const styles = (theme) => ({ paperHeaderMessage: theme.paper.message, paperHeaderAction: { paddingInline: 5, + color: "#00913E" }, paperDivider: theme.paper.divider, tableHeaderAction: theme.table.headerAction, @@ -84,12 +85,12 @@ class SelectionMenu extends Component { {entries.map((i, idx) => ( - + ))} - {this.props.exportable && ( ))} {this.props.exportable && ( - )} @@ -150,7 +151,7 @@ class SelectionMenu extends Component { processing, actionsContributionKey = null, } = this.props; - + console.log(actions, "actions") let contributed_entries = modulesManager.getContribs(actionsContributionKey); if (!actions.length && !contributed_entries) return null; if (processing) { @@ -170,7 +171,7 @@ class SelectionMenu extends Component { entries.push({ text: formatMessage(intl, "claim", a.label), action: a.action }); } }); - if (entries.length > 2 || (this.props.exportable && entries.length>=1)) { + if (entries.length > 2 || (this.props.exportable && entries.length >= 1)) { return this.renderMenu(entries, actionsContributionKey); } else { return this.renderButtons(entries, actionsContributionKey); @@ -360,13 +361,13 @@ class Searcher extends Component { return this.props.sorts(filters).map((s) => !!s ? [ - () => - this.setState( - (state, props) => ({ orderBy: sort(state.orderBy, s[0], s[1]) }), - (e) => this.props.fetch(this.filtersToQueryParams()) - ), - () => formatSorter(this.state.orderBy, s[0], s[1]), - ] + () => + this.setState( + (state, props) => ({ orderBy: sort(state.orderBy, s[0], s[1]) }), + (e) => this.props.fetch(this.filtersToQueryParams()) + ), + () => formatSorter(this.state.orderBy, s[0], s[1]), + ] : [null, () => null] ); } @@ -450,7 +451,7 @@ class Searcher extends Component { - {fetchedItems && ( + {fetchedItems && ( Date: Tue, 16 Jan 2024 18:55:18 +0530 Subject: [PATCH 048/111] paymentApprove button --- src/components/generics/Form.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 007b49aa..fb7d8818 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -31,6 +31,9 @@ const styles = (theme) => ({ fabMargin: { marginBottom: "140px", }, + fabPayMargin: { + marginBottom: "200px", + }, customFab: { background: "#fff", border: "2px solid #FF841C", // Your desired border color @@ -104,6 +107,7 @@ class Form extends Component { printButton, approverData, paymentPrint, + paymentApprove, success, edited, ...others @@ -193,7 +197,34 @@ class Form extends Component { /> )} - + {paymentApprove ? ( + <> + {withTooltip( +
+ approveorreject({ ...this.props.edited, status: -1 })} + disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + {withTooltip( +
+ approveorreject({ ...this.props.edited, status: 5 })} + disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + + ) : null} {/* {title == "Insuree.title" && this.props.edited?.biometricsStatus && this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( */} From 6b5afb45a7eb8c66e6d486e66fc06e0bc3b3bcc5 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Wed, 17 Jan 2024 11:47:28 +0530 Subject: [PATCH 049/111] added common snackbar --- src/components/generics/CommonSnakbar.js | 130 +++++++++++++++++++++++ src/components/generics/Form.js | 4 +- src/index.js | 2 + 3 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/components/generics/CommonSnakbar.js diff --git a/src/components/generics/CommonSnakbar.js b/src/components/generics/CommonSnakbar.js new file mode 100644 index 00000000..943e30a3 --- /dev/null +++ b/src/components/generics/CommonSnakbar.js @@ -0,0 +1,130 @@ +import React, { useState, useCallback } from "react"; +import Snackbar from "@material-ui/core/Snackbar"; +import Alert from "@material-ui/lab/Alert"; +import IconButton from "@material-ui/core/IconButton"; +import FileCopyIcon from "@material-ui/icons/FileCopy"; +import CloseIcon from "@material-ui/icons/Close"; +import ErrorIcon from "@material-ui/icons/Error"; +import WarningIcon from "@material-ui/icons/Warning"; +import InfoIcon from "@material-ui/icons/Info"; +import CheckCircleIcon from "@material-ui/icons/CheckCircle"; +import { makeStyles } from "@material-ui/core/styles"; + +const useStyles = makeStyles((theme) => ({ + snackbar: { + marginRight: "50px", + color: "white", + }, + alert: { + color: "white", + display: "flex", + alignItems: "center", + }, + copyContainer: { + display: "flex", + alignItems: "center", + }, + copyText: { + marginLeft: "4px", + }, + whiteIcon: { + color: "white", + }, +})); + +const CommonSnackbar = ({ open, onClose, message, severity, copyText = "" }) => { + const [isCopied, setIsCopied] = useState(false); + const classes = useStyles(); + + const handleCopyClick = useCallback(() => { + if (navigator.clipboard) { + navigator.clipboard + .writeText(copyText) + .then(() => { + setIsCopied(true); + }) + .catch((err) => { + console.error("Failed to copy text: ", err); + }); + } + }, [copyText]); + + const handleClose = (event, reason) => { + if (reason === "clickaway") { + return; + } + onClose(event, reason); + setIsCopied(false); + }; + + + const getIcon = () => { + switch (severity) { + case "error": + return ; + case "warning": + return ; + case "info": + return ; + case "success": + return ; + default: + return null; + } + }; + + const getBackgroundColor = () => { + switch (severity) { + case "error": + return "#d32f2f"; + case "warning": + return "#ffa000"; + case "info": + return "#1976d2"; + case "success": + return "#4caf50"; + default: + return "inherit"; + } + }; + + return ( + + + {copyText && ( +
+
{copyText}
+ + + + {isCopied ? "Copied!" : "Copy"} +
+ )} + + + + + } + > + {message} +
+
+ ); +}; + +export default CommonSnackbar; diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index fb7d8818..b80265e4 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -204,7 +204,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -216,7 +216,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > diff --git a/src/index.js b/src/index.js index ea25e57f..152d5f8d 100644 --- a/src/index.js +++ b/src/index.js @@ -114,6 +114,7 @@ import { formatJsonField } from "./helpers/jsonExt"; import { RIGHT_ROLE_SEARCH } from "./constants"; import { authMiddleware } from "./middlewares"; import RefreshAuthToken from "./components/RefreshAuthToken"; +import CommonSnackbar from "./components/generics/CommonSnakbar"; const ROUTE_ROLES = "roles"; const ROUTE_ROLE = "roles/role"; @@ -259,4 +260,5 @@ export { ConfirmDialog, useAuthentication, useBoolean, + CommonSnackbar }; From ffc93b821e4c5a0a92f08be65b27dab1356a7951 Mon Sep 17 00:00:00 2001 From: ankitkumar774 Date: Fri, 19 Jan 2024 10:46:35 +0530 Subject: [PATCH 050/111] get current username --- src/actions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/actions.js b/src/actions.js index b3086bfa..671cf23e 100644 --- a/src/actions.js +++ b/src/actions.js @@ -276,6 +276,7 @@ export function login(credentials) { await dispatch(refreshAuthToken()); } const action = await dispatch(loadUser()); + localStorage.setItem("userName", action?.payload?.username); localStorage.setItem("userLanguage", action?.payload?.i_user?.language); localStorage.setItem("userId", action?.payload?.id); return action.type !== "CORE_AUTH_ERR"; From 484bc8f550c115eda7fcdb6df9acf9b57e1f5ccc Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Thu, 25 Jan 2024 12:13:58 +0530 Subject: [PATCH 051/111] change style --- src/components/generics/Form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index b80265e4..5e45ff23 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -29,7 +29,7 @@ const styles = (theme) => ({ marginBottom: "70px", }, fabMargin: { - marginBottom: "140px", + marginBottom: "135px", }, fabPayMargin: { marginBottom: "200px", From 4511e0e26dbfbdda8f0786459bb0ad272af8830f Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 13 Feb 2024 17:25:18 +0530 Subject: [PATCH 052/111] add state in onChangeFilter --- src/components/generics/Searcher.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index 30747f56..1c862a19 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -85,7 +85,7 @@ class SelectionMenu extends Component { {entries.map((i, idx) => ( - + ))} {this.props.exportable && ( this.applyFilters()); + // console.log("this.props.updateIsVerifyInsuree", this.props.updateIsVerifyInsuree) + // this.setState({ filters }, (e) => this.applyFilters()); + this.setState({ filters }, () => { + if (this.props.updateIsVerifyInsuree) { + this.props.updateIsVerifyInsuree(false); // Update isVerifyInsuree in the parent component + this.applyFilters(); + } + this.applyFilters(); + }); }; _cacheAndApply = () => { From 6ae618089809e647832332ec82c357f81d51562e Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 5 Mar 2024 10:54:14 +0530 Subject: [PATCH 053/111] add button --- src/components/generics/Form.js | 111 ++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 41 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 5e45ff23..945fe683 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -110,6 +110,7 @@ class Form extends Component { paymentApprove, success, edited, + exceptionApprove, ...others } = this.props; let userId = localStorage.getItem("userId"); @@ -204,7 +205,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -216,7 +217,35 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + + ) : null} + {exceptionApprove ? ( + <> + {withTooltip( +
+ approveorreject({ ...this.props.edited, status: -1 })} + // disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + )} + {withTooltip( +
+ approveorreject({ ...this.props.edited, status: 5 })} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -229,9 +258,9 @@ class Form extends Component { this.props.edited?.biometricsStatus && this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( */} {title == "Insuree.title" && - this.props.edited?.biometricsStatus && - approverData == userId && - this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( + this.props.edited?.biometricsStatus && + approverData == userId && + this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( @@ -318,52 +347,52 @@ class Form extends Component { )} {!!this.props.paymentPrint ? withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {/* {(!!this.props.email && this.props.edited.email != "") ? */} {!!this.props.print && this.props.edited.email != "" ? withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) - : ""} - {!!this.props.email && this.props.edited.email != "" - ? withTooltip( -
+
+
emailButton(this.props.edited)} + onClick={(e) => printButton(this.props.edited)} > - + -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} + {!!this.props.email && this.props.edited.email != "" + ? withTooltip( +
+ emailButton(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && From b0b2d48242ac82036ca525ce417f1eb90ef87056 Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Wed, 6 Mar 2024 10:50:08 +0530 Subject: [PATCH 054/111] changed userID from reducer --- src/components/LogoutButton.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/LogoutButton.js b/src/components/LogoutButton.js index d48ae6f5..89fd2815 100644 --- a/src/components/LogoutButton.js +++ b/src/components/LogoutButton.js @@ -16,7 +16,8 @@ const useStyles = makeStyles((theme) => ({ const LogoutButton = () => { const history = useHistory(); const dispatch = useDispatch(); - const userid = localStorage.getItem("userId"); + // const userid = localStorage.getItem("userId"); + const userid = useSelector((store) => store.admin.user?.id); const onClick = async () => { const response = await dispatch(CheckAssignedProfile(userid)); if (!!response.payload.data.checkAssignedProfiles.status) { From e0d086d5248a0ab416c4dcf920ae7eaf3726f45a Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Wed, 6 Mar 2024 12:00:31 +0530 Subject: [PATCH 055/111] correction in logout --- src/components/LogoutButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/LogoutButton.js b/src/components/LogoutButton.js index 89fd2815..0a42979d 100644 --- a/src/components/LogoutButton.js +++ b/src/components/LogoutButton.js @@ -1,6 +1,6 @@ import React from "react"; import { makeStyles } from "@material-ui/core/styles"; -import { useDispatch } from "react-redux"; +import { useDispatch,useSelector } from "react-redux"; import { IconButton } from "@material-ui/core"; import { ExitToApp } from "@material-ui/icons"; import { CheckAssignedProfile, logout } from "../actions"; From 7fcac889c3476318e8018f7e86f865d5c6234c08 Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Wed, 6 Mar 2024 16:39:35 +0530 Subject: [PATCH 056/111] logout issue resolved --- README.md | 1 + src/components/LogoutButton.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d8b96cb..14d4b481 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ It is dedicated to be deployed as a module of [openimis-fe_js](https://github.co - `Searcher`: generic searcher page (with criteria form and result table) - `Form`: generic form. Manage dirty state, displays add/save button,... - `Table`: generic table. Headers (with -sort-actions), rows,... +- `CommonSnackbar`: generic snackbar. Display banner based on response ## Helpers diff --git a/src/components/LogoutButton.js b/src/components/LogoutButton.js index 0a42979d..eadc2cb4 100644 --- a/src/components/LogoutButton.js +++ b/src/components/LogoutButton.js @@ -16,10 +16,11 @@ const useStyles = makeStyles((theme) => ({ const LogoutButton = () => { const history = useHistory(); const dispatch = useDispatch(); - // const userid = localStorage.getItem("userId"); + const useridlocal = localStorage.getItem("userId"); const userid = useSelector((store) => store.admin.user?.id); + // console.log("userid",useSelector((store) => store.admin),'useridlocal',useridlocal); const onClick = async () => { - const response = await dispatch(CheckAssignedProfile(userid)); + const response = await dispatch(CheckAssignedProfile(useridlocal)); if (!!response.payload.data.checkAssignedProfiles.status) { await dispatch(logout()); history.push("/"); From f03129748ff5d542dc175528f6a01320512047aa Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:49:19 +0530 Subject: [PATCH 057/111] Form save button disable and enable --- src/components/generics/Form.js | 89 +++++++++++++++++---------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 945fe683..b7a91c6c 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -66,6 +66,9 @@ class Form extends Component { } else if (prevProps.update !== this.props.update) { this.setState({ saving: false }); } + if (prevProps.cancelSaveDisable !== this.props.cancelSaveDisable) { + this.setState({ saving: false }); + } } onEditedChanged = (data) => { @@ -205,7 +208,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -217,7 +220,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -233,7 +236,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -245,7 +248,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -258,9 +261,9 @@ class Form extends Component { this.props.edited?.biometricsStatus && this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( */} {title == "Insuree.title" && - this.props.edited?.biometricsStatus && - approverData == userId && - this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( + this.props.edited?.biometricsStatus && + approverData == userId && + this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( @@ -347,52 +350,52 @@ class Form extends Component { )} {!!this.props.paymentPrint ? withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {/* {(!!this.props.email && this.props.edited.email != "") ? */} {!!this.props.print && this.props.edited.email != "" ? withTooltip( -
-
+
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} + {!!this.props.email && this.props.edited.email != "" + ? withTooltip( +
printButton(this.props.edited)} + onClick={(e) => emailButton(this.props.edited)} > - + -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) - : ""} - {!!this.props.email && this.props.edited.email != "" - ? withTooltip( -
- emailButton(this.props.edited)} - > - - -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && From 704d41d1e485b66cd56a1ebb9402d294e2eee04a Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Thu, 4 Apr 2024 13:49:31 +0530 Subject: [PATCH 058/111] tooltip label changes --- src/components/generics/Form.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index b7a91c6c..a68ae985 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -213,7 +213,7 @@ class Form extends Component {
, - addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), )} {withTooltip(
@@ -225,7 +225,7 @@ class Form extends Component {
, - addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + addTooltip || formatMessage(this.props.intl, module, "approveTooltip"), )} ) : null} @@ -253,7 +253,7 @@ class Form extends Component {
, - addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + addTooltip || formatMessage(this.props.intl, module, "approveTooltip"), )} ) : null} @@ -317,7 +317,7 @@ class Form extends Component {
, - addTooltip || formatMessage(this.props.intl, module, "addTooltip"), + addTooltip || formatMessage(this.props.intl, module, "approveTooltip"), )} ) : null From cbbb81d44b762b0c0678481e53a6e853bb010e49 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 16 Apr 2024 13:30:08 +0530 Subject: [PATCH 059/111] update payment button --- src/components/generics/Form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index a68ae985..a37ebe6e 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -201,7 +201,7 @@ class Form extends Component { /> )} - {paymentApprove ? ( + {paymentApprove && !!canSave && !canSave() ? ( <> {withTooltip(
From 3fe91169e4fb08e5532a8d4d827f4f1cf6072531 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 16 Apr 2024 17:08:00 +0530 Subject: [PATCH 060/111] udate on form --- src/components/generics/Form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index a37ebe6e..a68ae985 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -201,7 +201,7 @@ class Form extends Component { /> )} - {paymentApprove && !!canSave && !canSave() ? ( + {paymentApprove ? ( <> {withTooltip(
From 30c0cb5ec484505badfc5ab83086d6a6ae0d393b Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Mon, 13 May 2024 12:55:08 +0530 Subject: [PATCH 061/111] add rework button --- src/components/generics/Form.js | 131 +++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 44 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index a68ae985..9a44fcbb 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -15,7 +15,7 @@ import _ from "lodash"; import CheckIcon from "@material-ui/icons/Check"; import CloseIcon from "@material-ui/icons/Close"; import SendIcon from "@material-ui/icons/Send"; - +import KeyboardReturnIcon from '@material-ui/icons/KeyboardReturn'; const styles = (theme) => ({ paper: theme.paper.paper, paperHeader: theme.paper.header, @@ -28,6 +28,13 @@ const styles = (theme) => ({ zIndex: 2000, marginBottom: "70px", }, + fabAboveRework: { + position: "fixed", + bottom: 80, + right: 8, + zIndex: 2000, + marginBottom: "80px", + }, fabMargin: { marginBottom: "135px", }, @@ -44,6 +51,11 @@ const styles = (theme) => ({ border: "2px solid #FF0000", // Your desired border color color: "#FF0000", // Your desired text/icon color }, + customFabRework: { + background: "orange", + border: "2px solid orange", // Your desired border color + color: "#FFF", // Your desired text/icon color + }, }); class Form extends Component { @@ -113,6 +125,9 @@ class Form extends Component { paymentApprove, success, edited, + rework, + actionRework, + reworkRequest, exceptionApprove, ...others } = this.props; @@ -208,7 +223,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -220,13 +235,41 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} >
, addTooltip || formatMessage(this.props.intl, module, "approveTooltip"), )} + {/* {withTooltip( +
+ rework({ ...this.props.edited, status: 3 })} + // disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), + )} */} + + ) : null} + {paymentApprove && actionRework ? ( + <> + {withTooltip( +
+ rework({ ...this.props.edited, status: 5 })} + // disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), + )} ) : null} {exceptionApprove ? ( @@ -236,7 +279,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -248,7 +291,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -261,9 +304,9 @@ class Form extends Component { this.props.edited?.biometricsStatus && this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( */} {title == "Insuree.title" && - this.props.edited?.biometricsStatus && - approverData == userId && - this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( + this.props.edited?.biometricsStatus && + approverData == userId && + this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( @@ -350,52 +393,52 @@ class Form extends Component { )} {!!this.props.paymentPrint ? withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {/* {(!!this.props.email && this.props.edited.email != "") ? */} {!!this.props.print && this.props.edited.email != "" ? withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) - : ""} - {!!this.props.email && this.props.edited.email != "" - ? withTooltip( -
+
+
emailButton(this.props.edited)} + onClick={(e) => printButton(this.props.edited)} > - + -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} + {!!this.props.email && this.props.edited.email != "" + ? withTooltip( +
+ emailButton(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && From 78e4694ab2e469e3e2a03aa209183fc34e11e493 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 21 May 2024 10:30:54 +0530 Subject: [PATCH 062/111] add paid button --- src/components/generics/Form.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 9a44fcbb..df0cf4ed 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -16,6 +16,8 @@ import CheckIcon from "@material-ui/icons/Check"; import CloseIcon from "@material-ui/icons/Close"; import SendIcon from "@material-ui/icons/Send"; import KeyboardReturnIcon from '@material-ui/icons/KeyboardReturn'; +import AccountBalanceIcon from '@material-ui/icons/AccountBalance'; + const styles = (theme) => ({ paper: theme.paper.paper, paperHeader: theme.paper.header, @@ -129,6 +131,8 @@ class Form extends Component { actionRework, reworkRequest, exceptionApprove, + showPaidButton, + paid, ...others } = this.props; let userId = localStorage.getItem("userId"); @@ -272,6 +276,22 @@ class Form extends Component { )} ) : null} + {showPaidButton ? ( + <> + {withTooltip( +
+ paid({ ...this.props.edited, status: 5 })} + // disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + // addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), + )} + + ) : null} {exceptionApprove ? ( <> {withTooltip( From 6911d4f2842294c5a23dc3e66ea6510aae7cdc04 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Sat, 25 May 2024 14:23:34 +0530 Subject: [PATCH 063/111] add rework tooltip --- src/components/generics/Form.js | 2 +- src/helpers/i18n.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index df0cf4ed..5653ef15 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -272,7 +272,7 @@ class Form extends Component {
, - addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), + addTooltip || formatMessage(this.props.intl, module, "reworkTooltip"), )} ) : null} diff --git a/src/helpers/i18n.js b/src/helpers/i18n.js index 01b77765..1bbc2d54 100644 --- a/src/helpers/i18n.js +++ b/src/helpers/i18n.js @@ -39,7 +39,7 @@ export function toISODate(d) { } export function withTooltip(c, t) { - return !!t ? {c} : c; + return !!t ? {c} : c; } export function useTranslations(moduleName, modulesManager) { From a3f8bcae7067e2e96f40f2593b2d935a5a9106ee Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Mon, 10 Jun 2024 16:35:03 +0530 Subject: [PATCH 064/111] add status check --- src/components/generics/Form.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 5653ef15..ccf19921 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -133,6 +133,7 @@ class Form extends Component { exceptionApprove, showPaidButton, paid, + claimStatus, ...others } = this.props; let userId = localStorage.getItem("userId"); @@ -159,11 +160,17 @@ class Form extends Component { )} + {!!actions && ( + {claimStatus && + + {formatMessage(this.props.intl, "claim", `claimStatus.${claimStatus}`)} + + } {actions.map((a, idx) => { if (!!a.onlyIfDirty && !this.state.dirty) return null; if (!!a.onlyIfNotDirty && !!this.state.dirty) return null; From 1b552787bfc23e6a11f9c8919582db635d0f8ea5 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Fri, 14 Jun 2024 11:08:39 +0530 Subject: [PATCH 065/111] add XAF and Date Picker changes --- src/components/inputs/NumberInput.js | 3 +- src/components/inputs/TextInput.js | 10 +++++-- src/pickers/AdDatePicker.js | 43 +++++++++++++++++----------- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/components/inputs/NumberInput.js b/src/components/inputs/NumberInput.js index bfa9fa56..746332b2 100644 --- a/src/components/inputs/NumberInput.js +++ b/src/components/inputs/NumberInput.js @@ -29,7 +29,7 @@ class NumberInput extends Component { this.setState({ isEdited: false }); }; render() { - const { intl, module = "core", min = null, max = null, value, error, displayZero = false, displayNa = false, decimal = false, ...others } = this.props; + const { intl, module = "core", min = null, max = null, value, error, displayZero = false, displayNa = false, decimal = false,isNumber, ...others } = this.props; let inputProps = { ...this.props.inputProps, type: "number" }; let err = error; @@ -60,6 +60,7 @@ class NumberInput extends Component { formatInput={(v) =>this.formatInput(v, displayZero, displayNa, decimal)} onFocus={() => this.setState({isEdited: true})} onBlur={() => this.handleNaBlur()} + isNumber={isNumber} /> ); } diff --git a/src/components/inputs/TextInput.js b/src/components/inputs/TextInput.js index 6c3ce254..b70d04d8 100644 --- a/src/components/inputs/TextInput.js +++ b/src/components/inputs/TextInput.js @@ -1,9 +1,9 @@ import React, { Component } from "react"; import { withTheme, withStyles } from "@material-ui/core/styles"; import { injectIntl } from "react-intl"; -import { TextField } from "@material-ui/core"; +import { TextField, InputAdornment } from "@material-ui/core"; import { formatMessage } from "../../helpers/i18n"; - +import { AttachMoney } from "@material-ui/icons"; const styles = (theme) => ({ label: { color: theme.palette.text.primary, @@ -72,6 +72,7 @@ class TextInput extends Component { helperText, type, capitalize, + isNumber, ...others } = this.props; const inputClass = readOnly ? classes.disabledInput : ""; @@ -99,6 +100,11 @@ class TextInput extends Component { style: { color: !!readOnly && "#7f7f7f", }, + startAdornment: ( + + {isNumber && XAF} + + ), inputProps: { style: { textTransform: !!capitalize && "capitalize", diff --git a/src/pickers/AdDatePicker.js b/src/pickers/AdDatePicker.js index f00f3d57..d8d1bfb8 100644 --- a/src/pickers/AdDatePicker.js +++ b/src/pickers/AdDatePicker.js @@ -2,7 +2,7 @@ import React, { Component } from "react"; import moment from "moment"; import { withTheme, withStyles } from "@material-ui/core/styles"; import { injectIntl } from "react-intl"; -import { FormControl } from "@material-ui/core"; +import { FormControl, TextField } from "@material-ui/core"; import { DatePicker as MUIDatePicker } from "@material-ui/pickers"; import { formatMessage, toISODate } from "../helpers/i18n"; import MomentUtils from "@date-io/moment"; @@ -27,14 +27,14 @@ class AdDatePicker extends Component { this.setState((state, props) => ({ value: props.value || null })); } - componentDidUpdate(prevState, prevProps, snapshot) { - if (prevState.value !== this.props.value) { - this.setState((state, props) => ({ value: fromISODate(props.value) })); + componentDidUpdate(prevProps) { + if (prevProps.value !== this.props.value) { + this.setState({ value: fromISODate(this.props.value) }); } } dateChange = (d) => { - this.setState({ value: d }, (i) => this.props.onChange(toISODate(d))); + this.setState({ value: d }, () => this.props.onChange(toISODate(d))); }; render() { @@ -50,42 +50,51 @@ class AdDatePicker extends Component { format = "DD-MM-YYYY", reset, monthtrue, + daytrue, ...otherProps } = this.props; let userlang = localStorage.getItem("userLanguage"); let locale = userlang === "fr" ? "fr" : "en"; moment.locale(locale); + + const displayFormat = daytrue ? 'DD' : format; + return ( ( + + )} /> @@ -93,4 +102,4 @@ class AdDatePicker extends Component { } } -export default injectIntl(withTheme(withStyles(styles)(AdDatePicker))); +export default injectIntl(withTheme(withStyles(styles)(AdDatePicker))); \ No newline at end of file From 95a09c20ce0b4f9d8febd46276a86d907f08a14c Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Mon, 24 Jun 2024 17:01:27 +0530 Subject: [PATCH 066/111] update localization --- src/components/generics/CommonSnakbar.js | 8 +++++--- src/translations/en.json | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/generics/CommonSnakbar.js b/src/components/generics/CommonSnakbar.js index 943e30a3..45dc7eff 100644 --- a/src/components/generics/CommonSnakbar.js +++ b/src/components/generics/CommonSnakbar.js @@ -9,7 +9,7 @@ import WarningIcon from "@material-ui/icons/Warning"; import InfoIcon from "@material-ui/icons/Info"; import CheckCircleIcon from "@material-ui/icons/CheckCircle"; import { makeStyles } from "@material-ui/core/styles"; - +import { formatMessage } from "@openimis/fe-core"; const useStyles = makeStyles((theme) => ({ snackbar: { marginRight: "50px", @@ -32,7 +32,7 @@ const useStyles = makeStyles((theme) => ({ }, })); -const CommonSnackbar = ({ open, onClose, message, severity, copyText = "" }) => { +const CommonSnackbar = ({ intl,open, onClose, message, severity, copyText = "" }) => { const [isCopied, setIsCopied] = useState(false); const classes = useStyles(); @@ -112,7 +112,9 @@ const CommonSnackbar = ({ open, onClose, message, severity, copyText = "" }) => - {isCopied ? "Copied!" : "Copy"} + {/* {isCopied ? "Copied!" : "Copy"} */} + {isCopied ? formatMessage(intl, "core", "common.Copied") : formatMessage(intl, "core", "common.Copy")} +
)} diff --git a/src/translations/en.json b/src/translations/en.json index 7f2b403e..1622ebff 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -69,5 +69,7 @@ "core.datePicker.ok":"OK", "core.datePicker.cancel":"CANCEL", "core.datePicker.clear":"CLEAR", - "core.common.errorBoundary":"An error was not properly caught. Refer to console log." + "core.common.errorBoundary":"An error was not properly caught. Refer to console log.", + "core.common.Copied":"Copied!", + "core.common.Copy":"Copy" } From 6cced9774ee3448ecaae61dc9ca0465cc09a2ec2 Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Mon, 24 Jun 2024 17:12:39 +0530 Subject: [PATCH 067/111] change in form for payment approval --- src/components/generics/Form.js | 108 ++++++++++++++++---------------- 1 file changed, 55 insertions(+), 53 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index ccf19921..e4c937c4 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -15,8 +15,8 @@ import _ from "lodash"; import CheckIcon from "@material-ui/icons/Check"; import CloseIcon from "@material-ui/icons/Close"; import SendIcon from "@material-ui/icons/Send"; -import KeyboardReturnIcon from '@material-ui/icons/KeyboardReturn'; -import AccountBalanceIcon from '@material-ui/icons/AccountBalance'; +import KeyboardReturnIcon from "@material-ui/icons/KeyboardReturn"; +import AccountBalanceIcon from "@material-ui/icons/AccountBalance"; const styles = (theme) => ({ paper: theme.paper.paper, @@ -160,17 +160,18 @@ class Form extends Component {
)} -
{!!actions && ( - {claimStatus && - - {formatMessage(this.props.intl, "claim", `claimStatus.${claimStatus}`)} - - } + {claimStatus && ( + + + {formatMessage(this.props.intl, "claim", `claimStatus.${claimStatus}`)} + + + )} {actions.map((a, idx) => { if (!!a.onlyIfDirty && !this.state.dirty) return null; if (!!a.onlyIfNotDirty && !!this.state.dirty) return null; @@ -234,7 +235,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -246,7 +247,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -274,7 +275,7 @@ class Form extends Component { rework({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -290,7 +291,7 @@ class Form extends Component { paid({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -306,7 +307,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -318,7 +319,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -331,9 +332,9 @@ class Form extends Component { this.props.edited?.biometricsStatus && this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( */} {title == "Insuree.title" && - this.props.edited?.biometricsStatus && - approverData == userId && - this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( + this.props.edited?.biometricsStatus && + approverData == userId && + this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( @@ -406,6 +407,7 @@ class Form extends Component { )} {(!!this.state.dirty || !!openDirty) && !!save && + !paymentApprove && withTooltip(
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {/* {(!!this.props.email && this.props.edited.email != "") ? */} {!!this.props.print && this.props.edited.email != "" ? withTooltip( -
-
+
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} + {!!this.props.email && this.props.edited.email != "" + ? withTooltip( +
printButton(this.props.edited)} + onClick={(e) => emailButton(this.props.edited)} > - + -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) - : ""} - {!!this.props.email && this.props.edited.email != "" - ? withTooltip( -
- emailButton(this.props.edited)} - > - - -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && From 37a5b867c3c22391c8b473ffb7b6b5591f9c0426 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 23 Jul 2024 16:09:05 +0530 Subject: [PATCH 068/111] udate form --- src/components/generics/Form.js | 115 +++++++++++++++++++------------- 1 file changed, 69 insertions(+), 46 deletions(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index e4c937c4..e6b0a3ec 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -17,7 +17,7 @@ import CloseIcon from "@material-ui/icons/Close"; import SendIcon from "@material-ui/icons/Send"; import KeyboardReturnIcon from "@material-ui/icons/KeyboardReturn"; import AccountBalanceIcon from "@material-ui/icons/AccountBalance"; - +import OpenInBrowserIcon from "@material-ui/icons/OpenInBrowser"; const styles = (theme) => ({ paper: theme.paper.paper, paperHeader: theme.paper.header, @@ -58,6 +58,11 @@ const styles = (theme) => ({ border: "2px solid orange", // Your desired border color color: "#FFF", // Your desired text/icon color }, + submitFabRework: { + background: "green", + border: "2px solid green", // Your desired border color + color: "#FFF", // Your desired text/icon color + }, }); class Form extends Component { @@ -134,6 +139,8 @@ class Form extends Component { showPaidButton, paid, claimStatus, + showSubmitButton, + submitted, ...others } = this.props; let userId = localStorage.getItem("userId"); @@ -235,7 +242,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -247,7 +254,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -275,7 +282,7 @@ class Form extends Component { rework({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -291,7 +298,7 @@ class Form extends Component { paid({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -307,7 +314,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: -1 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -319,7 +326,7 @@ class Form extends Component { approveorreject({ ...this.props.edited, status: 5 })} - // disabled={!!this.state.saving || (!!canSave && !canSave())} + // disabled={!!this.state.saving || (!!canSave && !canSave())} > @@ -332,9 +339,9 @@ class Form extends Component { this.props.edited?.biometricsStatus && this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( */} {title == "Insuree.title" && - this.props.edited?.biometricsStatus && - approverData == userId && - this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( + this.props.edited?.biometricsStatus && + approverData == userId && + this.props.edited?.status == "WAITING_FOR_APPROVAL" ? ( hasReject && this.props?.edited?.status !== "REJECTED" && this.props?.edited?.status !== "REWORK" ? ( <> {withTooltip( @@ -422,52 +429,52 @@ class Form extends Component { )} {!!this.props.paymentPrint ? withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
+ printButton(this.props.edited)} + > + + +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {/* {(!!this.props.email && this.props.edited.email != "") ? */} {!!this.props.print && this.props.edited.email != "" ? withTooltip( -
-
- printButton(this.props.edited)} - > - - -
-
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) - : ""} - {!!this.props.email && this.props.edited.email != "" - ? withTooltip( -
+
+
emailButton(this.props.edited)} + onClick={(e) => printButton(this.props.edited)} > - + -
, - // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), - ) +
+
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) + : ""} + {!!this.props.email && this.props.edited.email != "" + ? withTooltip( +
+ emailButton(this.props.edited)} + > + + +
, + // saveTooltip || formatMessage(this.props.intl, module, "saveTooltip"), + ) : ""} {!this.state.dirty && !!fab && @@ -479,6 +486,22 @@ class Form extends Component { , fabTooltip, )} + {showSubmitButton ? ( + <> + {withTooltip( +
+ submitted({ ...this.props.edited, status: 5 })} + // disabled={!!this.state.saving || (!!canSave && !canSave())} + > + + +
, + // addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), + )} + + ) : null} ); } From eb0fbdfd30c99576a8e54d597769885e61033918 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 23 Jul 2024 06:57:02 +0530 Subject: [PATCH 069/111] change button style --- src/components/generics/Form.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index e6b0a3ec..7cfd8a12 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -63,6 +63,15 @@ const styles = (theme) => ({ border: "2px solid green", // Your desired border color color: "#FFF", // Your desired text/icon color }, + fabSubmitRework: { + position: "fixed", + bottom: 1, + right: 8, + zIndex: 2000, + }, + fabSubmitMargin: { + marginBottom: "80px", + }, }); class Form extends Component { @@ -489,7 +498,7 @@ class Form extends Component { {showSubmitButton ? ( <> {withTooltip( -
+
submitted({ ...this.props.edited, status: 5 })} From 0d0dc0a3eadc303d8d5704dc83ad20b7e04661a5 Mon Sep 17 00:00:00 2001 From: RishavWtt Date: Tue, 23 Jul 2024 22:34:06 +0530 Subject: [PATCH 070/111] update form --- src/components/generics/Form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/generics/Form.js b/src/components/generics/Form.js index 7cfd8a12..029f2226 100644 --- a/src/components/generics/Form.js +++ b/src/components/generics/Form.js @@ -507,7 +507,7 @@ class Form extends Component {
, - // addTooltip || formatMessage(this.props.intl, module, "rejectTooltip"), + addTooltip || formatMessage(this.props.intl, module, "Submit"), )} ) : null} From 181cc39b3bd62a642b7f0bfcb8b3926fa2825b88 Mon Sep 17 00:00:00 2001 From: Rishav Johari <101561606+RishavWtt@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:12:46 +0530 Subject: [PATCH 071/111] add hfid in localstorage --- src/actions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/actions.js b/src/actions.js index 671cf23e..6379e6fe 100644 --- a/src/actions.js +++ b/src/actions.js @@ -279,6 +279,7 @@ export function login(credentials) { localStorage.setItem("userName", action?.payload?.username); localStorage.setItem("userLanguage", action?.payload?.i_user?.language); localStorage.setItem("userId", action?.payload?.id); + localStorage.setItem("HfId",action?.payload?.i_user?.health_facility_id) return action.type !== "CORE_AUTH_ERR"; }; } From f1dfadbe60a40ea7a8cb06169b092cdaa0857d39 Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:34:58 +0530 Subject: [PATCH 072/111] notification logic on frontend --- src/actions.js | 53 ++++++ src/components/RequireAuth.js | 37 ++++- src/components/dialogs/NotificationDialog.js | 161 +++++++++++++++++++ src/reducer.js | 18 +++ src/translations/en.json | 15 +- 5 files changed, 273 insertions(+), 11 deletions(-) create mode 100644 src/components/dialogs/NotificationDialog.js diff --git a/src/actions.js b/src/actions.js index 671cf23e..dbf7dc37 100644 --- a/src/actions.js +++ b/src/actions.js @@ -8,6 +8,7 @@ import { formatGQLString, formatMutation, formatServerError, + decodeId, } from "./helpers/api"; const ROLE_FULL_PROJECTION = () => [ @@ -505,3 +506,55 @@ export function clearCurrentPaginationPage() { dispatch({ type: "CORE_PAGINATION_PAGE_CLEAR" }); }; } + +export function fetchNotification(userID) { + return graphql( + ` query CamuNotifications { + camuNotifications(first: 10, user_Id: "${userID}") { + totalCount + edgeCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + edges { + node { + id + title + module + message + isRead + createdAt + redirectUrl + } + } + } + } + `, + "CORE_NOTIFICATION_LIST", + ); +} + +function formatNotificationGQL(data) { + + return ` + ${!!data.userId ? `userId: "${data.userId}"` : ""} + ${!!data.readAll ? `readAll: ${data.readAll}` : ""} + ${!!data.id ? `notificationId: "${decodeId(data.id)}"` : ""} + `; +} + +export function markNotificationAsRead(data, clientMutationLabel) { + let mutation = `mutation MarkNotificationAsRead { + markNotificationAsRead(${formatNotificationGQL(data)}) { + success + } +}`; + // let mutation = formatMutation("markNotificationAsRead ", formatNotificationGQL(data), clientMutationLabel); + var requestedDateTime = new Date(); + return graphql(mutation, ["CORE_ROLE_MUTATION_REQ", "CORE_CREATE_NOTIFICATION_RESP", "CORE_ROLE_MUTATION_ERR"], { + clientMutationLabel, + }); +} diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index cbc2d2d5..ca341fb4 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -26,9 +26,10 @@ import { useBoolean, useAuthentication } from "../helpers/hooks"; import { useGraphqlQuery } from "@openimis/fe-core"; import { formatMessageWithValues, withModulesManager, withHistory, historyPush } from "@openimis/fe-core"; import NotificationsIcon from "@material-ui/icons/Notifications"; -import { useDispatch } from "react-redux"; +import { useDispatch,useSelector } from "react-redux"; import { useIdleTimer } from "react-idle-timer/dist/index.legacy.cjs.js"; // otherwise not building: https://github.com/SupremeTechnopriest/react-idle-timer/issues/350 import { CheckAssignedProfile, logout } from "../actions"; +import NotificationDialog from "./dialogs/NotificationDialog"; export const APP_BAR_CONTRIBUTION_KEY = "core.AppBar"; export const MAIN_MENU_CONTRIBUTION_KEY = "core.MainMenu"; @@ -181,6 +182,7 @@ const RequireAuth = (props) => { const { children, logo, redirectTo, ...others } = props; const [isOpen, setOpen] = useBoolean(); const [isDrawerOpen, setDrawerOpen] = useBoolean(); + const [anchorEl, setAnchorEl] = useState(null); const theme = useTheme(); const classes = useStyles(); const modulesManager = useModulesManager(); @@ -202,12 +204,28 @@ const RequireAuth = (props) => { dispatch({ type: "INSUREE_COUNT_RESP", payload: data }); } }, [data]); - const bellIcon = () => { - if (data?.approverFamiliesCount?.approverFamiliesCount > 0) { - historyPush(modulesManager, props.history, "insuree.route.pendingApproval"); + + const getNotification=useSelector((store)=>store.core) + console.log('getNotification',getNotification); + + const bellIcon = (event) => { + if (anchorEl) { + setAnchorEl(null); // Close the dialog if it's already open + } else { + setAnchorEl(event.currentTarget); // Open the dialog if it's closed } + // if (data?.approverFamiliesCount?.approverFamiliesCount > 0) { + // historyPush(modulesManager, props.history, "insuree.route.pendingApproval"); + // } + }; + + const handleClose = () => { + setAnchorEl(null); }; + const open = Boolean(anchorEl); + const id = open ? 'notification-popover' : undefined; + const isAppBarMenu = useMemo(() => theme.menu.variant.toUpperCase() === "APPBAR", [theme.menu.variant]); const idleTimeSet = 30 * 60 * 1000; console.log("process.env.REACT_APP_IDLE_LOGOUT_TIME", Math.floor(process.env.REACT_APP_IDLE_LOGOUT_TIME)); @@ -275,7 +293,7 @@ const RequireAuth = (props) => {
-
{data?.approverFamiliesCount?.approverFamiliesCount}
+
{getNotification?.notificationListTotalCount}
@@ -313,6 +331,15 @@ const RequireAuth = (props) => { > {children} + ); }; diff --git a/src/components/dialogs/NotificationDialog.js b/src/components/dialogs/NotificationDialog.js new file mode 100644 index 00000000..1cfa17b6 --- /dev/null +++ b/src/components/dialogs/NotificationDialog.js @@ -0,0 +1,161 @@ +import React, { useState, useEffect } from "react"; +import { + IconButton, + Popover, + List, + ListItem, + ListItemText, + ListItemIcon, + Typography, + Divider, + Button, +} from "@material-ui/core"; +import CheckCircleIcon from "@material-ui/icons/CheckCircle"; +import { makeStyles } from "@material-ui/core/styles"; +import { useDispatch,useSelector } from "react-redux"; +import { fetchNotification, markNotificationAsRead } from "../../actions"; +import { historyPush, useHistory } from "../../helpers/history"; +import { useTranslations, formatMessage } from "../../helpers/i18n"; +import { useIntl } from "react-intl"; +import { parseData } from "../../helpers/api"; + +const useStyles = makeStyles((theme) => ({ + popover: { + position: "relative", + "&::before": { + content: '""', + position: "absolute", + top: -8, + left: "calc(50% - 8px)", // Center the arrow horizontally + width: 0, + height: 0, + borderLeft: "8px solid transparent", + borderRight: "8px solid transparent", + borderBottom: `8px solid ${theme.palette.background.paper}`, + zIndex: 1, + }, + }, + arrow: { + position: "absolute", + top: "-8px", + left: "calc(50% - 8px)", + width: 0, + height: 0, + borderLeft: "8px solid transparent", + borderRight: "8px solid transparent", + borderBottom: `8px solid ${theme.palette.background.paper}`, + zIndex: 1, + }, + clearAllButton: { + padding: 0, + minHeight: "auto", + minWidth: "auto", + color: theme.palette.primary.main, + }, +})); + +const NotificationDialog = ({ anchorEl, onClose, open, id, notificationData, modulesManager }) => { + const [notifications, setNotifications] = useState([]); + const intl = useIntl(); + const { formatDateFromISO } = useTranslations("core", modulesManager); + const classes = useStyles(); + const dispatch = useDispatch(); + const history = useHistory(); + const userid = localStorage.getItem("userId"); + const userLanguage = localStorage.getItem("userLanguage"); + const checkRes=useSelector((store)=>store.core) + useEffect(() => { + // if (open) { + dispatch(fetchNotification(userid)); + // } + }, [open]); + + useEffect(() => { + if (notificationData) { + setNotifications(notificationData); + } + }, [notificationData]); + + const handleClearAll = () => { + const res=dispatch(markNotificationAsRead({ readAll:true, userId: userid }, "label")); + if(!!res){ + dispatch(fetchNotification(userid)); + // setNotifications([]); + } + }; + + const handleListItemClick = (notification) => { + if (!!notification.redirectUrl) { + history.push(notification.redirectUrl); + const res=dispatch(markNotificationAsRead({ ...notification, userId: userid }, "label")); + if(!!res){ + dispatch(fetchNotification(userid)); + } + onClose(); + } + }; + + const getNotificationMessage = (message) => { + try { + const parsedMessage = JSON.parse(message); + return parsedMessage[userLanguage] || parsedMessage["en"]; + } catch (error) { + console.error("Failed to parse notification message:", error); + return message; // Fallback to the original message if parsing fails + } +}; + + return ( +
+ + {/*
*/} +
+ {formatMessage(intl, "core", "title")} + +
+ + + {notifications.length > 0 ? ( + notifications.map((notification, index) => ( + + {/* */} + handleListItemClick(notification)}> + + + + + + {index < notifications.length - 1 && } + + )) + ) : ( + + {formatMessage(intl, "core", "emptyNotification")} + + )} + +
+
+ ); +}; + +export default NotificationDialog; diff --git a/src/reducer.js b/src/reducer.js index 5598c3ea..9ce6ef17 100644 --- a/src/reducer.js +++ b/src/reducer.js @@ -44,6 +44,11 @@ function reducer( beforeCursor: null, module: null, assigned: null, + fetchingNotificationList: false, + fetchedNotificationList: false, + notificationList: null, + notificationListTotalCount: null, + errorNotificationList: null, }, action, ) { @@ -310,10 +315,23 @@ function reducer( }, }, }; + case "CORE_NOTIFICATION_LIST_RESP": + return { + ...state, + fetchingNotificationList: false, + fetchedNotificationList: true, + notificationList: parseData(action.payload.data.camuNotifications), + notificationListTotalCount: !!action.payload.data.camuNotifications + ? action.payload.data.camuNotifications.totalCount + : null, + errorNotificationList: formatGraphQLError(action.payload), + }; case "CORE_ROLE_MUTATION_REQ": return dispatchMutationReq(state, action); case "CORE_ROLE_MUTATION_ERR": return dispatchMutationErr(state, action); + case "CORE_CREATE_NOTIFICATION_RESP": + return dispatchMutationResp(state, "markNotificationAsRead", action); case "CORE_CREATE_ROLE_RESP": return dispatchMutationResp(state, "createRole", action); case "CORE_UPDATE_ROLE_RESP": diff --git a/src/translations/en.json b/src/translations/en.json index 1622ebff..7b31263f 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -66,10 +66,13 @@ "core.ForgotPasswordPage.recoverTitle": "Récupérer votre compte", "core.ForgotPasswordPage.explanationMessage": "Saisissez votre nom d'utilisateur pour pouvoir récupérer votre compte. Un e-mail contenant les instructions sera envoyé à votre adresse e-mail.", "core.ForgotPasswordPage.contactAdministrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur.", - "core.datePicker.ok":"OK", - "core.datePicker.cancel":"CANCEL", - "core.datePicker.clear":"CLEAR", - "core.common.errorBoundary":"An error was not properly caught. Refer to console log.", - "core.common.Copied":"Copied!", - "core.common.Copy":"Copy" + "core.datePicker.ok": "OK", + "core.datePicker.cancel": "CANCEL", + "core.datePicker.clear": "CLEAR", + "core.common.errorBoundary": "An error was not properly caught. Refer to console log.", + "core.common.Copied": "Copied!", + "core.common.Copy": "Copy", + "core.title": "Notifications", + "core.clearAll": "Clear All", + "core.emptyNotification": "No Notification" } From ca581a2b72da66e9a84932c025117a49ee459685 Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:28:46 +0530 Subject: [PATCH 073/111] notification on scroll call API --- src/actions.js | 4 +- src/components/dialogs/NotificationDialog.js | 50 ++++++++++++-------- src/components/generics/Table.js | 2 +- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/actions.js b/src/actions.js index 0d3a51ca..b48e705e 100644 --- a/src/actions.js +++ b/src/actions.js @@ -508,10 +508,10 @@ export function clearCurrentPaginationPage() { }; } -export function fetchNotification(userID) { +export function fetchNotification(userID,first=10) { return graphql( ` query CamuNotifications { - camuNotifications(first: 10, user_Id: "${userID}") { + camuNotifications(first: ${first}, user_Id: "${userID}") { totalCount edgeCount pageInfo { diff --git a/src/components/dialogs/NotificationDialog.js b/src/components/dialogs/NotificationDialog.js index 1cfa17b6..cfa649c3 100644 --- a/src/components/dialogs/NotificationDialog.js +++ b/src/components/dialogs/NotificationDialog.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect,useRef } from "react"; import { IconButton, Popover, @@ -12,7 +12,7 @@ import { } from "@material-ui/core"; import CheckCircleIcon from "@material-ui/icons/CheckCircle"; import { makeStyles } from "@material-ui/core/styles"; -import { useDispatch,useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { fetchNotification, markNotificationAsRead } from "../../actions"; import { historyPush, useHistory } from "../../helpers/history"; import { useTranslations, formatMessage } from "../../helpers/i18n"; @@ -56,6 +56,7 @@ const useStyles = makeStyles((theme) => ({ const NotificationDialog = ({ anchorEl, onClose, open, id, notificationData, modulesManager }) => { const [notifications, setNotifications] = useState([]); + const [hasFetchedMore, setHasFetchedMore] = useState(false); const intl = useIntl(); const { formatDateFromISO } = useTranslations("core", modulesManager); const classes = useStyles(); @@ -63,7 +64,9 @@ const NotificationDialog = ({ anchorEl, onClose, open, id, notificationData, mod const history = useHistory(); const userid = localStorage.getItem("userId"); const userLanguage = localStorage.getItem("userLanguage"); - const checkRes=useSelector((store)=>store.core) + const checkRes = useSelector((store) => store.core); + const listRef = useRef(null); + useEffect(() => { // if (open) { dispatch(fetchNotification(userid)); @@ -77,33 +80,42 @@ const NotificationDialog = ({ anchorEl, onClose, open, id, notificationData, mod }, [notificationData]); const handleClearAll = () => { - const res=dispatch(markNotificationAsRead({ readAll:true, userId: userid }, "label")); - if(!!res){ + const res = dispatch(markNotificationAsRead({ readAll: true, userId: userid }, "label")); + if (!!res) { dispatch(fetchNotification(userid)); - // setNotifications([]); - } + setNotifications([]); + } }; const handleListItemClick = (notification) => { if (!!notification.redirectUrl) { history.push(notification.redirectUrl); - const res=dispatch(markNotificationAsRead({ ...notification, userId: userid }, "label")); - if(!!res){ + const res = dispatch(markNotificationAsRead({ ...notification, userId: userid }, "label")); + if (!!res) { dispatch(fetchNotification(userid)); - } + } onClose(); } }; const getNotificationMessage = (message) => { - try { - const parsedMessage = JSON.parse(message); - return parsedMessage[userLanguage] || parsedMessage["en"]; - } catch (error) { - console.error("Failed to parse notification message:", error); - return message; // Fallback to the original message if parsing fails - } -}; + try { + const parsedMessage = JSON.parse(message); + return parsedMessage[userLanguage] || parsedMessage["en"]; + } catch (error) { + console.error("Failed to parse notification message:", error); + return message; // Fallback to the original message if parsing fails + } + }; + + const handleScroll = () => { + const threshold = 1; + const isBottom = listRef.current.scrollHeight - listRef.current.scrollTop <= listRef.current.clientHeight + threshold; + if (isBottom && !hasFetchedMore) { + dispatch(fetchNotification(userid,checkRes.notificationListTotalCount)); + setHasFetchedMore(true); // Set to true to prevent further API calls + } + }; return (
@@ -130,7 +142,7 @@ const NotificationDialog = ({ anchorEl, onClose, open, id, notificationData, mod
- + {notifications.length > 0 ? ( notifications.map((notification, index) => ( diff --git a/src/components/generics/Table.js b/src/components/generics/Table.js index 0b9c501a..73fa1ecb 100644 --- a/src/components/generics/Table.js +++ b/src/components/generics/Table.js @@ -323,7 +323,7 @@ class Table extends Component { {(fetching || error) && ( - {" "} + {/* We do not want to display the spinner with the empty table */} )} From d30ca4954b892ce2668243766aaa5fb0be4acaaa Mon Sep 17 00:00:00 2001 From: richa-rathoreee Date: Fri, 23 Aug 2024 11:27:07 +0530 Subject: [PATCH 074/111] changes --- src/translations/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/translations/en.json b/src/translations/en.json index 1622ebff..f9459e60 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -71,5 +71,6 @@ "core.datePicker.clear":"CLEAR", "core.common.errorBoundary":"An error was not properly caught. Refer to console log.", "core.common.Copied":"Copied!", - "core.common.Copy":"Copy" + "core.common.Copy":"Copy", + "core.bank.label": "Bank" } From 44741a4041492a149c116f17eb05b10d019792c6 Mon Sep 17 00:00:00 2001 From: Rishav Johari <101561606+RishavWtt@users.noreply.github.com> Date: Thu, 29 Aug 2024 19:12:54 +0530 Subject: [PATCH 075/111] add check for fosacategory limit --- src/components/inputs/TextInput.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/inputs/TextInput.js b/src/components/inputs/TextInput.js index b70d04d8..6cc2fb75 100644 --- a/src/components/inputs/TextInput.js +++ b/src/components/inputs/TextInput.js @@ -53,6 +53,9 @@ class TextInput extends Component { if (this.props.formatInput) { value = this.props.formatInput(value); } + if (this.props.CapitalThreeLetterLimit) { + value = value.slice(0, 3).toUpperCase(); // Restrict to 3 letters and capitalize them + } if (value !== this.state.value) { this.setState({ value }, () => this.props.onChange && this.props.onChange(this.state.value)); } From 97038c11e3735c681b8c8a846912fbeb277823b0 Mon Sep 17 00:00:00 2001 From: ankitkumar774 <135097567+ankitkumar774@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:57:21 +0530 Subject: [PATCH 076/111] notification CSS correction --- src/components/RequireAuth.js | 11 ++++++----- src/components/dialogs/NotificationDialog.js | 12 +++++++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index ca341fb4..803b9b3f 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -164,10 +164,12 @@ const useStyles = makeStyles((theme) => ({ }, iconBtn: { position: "absolute", - top: "5", - right: "0", - width: "15px", - height: "15px", + top: "-.5rem", + right: ".8rem", + padding: theme.spacing(1.6), + width: "1.1rem", + // width: "15px", + height: "1.1rem", background: "red", borderRadius: "50%", marginBottom: "20px", @@ -206,7 +208,6 @@ const RequireAuth = (props) => { }, [data]); const getNotification=useSelector((store)=>store.core) - console.log('getNotification',getNotification); const bellIcon = (event) => { if (anchorEl) { diff --git a/src/components/dialogs/NotificationDialog.js b/src/components/dialogs/NotificationDialog.js index cfa649c3..934937a4 100644 --- a/src/components/dialogs/NotificationDialog.js +++ b/src/components/dialogs/NotificationDialog.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect,useRef } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { IconButton, Popover, @@ -110,9 +110,15 @@ const NotificationDialog = ({ anchorEl, onClose, open, id, notificationData, mod const handleScroll = () => { const threshold = 1; - const isBottom = listRef.current.scrollHeight - listRef.current.scrollTop <= listRef.current.clientHeight + threshold; + const isBottom = + listRef.current.scrollHeight - listRef.current.scrollTop <= listRef.current.clientHeight + threshold; if (isBottom && !hasFetchedMore) { - dispatch(fetchNotification(userid,checkRes.notificationListTotalCount)); + dispatch( + fetchNotification( + userid, + checkRes.notificationListTotalCount < 100 ? checkRes.notificationListTotalCount : 100, + ), + ); setHasFetchedMore(true); // Set to true to prevent further API calls } }; From 84f8aac2dd72da55ca82a28cb2bf175c569c6d8c Mon Sep 17 00:00:00 2001 From: Rishav Johari <101561606+RishavWtt@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:44:31 +0530 Subject: [PATCH 077/111] craete time picker component --- src/index.js | 2 + src/pickers/AdTimePicker.js | 129 ++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/pickers/AdTimePicker.js diff --git a/src/index.js b/src/index.js index 152d5f8d..83a92991 100644 --- a/src/index.js +++ b/src/index.js @@ -115,6 +115,7 @@ import { RIGHT_ROLE_SEARCH } from "./constants"; import { authMiddleware } from "./middlewares"; import RefreshAuthToken from "./components/RefreshAuthToken"; import CommonSnackbar from "./components/generics/CommonSnakbar"; +import AdTimePicker from "./pickers/AdTimePicker"; const ROUTE_ROLES = "roles"; const ROUTE_ROLE = "roles/role"; @@ -129,6 +130,7 @@ const DEFAULT_CONFIG = { { key: "core.MonthPicker", ref: MonthPicker }, { key: "core.LanguagePicker", ref: LanguagePicker }, { key: "core.route.role", ref: ROUTE_ROLE }, + { key: "core.AdTimePicker", ref: AdTimePicker }, ], "core.Boot": [KeepLegacyAlive, RefreshAuthToken], "core.Router": [ diff --git a/src/pickers/AdTimePicker.js b/src/pickers/AdTimePicker.js new file mode 100644 index 00000000..79246fab --- /dev/null +++ b/src/pickers/AdTimePicker.js @@ -0,0 +1,129 @@ +import React, { Component } from "react"; +import moment from "moment"; +import { withTheme, withStyles } from "@material-ui/core/styles"; +import { injectIntl } from "react-intl"; +import { FormControl, TextField } from "@material-ui/core"; +import { TimePicker as MUITimePicker } from "@material-ui/pickers"; +import { formatMessage } from "../helpers/i18n"; +import MomentUtils from "@date-io/moment"; +import { MuiPickersUtilsProvider } from "@material-ui/pickers"; +import "moment/locale/fr"; + +const styles = (theme) => ({ + label: { + color: theme.palette.text.primary, + }, +}); + +function fromISODate(timeStr) { + if (!timeStr) return null; + + // Log what is being passed to moment + console.log("Converting time string:", timeStr); + + // Ensure the time string is in "HH:mm:ss" format + const time = moment(timeStr, "HH:mm:ss"); + + // Check if the date is valid + if (!time.isValid()) { + console.error("Invalid time format:", timeStr); + return null; + } + + return time.toDate(); // Convert the moment object to a JavaScript Date object + } + + +class AdTimePicker extends Component { + state = { value: null }; + + componentDidMount() { + if (this.props.value) { + console.log("Initial value:", this.props.value); + this.setState({ value: fromISODate(this.props.value) }); + } + } + + componentDidUpdate(prevProps) { + if (prevProps.value !== this.props.value) { + console.log("Previous value:", prevProps.value); + console.log("Current value received:", this.props.value); + + if (this.props.value) { + const parsedDate = fromISODate(this.props.value); + if (parsedDate) { + this.setState({ value: parsedDate }); + } else { + console.error("Failed to parse time:", this.props.value); + } + } + } + } + + + dateChange = (d) => { + if (!d) { + this.setState({ value: null }, () => this.props.onChange(null)); + return; + } + + // Format the date as "HH:mm:ss" and update state + const formattedTime = moment(d).format('HH:mm:ss'); + this.setState({ value: d }, () => this.props.onChange(formattedTime)); + }; + + + render() { + const { + intl, + classes, + readOnly = false, + required = false, + fullWidth = true, + label, + ...otherProps + } = this.props; + + let userlang = localStorage.getItem("userLanguage"); + let locale = userlang === "fr" ? "fr" : "en"; + moment.locale(locale); + console.log("value",this.state.value) + return ( + + + ( + + )} + /> + + + ); + } + } + + +export default injectIntl(withTheme(withStyles(styles)(AdTimePicker))); From 73528df1a01d9563eea179a21b73e2c273d97c66 Mon Sep 17 00:00:00 2001 From: richa-rathoreee Date: Tue, 1 Oct 2024 11:11:16 +0530 Subject: [PATCH 078/111] changes btn --- src/components/generics/Searcher.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/generics/Searcher.js b/src/components/generics/Searcher.js index 1c862a19..c88f9f91 100644 --- a/src/components/generics/Searcher.js +++ b/src/components/generics/Searcher.js @@ -150,8 +150,9 @@ class SelectionMenu extends Component { actions = [], processing, actionsContributionKey = null, + isMenu = true } = this.props; - console.log(actions, "actions") + console.log(actions, isMenu,"actionss") let contributed_entries = modulesManager.getContribs(actionsContributionKey); if (!actions.length && !contributed_entries) return null; if (processing) { @@ -171,9 +172,11 @@ class SelectionMenu extends Component { entries.push({ text: formatMessage(intl, "claim", a.label), action: a.action }); } }); - if (entries.length > 2 || (this.props.exportable && entries.length >= 1)) { + if (entries.length > 5 || (this.props.exportable && entries.length >= 1)) { return this.renderMenu(entries, actionsContributionKey); } else { + console.log(entries,'entries'); + return this.renderButtons(entries, actionsContributionKey); } } @@ -362,6 +365,7 @@ class Searcher extends Component { (e) => a(s) ); }; + headerActions = (filters) => { if (!!this.props.headerActions) return this.props.headerActions(filters); @@ -413,6 +417,7 @@ class Searcher extends Component { processing = false, withSelection = null, actionsContributionKey = null, + isMenu = true, withPagination = true, exportable = false, exportFetch = null, From 7015e0cd843a14bc62875fd1f8d98ced7d3c73c5 Mon Sep 17 00:00:00 2001 From: tom hikari Date: Wed, 30 Oct 2024 11:26:58 +0100 Subject: [PATCH 079/111] feature current title menu and page --- src/components/RequireAuth.js | 25 +-- src/components/hooks/pageTitle.js | 26 +++ src/components/hooks/routes.js | 247 +++++++++++++++++++++++++++ src/components/hooks/usePageTitle.js | 20 +++ src/pages/LoginPage.js | 9 + 5 files changed, 316 insertions(+), 11 deletions(-) create mode 100644 src/components/hooks/pageTitle.js create mode 100644 src/components/hooks/routes.js create mode 100644 src/components/hooks/usePageTitle.js diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index 803b9b3f..9520a18e 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -26,10 +26,11 @@ import { useBoolean, useAuthentication } from "../helpers/hooks"; import { useGraphqlQuery } from "@openimis/fe-core"; import { formatMessageWithValues, withModulesManager, withHistory, historyPush } from "@openimis/fe-core"; import NotificationsIcon from "@material-ui/icons/Notifications"; -import { useDispatch,useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { useIdleTimer } from "react-idle-timer/dist/index.legacy.cjs.js"; // otherwise not building: https://github.com/SupremeTechnopriest/react-idle-timer/issues/350 import { CheckAssignedProfile, logout } from "../actions"; import NotificationDialog from "./dialogs/NotificationDialog"; +import PageTitle from "./hooks/pageTitle"; export const APP_BAR_CONTRIBUTION_KEY = "core.AppBar"; export const MAIN_MENU_CONTRIBUTION_KEY = "core.MainMenu"; @@ -207,8 +208,8 @@ const RequireAuth = (props) => { } }, [data]); - const getNotification=useSelector((store)=>store.core) - + const getNotification = useSelector((store) => store.core); + const bellIcon = (event) => { if (anchorEl) { setAnchorEl(null); // Close the dialog if it's already open @@ -225,7 +226,7 @@ const RequireAuth = (props) => { }; const open = Boolean(anchorEl); - const id = open ? 'notification-popover' : undefined; + const id = open ? "notification-popover" : undefined; const isAppBarMenu = useMemo(() => theme.menu.variant.toUpperCase() === "APPBAR", [theme.menu.variant]); const idleTimeSet = 30 * 60 * 1000; @@ -249,6 +250,7 @@ const RequireAuth = (props) => { }, [startIdleTimer]); if (!auth.isAuthenticated) { + sessionStorage.setItem("session_expired", "1"); return ; } @@ -330,16 +332,17 @@ const RequireAuth = (props) => { [classes.jrnlContentShift]: isDrawerOpen, })} > + {children} ); diff --git a/src/components/hooks/pageTitle.js b/src/components/hooks/pageTitle.js new file mode 100644 index 00000000..d727951b --- /dev/null +++ b/src/components/hooks/pageTitle.js @@ -0,0 +1,26 @@ +import { Box, Grid, Typography } from "@material-ui/core"; +import { makeStyles } from "@material-ui/styles"; +import React from "react"; +import UsePageTitle from "./usePageTitle"; + +const useStyles = makeStyles((theme) => ({ + container: theme.page, +})); + +function PageTitle() { + const classes = useStyles(); + const page = UsePageTitle(); + + return ( + + + + {page.parent} + {page.title} + + + + ); +} + +export default PageTitle; diff --git a/src/components/hooks/routes.js b/src/components/hooks/routes.js new file mode 100644 index 00000000..80bef301 --- /dev/null +++ b/src/components/hooks/routes.js @@ -0,0 +1,247 @@ +const affiliation = [ + { + parent: "Affiliation", + path: "/insuree/families", + title: "Liste des familles", + }, + { + parent: "Affiliation", + path: "/insuree/insurees", + title: "Liste des assurés", + }, + { + parent: "Affiliation", + path: "/policy/policies", + title: "Polices", + }, + { + parent: "Affiliation", + title: "Affectation d'un utilisateur", + path: "insuree/insurees/PendingApprovalAssignemnt", + }, +]; + +const administration = [ + { + parent: "Administration", + path: "/admin/users", + title: "Utilisateurs", + }, + { + parent: "Administration", + path: "/location/locations", + title: "Localisations geographiques", + }, + { + parent: "Administration", + path: "/location/centers", + title: "Centres", + }, + { + parent: "Administration", + path: "/roles", + title: "Gestion des roles", + }, + { + parent: "Administration", + path: "/policyHolderUsers", + title: "Administrateurs souscripteurs", + }, + { + parent: "Administration", + path: "/admin/dashboard", + title: "Dashboard", + }, +]; + +const demandePayement = [ + { + parent: "Demande de paiement", + path: "/claim/reviews", + title: "Controle et paiement des factures", + }, + { + parent: "Demande de paiement", + path: "/claim_batch", + title: "Evaluation par lots", + }, +]; + +const category = [ + { + parent: "Category des assurés", + title: "Category des assurés", + path: "/admin/products", + }, + { + parent: "Category des assurés", + title: "Cotisations", + path: "/contributionPlans", + }, + { + parent: "Category des assurés", + title: "Taux/forfait cotisations", + path: "/contributionPlanBundles", + }, +]; + +const fosa = [ + { + parent: "Fosa", + title: "Formation sanitaire", + path: "/location/healthFacilities", + }, + { + parent: "Fosa", + title: "Panier des soins : actes des soins", + path: "/medical/pricelists/services", + }, + { + parent: "Fosa", + title: "Panier des soins: produits medicaux", + path: "/medical/pricelists/items", + }, + { + parent: "Fosa", + title: "Actes des soins", + path: "/medical/medicalServices", + }, + { + parent: "Fosa", + title: "Produits medicaux", + path: "/medical/medicalItems", + }, + { + parent: "Fosa", + title: "Verification", + path: "/insuree/insurees/verifyinsuree", + }, +]; + +const outils = [ + { + parent: "Outils", + path: "/tools/registers", + title: "Registres", + }, + { + parent: "Outils", + path: "/tools/extracts", + title: "Extraits", + }, + { + parent: "Outils", + path: "/tools/reports", + title: "Rapports", + }, +]; + +const profile = [ + { + parent: "Profil", + path: "/profile/myProfile", + title: "Information", + }, + { + parent: "Profil", + path: "/profile/changePassword", + title: "Changer mot de passe", + }, +]; + +const souscripteurs = [ + { + parent: "Souscripteurs", + path: "/contribution/contributions", + title: "Contributions", + }, + { + parent: "Souscripteurs", + path: "/front/policyHolders", + title: "Immatriculation", + }, + { + parent: "Souscripteurs", + path: "/contribution/contributions", + title: "Contributions", + }, + { + parent: "Souscripteurs", + path: "/payment/payments", + title: "Recouvrements", + }, + { + parent: "Souscripteurs", + path: "/paymentApproval", + title: "Paiement par approbation", + }, + { + parent: "Souscripteurs", + path: "/contracts", + title: "Déclaration", + }, + { + parent: "Souscripteurs", + path: "/declaration", + title: "Rapport de déclaration", + }, + { + parent: "Souscripteurs", + path: "/policyholderRequest", + title: "Nouveau souscripteur demandes", + }, +]; + +const juridique = [ + { + parent: "Juridique et financier", + path: "/invoices", + title: "Factures", + }, + { + parent: "Juridique et financier", + path: "/bills", + title: "Factures", + }, + { + parent: "Juridique et financier", + path: "/paymentPlans", + title: "Plans de paiement", + }, +]; + +const exceptions = [ + { + parent: "Exceptions", + path: "/exception", + title: "Exception pour les assurés", + }, + { + parent: "Exceptions", + path: "/exception/policyholder", + title: "Exception pour les souscripteurs", + }, + { + parent: "Exceptions", + path: "/exception/pendingapproval", + title: "En attente d'approbation", + }, +]; + +export const routePages = [ + { + "path": "home", + "title": "", + "parent": "", + }, + ...affiliation, + ...demandePayement, + ...administration, + ...category, + ...fosa, + ...outils, + ...profile, + ...souscripteurs, + ...juridique, + ...exceptions, +]; diff --git a/src/components/hooks/usePageTitle.js b/src/components/hooks/usePageTitle.js new file mode 100644 index 00000000..80ed63d6 --- /dev/null +++ b/src/components/hooks/usePageTitle.js @@ -0,0 +1,20 @@ +import React from "react"; +import { useLocation } from "react-router-dom"; +import { routePages } from "../hooks/routes"; + +function UsePageTitle() { + const location = useLocation(); + const { pathname } = location; + const [page, setPage] = React.useState({}); + + React.useEffect(() => { + const routes = routePages.find((item) => item.path === pathname || pathname.startsWith(item.path)); + if (routes) { + setPage((prev) => ({ ...routes })); + } + }, [pathname]); + + return page; +} + +export default UsePageTitle; diff --git a/src/pages/LoginPage.js b/src/pages/LoginPage.js index 7509785a..2211aa6f 100644 --- a/src/pages/LoginPage.js +++ b/src/pages/LoginPage.js @@ -13,6 +13,7 @@ import { InputAdornment, TextField, } from "@material-ui/core"; +import Alert from '@material-ui/lab/Alert'; import TextInput from "../components/inputs/TextInput"; import { useTranslations } from "../helpers/i18n"; import { useModulesManager } from "../helpers/modules"; @@ -101,6 +102,7 @@ const LoginPage = ({ logo, backgroundImage }) => { setError(false); setAuthenticating(true); if (await auth.login(credentials)) { + sessionStorage.removeItem("session_expired"); history.push("/"); } else { setError(true); @@ -161,6 +163,13 @@ const LoginPage = ({ logo, backgroundImage }) => { > CAMU IMS
+ +
+ {sessionStorage.getItem("session_expired") && ( + Session Expired + )} +
+ Date: Wed, 30 Oct 2024 11:36:09 +0100 Subject: [PATCH 080/111] underline current menu --- .../generics/MainMenuContribution.js | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/components/generics/MainMenuContribution.js b/src/components/generics/MainMenuContribution.js index 06e55dfb..a2d8f4a2 100644 --- a/src/components/generics/MainMenuContribution.js +++ b/src/components/generics/MainMenuContribution.js @@ -20,9 +20,11 @@ import { Grow, Paper, ClickAwayListener, + Box, } from "@material-ui/core"; import withModulesManager from "../../helpers/modules"; import { _historyPush } from "../../helpers/history"; +import UsePageTitle from "../hooks/usePageTitle"; const styles = (theme) => ({ panel: { @@ -113,14 +115,14 @@ class MainMenuContribution extends Component { handleMenuSelect = (e, route) => { // block normal href only for left click - if (e.type === 'click') { + if (e.type === "click") { e.stopPropagation(); e.preventDefault(); } this.toggleExpanded(e); this.redirect(route); }; - + redirect(route) { const { modulesManager, history } = this.props; _historyPush(modulesManager, history, route); @@ -129,10 +131,8 @@ class MainMenuContribution extends Component { appBarMenu = () => { return ( - + + {this.props.entries.map((entry, idx) => (
- this.handleMenuSelect(e, entry.route)} component="a" href={`${process.env.PUBLIC_URL || ""}${entry.route}`} passHref> + this.handleMenuSelect(e, entry.route)} + component="a" + href={`${process.env.PUBLIC_URL || ""}${entry.route}`} + passHref + > {entry.icon} - - + {entry.withDivider && ( { + const page = UsePageTitle(); + + return ( + <> + + + ); +}; + export default withModulesManager(withTheme(withStyles(styles)(MainMenuContribution))); From 3685efce2107dfdbc4fb3ef9dd25ead48725d9bd Mon Sep 17 00:00:00 2001 From: tom hikari Date: Wed, 6 Nov 2024 16:34:46 +0100 Subject: [PATCH 081/111] menu-and-title --- src/components/hooks/pageTitle.js | 4 +++ src/components/hooks/routes.js | 52 +++++++++++++++++++++++++++- src/components/hooks/usePageTitle.js | 12 ++++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/components/hooks/pageTitle.js b/src/components/hooks/pageTitle.js index d727951b..efa79875 100644 --- a/src/components/hooks/pageTitle.js +++ b/src/components/hooks/pageTitle.js @@ -11,6 +11,10 @@ function PageTitle() { const classes = useStyles(); const page = UsePageTitle(); + if (!page.parent) { + return <>; + } + return ( diff --git a/src/components/hooks/routes.js b/src/components/hooks/routes.js index 80bef301..248f2f77 100644 --- a/src/components/hooks/routes.js +++ b/src/components/hooks/routes.js @@ -27,6 +27,26 @@ const administration = [ path: "/admin/users", title: "Utilisateurs", }, + { + parent: "Administration", + path: "/admin/bank", + title: "Bank", + }, + { + parent: "Administration", + path: "/admin/fosaConfiguration", + title: "Catégories des Fosa", + }, + { + parent: "Administration", + path: "/admin/operation", + title: "Opération Management", + }, + { + parent: "Administration", + path: "/admin/serviceActs", + title: "Medical services category management", + }, { parent: "Administration", path: "/location/locations", @@ -52,6 +72,16 @@ const administration = [ path: "/admin/dashboard", title: "Dashboard", }, + { + parent: "Administration", + path: "/admin/fosa/users", + title: "Utilisateurs Fosa", + }, + { + parent: "Administration", + path: "/admin/policyholder/users", + title: "Utilisateurs souscripteurs", + }, ]; const demandePayement = [ @@ -65,6 +95,16 @@ const demandePayement = [ path: "/claim_batch", title: "Evaluation par lots", }, + { + parent: "Demande de paiement", + path: "/claim/healthFacilities", + title: "Demande de paiement", + }, + { + parent: "Demande de paiement", + path: "/claim/invoiceApproval", + title: "Invoices", + }, ]; const category = [ @@ -134,6 +174,11 @@ const outils = [ path: "/tools/reports", title: "Rapports", }, + { + parent: "Outils", + path: "/tools/manualSync", + title: "Manuels Synchronisation", + }, ]; const profile = [ @@ -157,7 +202,7 @@ const souscripteurs = [ }, { parent: "Souscripteurs", - path: "/front/policyHolders", + path: "/policyHolders", title: "Immatriculation", }, { @@ -208,6 +253,11 @@ const juridique = [ path: "/paymentPlans", title: "Plans de paiement", }, + { + parent: "Juridique et financier", + path: "/payment/paymentpenalty", + title: "Pénalité de sanction", + }, ]; const exceptions = [ diff --git a/src/components/hooks/usePageTitle.js b/src/components/hooks/usePageTitle.js index 80ed63d6..337ae3de 100644 --- a/src/components/hooks/usePageTitle.js +++ b/src/components/hooks/usePageTitle.js @@ -8,7 +8,17 @@ function UsePageTitle() { const [page, setPage] = React.useState({}); React.useEffect(() => { - const routes = routePages.find((item) => item.path === pathname || pathname.startsWith(item.path)); + const routes = routePages.find((item) => { + if (item.path === pathname) { + return item; + } + + if (pathname.startsWith(item.path)) { + return item; + } + + return null; + }); if (routes) { setPage((prev) => ({ ...routes })); } From 0afd30d0d4c06b9e89f315bd0830a4dce1fe9382 Mon Sep 17 00:00:00 2001 From: tom hikari Date: Mon, 3 Mar 2025 16:09:31 +0100 Subject: [PATCH 082/111] remove back project --- src/components/RequireAuth.js | 113 +++++++++++++++++++------------- src/components/generics/Form.js | 7 +- 2 files changed, 72 insertions(+), 48 deletions(-) diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index 9520a18e..a8870ca9 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -1,4 +1,6 @@ import React, { useMemo, useState, useEffect } from "react"; +import { BrowserRouter as Router, Switch, Route, Link, useRouteMatch, useParams, useLocation } from "react-router-dom"; + import withWidth from "@material-ui/core/withWidth"; import { Redirect } from "../helpers/history"; import { alpha, useTheme, makeStyles } from "@material-ui/core/styles"; @@ -181,7 +183,15 @@ const useStyles = makeStyles((theme) => ({ }, })); +export function useQuery() { + const { search } = useLocation(); + + return React.useMemo(() => new URLSearchParams(search), [search]); +} + const RequireAuth = (props) => { + // let { hideMenuNavigation } = useParams(); + let query = useQuery(); const { children, logo, redirectTo, ...others } = props; const [isOpen, setOpen] = useBoolean(); const [isDrawerOpen, setDrawerOpen] = useBoolean(); @@ -191,6 +201,7 @@ const RequireAuth = (props) => { const modulesManager = useModulesManager(); const auth = useAuthentication(); const [searchString, setSearchString] = useState(); + const [hideMenu, setHideMenu] = useState(false); const dispatch = useDispatch(); const { isLoading, data, error } = useGraphqlQuery( ` @@ -202,6 +213,12 @@ const RequireAuth = (props) => { `, { str: searchString }, ); + + useEffect(() => { + if (query.get("hideMenuNavigation")) { + setHideMenu(true); + } + }, [query]); useEffect(() => { if (!!data) { dispatch({ type: "INSUREE_COUNT_RESP", payload: data }); @@ -256,56 +273,58 @@ const RequireAuth = (props) => { return ( <> - - - - - - + + + + {/* {modulesManager.getOpenIMISVersion()} */} + + + {isAppBarMenu && ( - + +
+ )} - CAMU - - - - - {/* {modulesManager.getOpenIMISVersion()} */} - - - - {isAppBarMenu && ( - - -
- - - )} - -
-
-
-
{getNotification?.notificationListTotalCount}
- + +
+
+
+
{getNotification?.notificationListTotalCount}
+ +
-
-
+ - - {/* */} - - + + {/* */} + + + )} {isOpen && ( )} - -
+ {!hideMenu && } + {!hideMenu &&
}
- + {!hideMenu && } {children}
({ dirty: true })); } + + // get query params from url using window.location.search + const query = new URLSearchParams(window.location.search); + this.setState({ hideMenuNavigation: query.get("hideMenuNavigation") }); } componentDidUpdate(prevProps, prevState, snapshot) { @@ -162,7 +167,7 @@ class Form extends Component { - {!!back && ( + {!!back && !this.state.hideMenuNavigation && ( From 133fa648e258a186b78c0150f1eb7fefaf72a5c2 Mon Sep 17 00:00:00 2001 From: tom hikari Date: Wed, 12 Mar 2025 11:03:02 +0100 Subject: [PATCH 083/111] feature/new-reset-pages --- src/components/App.js | 7 +- src/pages/VerifyUserAndUpdatePasswordPage.js | 158 +++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/pages/VerifyUserAndUpdatePasswordPage.js diff --git a/src/components/App.js b/src/components/App.js index 34b98800..5ef94538 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -17,6 +17,7 @@ import LoginPage from "../pages/LoginPage"; import { useAuthentication } from "../helpers/hooks"; import ForgotPasswordPage from "../pages/ForgotPasswordPage"; import SetPasswordPage from "../pages/SetPasswordPage"; +import VerifyUserAndUpdatePasswordPage from "../pages/VerifyUserAndUpdatePasswordPage"; import { ErrorBoundary } from "@openimis/fe-core"; export const ROUTER_CONTRIBUTION_KEY = "core.Router"; @@ -109,6 +110,10 @@ const App = (props) => { } /> } /> } /> + } + /> {unauthenticatedRoutes.map((route) => ( { path={"/" + route.path} render={(props) => ( - + )} /> diff --git a/src/pages/VerifyUserAndUpdatePasswordPage.js b/src/pages/VerifyUserAndUpdatePasswordPage.js new file mode 100644 index 00000000..39a85350 --- /dev/null +++ b/src/pages/VerifyUserAndUpdatePasswordPage.js @@ -0,0 +1,158 @@ +import React, { useState, useMemo, useEffect } from "react"; + +import { makeStyles } from "@material-ui/styles"; +import { Button, Box, Grid, Paper } from "@material-ui/core"; +import TextInput from "../components/inputs/TextInput"; +import { useTranslations } from "../helpers/i18n"; +import { useModulesManager } from "../helpers/modules"; +import { useHistory } from "../helpers/history"; +import Helmet from "../helpers/Helmet"; +import { useGraphqlMutation } from "../helpers/hooks"; + +const useStyles = makeStyles((theme) => ({ + container: { + position: "absolute", + top: "20%", + left: 0, + right: 0, + margin: "auto", + display: "flex", + justifyContent: "center", + }, + paper: theme.paper.paper, + logo: { + maxHeight: 100, + }, + setBox: { + boxShadow: '0px 0px 0px #eee' + } +})); + +const VerifyUserAndUpdatePasswordPage = (props) => { + const classes = useStyles(); + const history = useHistory(); + const modulesManager = useModulesManager(); + const { formatMessage } = useTranslations("core.SetPasswordPage", modulesManager); + const [credentials, setCredentials] = useState({}); + const [error, setError] = useState(); + const { mutate } = useGraphqlMutation( + ` + mutation setPassword ($input: SetPasswordMutationInput!) { + setPassword(input: $input) { + clientMutationId + success + error + } + } + `, + { wait: false }, + ); + + useEffect(() => { + const search = new URLSearchParams(location.search); + setCredentials({ token: search.get("token") }); + }, []); + + const onSubmit = async (e) => { + e.preventDefault(); + if (isValid) { + const result = await mutate({ + username: credentials.username, + token: credentials.token, + newPassword: credentials.password, + }); + if (result?.setPassword.success) { + history.push("/"); + } else { + setError(result?.setPassword.error || formatMessage("error")); + } + } + }; + + const isValid = useMemo( + () => + credentials.confirmPassword && + credentials.password && + credentials.password === credentials.confirmPassword && + credentials.username && + credentials.token, + [credentials], + ); + + return ( + <> +
+
+
+ + +
+ + + + + +
{formatMessage("pageTitle")}
+ + setCredentials({ ...credentials, username })} + /> + + + setCredentials({ ...credentials, password })} + /> + + + setCredentials({ ...credentials, confirmPassword })} + /> + + {error && ( + + {error} + + )} + + + + +
+
+
+
+
+
+ + ); +}; + +export default VerifyUserAndUpdatePasswordPage; From 441e09bf35c1dc13495a5ef6847cc1a413da7bde Mon Sep 17 00:00:00 2001 From: tom hikari Date: Wed, 12 Mar 2025 11:31:52 +0100 Subject: [PATCH 084/111] fix update query --- const { mutate } = useGraphqlMutation( | 11 ++ src/helpers/hooks.js | 10 +- src/index.js | 4 +- src/pages/VerifyUserAndUpdatePasswordPage.js | 183 +++++++++++-------- 4 files changed, 126 insertions(+), 82 deletions(-) create mode 100644 const { mutate } = useGraphqlMutation( diff --git a/const { mutate } = useGraphqlMutation( b/const { mutate } = useGraphqlMutation( new file mode 100644 index 00000000..a0ad3c30 --- /dev/null +++ b/const { mutate } = useGraphqlMutation( @@ -0,0 +1,11 @@ +const { mutate } = useGraphqlMutation( + ` + mutation verifyUserAndUpdatePassword($password: String!, $token: String!, $userId: String!) { + verifyUserAndUpdatePassword(password: $password, token: $token, userId: $userId) { + success + message + } + } + `, + { wait: false }, + ); \ No newline at end of file diff --git a/src/helpers/hooks.js b/src/helpers/hooks.js index 5f9f3a50..49a5f7fb 100644 --- a/src/helpers/hooks.js +++ b/src/helpers/hooks.js @@ -95,7 +95,7 @@ export const useGraphqlMutation = (operation, config) => { const dispatch = useDispatch(); const [state, setState] = useState({ isLoading: false, error: null }); - function mutate(input) { + function mutate(input, usePlainObject = false) { if (state.isLoading) { console.warn("A mutation is already in progress"); return; @@ -103,9 +103,11 @@ export const useGraphqlMutation = (operation, config) => { setState({ isLoading: true, error: null }); return new Promise(async (resolve, reject) => { try { - const variables = { - input, - }; + const variables = usePlainObject + ? input + : { + input, + }; const result = await dispatch( graphqlMutation(operation, variables, config.type, { operation, input }, config.wait), ); diff --git a/src/index.js b/src/index.js index 83a92991..90f9fb76 100644 --- a/src/index.js +++ b/src/index.js @@ -59,6 +59,7 @@ import { fetchMutation, prepareMutation, clearCurrentPaginationPage, + login, } from "./actions"; import { formatMessage, @@ -262,5 +263,6 @@ export { ConfirmDialog, useAuthentication, useBoolean, - CommonSnackbar + CommonSnackbar, + login, }; diff --git a/src/pages/VerifyUserAndUpdatePasswordPage.js b/src/pages/VerifyUserAndUpdatePasswordPage.js index 39a85350..32e3670c 100644 --- a/src/pages/VerifyUserAndUpdatePasswordPage.js +++ b/src/pages/VerifyUserAndUpdatePasswordPage.js @@ -24,8 +24,8 @@ const useStyles = makeStyles((theme) => ({ maxHeight: 100, }, setBox: { - boxShadow: '0px 0px 0px #eee' - } + boxShadow: "0px 0px 0px #eee", + }, })); const VerifyUserAndUpdatePasswordPage = (props) => { @@ -35,13 +35,24 @@ const VerifyUserAndUpdatePasswordPage = (props) => { const { formatMessage } = useTranslations("core.SetPasswordPage", modulesManager); const [credentials, setCredentials] = useState({}); const [error, setError] = useState(); + // const { mutate } = useGraphqlMutation( + // ` + // mutation verifyUserAndUpdatePassword ($input: VerifyUserAndUpdatePasswordMutationInput!) { + // verifyUserAndUpdatePassword($input) { + // success + // error + // } + // } + // `, + // { wait: false }, + // ); + const { mutate } = useGraphqlMutation( ` - mutation setPassword ($input: SetPasswordMutationInput!) { - setPassword(input: $input) { - clientMutationId + mutation verifyUserAndUpdatePassword($password: String!, $token: String!, $userId: String!) { + verifyUserAndUpdatePassword(password: $password, token: $token, userId: $userId) { success - error + message } } `, @@ -50,21 +61,29 @@ const VerifyUserAndUpdatePasswordPage = (props) => { useEffect(() => { const search = new URLSearchParams(location.search); - setCredentials({ token: search.get("token") }); + setCredentials({ + token: search.get("token"), + username: search.get("username"), + userId: search.get("user_id"), + }); }, []); const onSubmit = async (e) => { e.preventDefault(); if (isValid) { - const result = await mutate({ - username: credentials.username, - token: credentials.token, - newPassword: credentials.password, - }); - if (result?.setPassword.success) { + const result = await mutate( + { + password: credentials.password, + username: credentials.username, + token: credentials.token, + userId: credentials.userId, + }, + true, + ); + if (result?.verifyUserAndUpdatePassword.success) { history.push("/"); } else { - setError(result?.setPassword.error || formatMessage("error")); + setError(result?.verifyUserAndUpdatePassword.error || formatMessage("error")); } } }; @@ -81,75 +100,85 @@ const VerifyUserAndUpdatePasswordPage = (props) => { return ( <> -
-
-
- - -
- - - +
+
+
+ + + + + + -
{formatMessage("pageTitle")}
- - setCredentials({ ...credentials, username })} - /> - - - setCredentials({ ...credentials, password })} - /> - - - setCredentials({ ...credentials, confirmPassword })} - /> - - {error && ( +
+ {formatMessage("pageTitle")} +
+ + + + + setCredentials({ ...credentials, password })} + /> + - {error} + setCredentials({ ...credentials, confirmPassword })} + /> - )} + {error && ( + + {error} + + )} - - + + + -
-
- -
-
+ + + +
); From 885237014d9db2c83971d482d3fa225e2a90846e Mon Sep 17 00:00:00 2001 From: tom hikari Date: Wed, 12 Mar 2025 11:57:44 +0100 Subject: [PATCH 085/111] fix response --- src/pages/VerifyUserAndUpdatePasswordPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/VerifyUserAndUpdatePasswordPage.js b/src/pages/VerifyUserAndUpdatePasswordPage.js index 32e3670c..46c6b356 100644 --- a/src/pages/VerifyUserAndUpdatePasswordPage.js +++ b/src/pages/VerifyUserAndUpdatePasswordPage.js @@ -80,10 +80,10 @@ const VerifyUserAndUpdatePasswordPage = (props) => { }, true, ); - if (result?.verifyUserAndUpdatePassword.success) { + if (result?.data?.verifyUserAndUpdatePassword.success) { history.push("/"); } else { - setError(result?.verifyUserAndUpdatePassword.error || formatMessage("error")); + setError(result?.data?.verifyUserAndUpdatePassword.error || formatMessage("error")); } } }; From 12be83f24c865a02f11ee61b9eac332e0727511f Mon Sep 17 00:00:00 2001 From: tom hikari Date: Wed, 12 Mar 2025 14:06:40 +0100 Subject: [PATCH 086/111] reset password --- src/pages/ForgotPasswordPage.js | 240 +++++++++---------- src/pages/VerifyUserAndUpdatePasswordPage.js | 11 - 2 files changed, 120 insertions(+), 131 deletions(-) diff --git a/src/pages/ForgotPasswordPage.js b/src/pages/ForgotPasswordPage.js index 7e41282e..f02241b5 100644 --- a/src/pages/ForgotPasswordPage.js +++ b/src/pages/ForgotPasswordPage.js @@ -7,8 +7,8 @@ import { useTranslations } from "../helpers/i18n"; import { useModulesManager } from "../helpers/modules"; import Helmet from "../helpers/Helmet"; import { useGraphqlMutation } from "../helpers/hooks"; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import { useHistory } from 'react-router-dom'; +import ArrowBackIcon from "@material-ui/icons/ArrowBack"; +import { useHistory } from "react-router-dom"; const useStyles = makeStyles((theme) => ({ container: { @@ -32,16 +32,15 @@ const ForgotPasswordPage = (props) => { const classes = useStyles(); const modulesManager = useModulesManager(); const { formatMessage } = useTranslations("core.ForgotPasswordPage", modulesManager); - const [username, setUsername] = useState(); + const [email, setEmail] = useState(); const [isDone, setDone] = useState(false); const history = useHistory(); const { isLoading, mutate } = useGraphqlMutation( ` - mutation resetPassword($input: ResetPasswordMutationInput!) { - resetPassword(input: $input) { - clientMutationId + mutation newPasswordRequest($email: String!, $fromWhatEnv: String!) { + newPasswordRequest(email: $email, fromWhatEnv: $fromWhatEnv) { success - error + message } } `, @@ -52,133 +51,134 @@ const ForgotPasswordPage = (props) => { const onSubmit = async (e) => { e.preventDefault(); - await mutate({ username }); + const res = await mutate({ email, fromWhatEnv: "imis" }, true); + console.log("res", res); await setDone(true); }; const handleBackToLogin = () => { // Use the history object to navigate to the LoginPage route - history.push('/login'); + history.push("/login"); }; return ( <> -
-
-
- - -
- - {!isDone && ( - - - - -
{formatMessage("recoverTitle")}
- {/* -

{formatMessage("recoverTitle")}

-
*/} - {/* - {formatMessage("explanationMessage")} - - - {formatMessage("contactAdministrator")} - */} - - setUsername(username)} - /> - - - - - - + {formatMessage("recoverTitle")} +
+ + + setEmail(email)} + /> + + + + + + + - - )} + )} - {isDone && - - //

{formatMessage("done")}

- + {isDone && ( + //

{formatMessage("done")}

- - - - -
{formatMessage('done.Verification')}
-
{formatMessage('done.Administrator')}
- - - -
- } - - - -
+ + + + +
+ {formatMessage("done.Verification")} +
+
+ {formatMessage("done.Administrator")} +
+ + + +
+ )} + + + +
- ); }; diff --git a/src/pages/VerifyUserAndUpdatePasswordPage.js b/src/pages/VerifyUserAndUpdatePasswordPage.js index 46c6b356..b7c16461 100644 --- a/src/pages/VerifyUserAndUpdatePasswordPage.js +++ b/src/pages/VerifyUserAndUpdatePasswordPage.js @@ -35,17 +35,6 @@ const VerifyUserAndUpdatePasswordPage = (props) => { const { formatMessage } = useTranslations("core.SetPasswordPage", modulesManager); const [credentials, setCredentials] = useState({}); const [error, setError] = useState(); - // const { mutate } = useGraphqlMutation( - // ` - // mutation verifyUserAndUpdatePassword ($input: VerifyUserAndUpdatePasswordMutationInput!) { - // verifyUserAndUpdatePassword($input) { - // success - // error - // } - // } - // `, - // { wait: false }, - // ); const { mutate } = useGraphqlMutation( ` From 86e56c39fc2760cb867fe973ce34e999de18476b Mon Sep 17 00:00:00 2001 From: tom hikari Date: Wed, 12 Mar 2025 14:35:25 +0100 Subject: [PATCH 087/111] reset and forgot password --- src/actions.js | 24 +++++++-- src/helpers/hooks.js | 52 +++++++++++++++++++- src/pages/ForgotPasswordPage.js | 17 +++++-- src/pages/VerifyUserAndUpdatePasswordPage.js | 8 +-- 4 files changed, 90 insertions(+), 11 deletions(-) diff --git a/src/actions.js b/src/actions.js index b48e705e..c93812bd 100644 --- a/src/actions.js +++ b/src/actions.js @@ -215,6 +215,25 @@ export function graphqlMutation( }; } +export function graphqlMutation2( + mutation, + variables, + type = "CORE_TRIGGER_MUTATION", + params = {}, + wait = true, + additionalRequest = "", +) { + let clientMutationId; + if (variables?.input) { + clientMutationId = uuid.uuid(); + variables.input.clientMutationId = clientMutationId; + } + return async (dispatch) => { + const response = await dispatch(graphqlWithVariables(mutation, variables, type, params)); + return response?.payload?.data; + }; +} + export function graphqlMutationLegacy( payload, type = "CORE_TRIGGER_MUTATION", @@ -280,7 +299,7 @@ export function login(credentials) { localStorage.setItem("userName", action?.payload?.username); localStorage.setItem("userLanguage", action?.payload?.i_user?.language); localStorage.setItem("userId", action?.payload?.id); - localStorage.setItem("HfId",action?.payload?.i_user?.health_facility_id) + localStorage.setItem("HfId", action?.payload?.i_user?.health_facility_id); return action.type !== "CORE_AUTH_ERR"; }; } @@ -508,7 +527,7 @@ export function clearCurrentPaginationPage() { }; } -export function fetchNotification(userID,first=10) { +export function fetchNotification(userID, first = 10) { return graphql( ` query CamuNotifications { camuNotifications(first: ${first}, user_Id: "${userID}") { @@ -539,7 +558,6 @@ export function fetchNotification(userID,first=10) { } function formatNotificationGQL(data) { - return ` ${!!data.userId ? `userId: "${data.userId}"` : ""} ${!!data.readAll ? `readAll: ${data.readAll}` : ""} diff --git a/src/helpers/hooks.js b/src/helpers/hooks.js index 49a5f7fb..de320672 100644 --- a/src/helpers/hooks.js +++ b/src/helpers/hooks.js @@ -1,7 +1,15 @@ import { useModulesManager } from "@openimis/fe-core"; import { useState, useEffect, useRef, useCallback } from "react"; import { useSelector, useDispatch } from "react-redux"; -import { refreshAuthToken, login, logout, initialize, graphqlWithVariables, graphqlMutation } from "../actions"; +import { + refreshAuthToken, + login, + logout, + initialize, + graphqlWithVariables, + graphqlMutation, + graphqlMutation2, +} from "../actions"; export const useDebounceCb = (cb, duration = 0) => { const [payload, setPayload] = useState(); @@ -146,6 +154,48 @@ export const useGraphqlMutation = (operation, config) => { }; }; +export const useGraphqlMutation2 = (operation, config) => { + config = { ...DEFAULT_GRAPHQL_MUTATION_CONFIG, ...config }; + const dispatch = useDispatch(); + const [state, setState] = useState({ isLoading: false, error: null }); + + const mutate = async (input, usePlainObject = false) => { + if (state.isLoading) { + console.warn("A mutation is already in progress"); + return; + } + + setState({ isLoading: true, error: null }); + + try { + const variables = usePlainObject ? input : { input }; + + const result = await dispatch(graphqlMutation2(operation, variables, config.type, { operation, input }, false)); + + const error = result?.error?.map((err) => err.detail).join("; "); + + if (error) { + throw new Error(error); + } + + setState({ isLoading: false, error: null }); + + return result; + } catch (err) { + setState({ isLoading: false, error: err }); + + // throw err; + return err; + } + }; + + return { + isLoading: state.isLoading, + error: state.error, + mutate, + }; +}; + export const useAuthentication = () => { const dispatch = useDispatch(); const user = useSelector((state) => state.core.user); diff --git a/src/pages/ForgotPasswordPage.js b/src/pages/ForgotPasswordPage.js index f02241b5..fb6b669c 100644 --- a/src/pages/ForgotPasswordPage.js +++ b/src/pages/ForgotPasswordPage.js @@ -6,7 +6,7 @@ import TextInput from "../components/inputs/TextInput"; import { useTranslations } from "../helpers/i18n"; import { useModulesManager } from "../helpers/modules"; import Helmet from "../helpers/Helmet"; -import { useGraphqlMutation } from "../helpers/hooks"; +import { useGraphqlMutation, useGraphqlMutation2 } from "../helpers/hooks"; import ArrowBackIcon from "@material-ui/icons/ArrowBack"; import { useHistory } from "react-router-dom"; @@ -34,8 +34,9 @@ const ForgotPasswordPage = (props) => { const { formatMessage } = useTranslations("core.ForgotPasswordPage", modulesManager); const [email, setEmail] = useState(); const [isDone, setDone] = useState(false); + const [error, setError] = useState(null); const history = useHistory(); - const { isLoading, mutate } = useGraphqlMutation( + const { isLoading, mutate } = useGraphqlMutation2( ` mutation newPasswordRequest($email: String!, $fromWhatEnv: String!) { newPasswordRequest(email: $email, fromWhatEnv: $fromWhatEnv) { @@ -53,7 +54,11 @@ const ForgotPasswordPage = (props) => { e.preventDefault(); const res = await mutate({ email, fromWhatEnv: "imis" }, true); console.log("res", res); - await setDone(true); + if (res?.newPasswordRequest?.success) { + await setDone(true); + } else { + setError(res?.newPasswordRequest?.message || "An error occurred, be sure to use a valid email"); + } }; const handleBackToLogin = () => { @@ -109,6 +114,12 @@ const ForgotPasswordPage = (props) => { onChange={(email) => setEmail(email)} /> + + {error && ( + + {error} + + )} + + + + {/* {modulesManager.getOpenIMISVersion()} */} + + + {isAppBarMenu && ( - + +
+ )} - CAMU - - - - - {/* {modulesManager.getOpenIMISVersion()} */} - - - - {isAppBarMenu && ( - - -
- - - )} - -
-
-
-
{getNotification?.notificationListTotalCount}
- + +
+
+
+
{getNotification?.notificationListTotalCount}
+ +
-
-
+ - - {/* */} - - + + {/* */} + + + + )} {isOpen && ( From 30872e66e4c12c530e728744349f9444eda59a12 Mon Sep 17 00:00:00 2001 From: tom hikari Date: Tue, 16 Dec 2025 16:32:53 +0100 Subject: [PATCH 104/111] fix: correct logic for GED service status and add debug logs in GedAlertBanner --- src/components/GedAlertBanner.js | 8 +++----- src/helpers/hooks/useGedHealthCheck.js | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/GedAlertBanner.js b/src/components/GedAlertBanner.js index fc190b0b..a8c74fb1 100644 --- a/src/components/GedAlertBanner.js +++ b/src/components/GedAlertBanner.js @@ -6,6 +6,9 @@ export default function GedAlertBanner() { if (!isGedDown) return <>; + console.log("===> isGedDown", isGedDown); + console.log("===> isChecking", isChecking); + return ( <>
{`⚠️ Service GED (DMS) est actuellement indisponible. Veuillez contacter l'équipe technique.`} diff --git a/src/helpers/hooks/useGedHealthCheck.js b/src/helpers/hooks/useGedHealthCheck.js index 838d1efe..e016f853 100644 --- a/src/helpers/hooks/useGedHealthCheck.js +++ b/src/helpers/hooks/useGedHealthCheck.js @@ -28,7 +28,7 @@ export const useGedHealthCheck = () => { setHealthStatus((prev) => ({ ...prev, isChecking: false, - isGedDown: payload.status === 200, + isGedDown: payload.status !== 200, })); sessionStorage.setItem("gedHealthStatus", payload.status === 200 ? "UP" : "DOWN"); From 7be869ae2f11d5b1e9c369e6aff8f0c0bef11a38 Mon Sep 17 00:00:00 2001 From: tom hikari Date: Tue, 16 Dec 2025 16:41:26 +0100 Subject: [PATCH 105/111] refactor: simplify GedAlertBanner by removing unnecessary elements and adjusting margin --- src/components/GedAlertBanner.js | 42 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/src/components/GedAlertBanner.js b/src/components/GedAlertBanner.js index a8c74fb1..ee4de3d5 100644 --- a/src/components/GedAlertBanner.js +++ b/src/components/GedAlertBanner.js @@ -6,33 +6,21 @@ export default function GedAlertBanner() { if (!isGedDown) return <>; - console.log("===> isGedDown", isGedDown); - console.log("===> isChecking", isChecking); - return ( - <> -
- {`⚠️ Service GED (DMS) est actuellement indisponible. Veuillez contacter l'équipe technique.`} -
- -
- +
+ {`⚠️ Service GED (DMS) est actuellement indisponible. Veuillez contacter l'équipe technique.`} +
); } From 0003199e03593b59efba6a49b0fca90b1fea8a89 Mon Sep 17 00:00:00 2001 From: tom hikari Date: Tue, 16 Dec 2025 17:03:06 +0100 Subject: [PATCH 106/111] fix: update health status logic in useGedHealthCheck to handle stored status correctly --- src/helpers/hooks/useGedHealthCheck.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/helpers/hooks/useGedHealthCheck.js b/src/helpers/hooks/useGedHealthCheck.js index e016f853..7b5c6642 100644 --- a/src/helpers/hooks/useGedHealthCheck.js +++ b/src/helpers/hooks/useGedHealthCheck.js @@ -46,6 +46,12 @@ export const useGedHealthCheck = () => { if (!storedStatus) { fetchHealthStatus(); + } else { + setHealthStatus((prev) => ({ + ...prev, + isChecking: false, + isGedDown: storedStatus !== "UP", + })); } }, []); From df1edf5bb90b823ddab2c573a8dcfefa4a26255f Mon Sep 17 00:00:00 2001 From: tom hikari Date: Tue, 16 Dec 2025 17:08:36 +0100 Subject: [PATCH 107/111] refactor: remove margin from GedAlertBanner and ensure consistent rendering in RequireAuth component --- src/components/GedAlertBanner.js | 1 - src/components/RequireAuth.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/GedAlertBanner.js b/src/components/GedAlertBanner.js index ee4de3d5..140c99d3 100644 --- a/src/components/GedAlertBanner.js +++ b/src/components/GedAlertBanner.js @@ -15,7 +15,6 @@ export default function GedAlertBanner() { padding: "12px 0", fontWeight: "bold", fontSize: "14px", - marginTop: "80px", width: "100%", boxShadow: "0 2px 4px rgba(0,0,0,0.1)", }} diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index 8832f765..be961346 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -332,7 +332,6 @@ const RequireAuth = (props) => { {/* */} - )} {isOpen && ( @@ -361,6 +360,7 @@ const RequireAuth = (props) => { [classes.jrnlContentShift]: isDrawerOpen, })} > + {!hideMenu && } {children} From 920e83acffea2c324521f9d614f7de8b3d282244 Mon Sep 17 00:00:00 2001 From: sancty Date: Thu, 18 Dec 2025 15:28:11 +0100 Subject: [PATCH 108/111] refactor: reorganize MainMenuContribution component and enhance route translations - Refactored MainMenuContribution to utilize a new MenuItemsList component for rendering menu items. - Improved route handling in usePageTitle to support translation of route titles and subtitles. - Updated route definitions to use translation keys for better localization support. - Enhanced styling for page titles in PageTitle component to improve visual hierarchy. --- .../generics/MainMenuContribution.js | 223 ++++++++--- src/components/hooks/pageTitle.js | 41 +- src/components/hooks/routes.js | 351 ++++++++++++------ src/components/hooks/usePageTitle.js | 100 ++++- src/translations/en.json | 112 +++++- src/translations/fr.json | 142 ++++++- 6 files changed, 771 insertions(+), 198 deletions(-) diff --git a/src/components/generics/MainMenuContribution.js b/src/components/generics/MainMenuContribution.js index a2d8f4a2..7738a279 100644 --- a/src/components/generics/MainMenuContribution.js +++ b/src/components/generics/MainMenuContribution.js @@ -1,29 +1,31 @@ -import React, { Component, Fragment } from "react"; -import PropTypes from "prop-types"; -import MuiAccordion from "@material-ui/core/Accordion"; -import MuiAccordionDetails from "@material-ui/core/AccordionDetails"; -import MuiAccordionSummary from "@material-ui/core/AccordionSummary"; -import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; -import Typography from "@material-ui/core/Typography"; -import { withTheme, withStyles } from "@material-ui/core/styles"; -import ListItem from "@material-ui/core/ListItem"; -import ListItemIcon from "@material-ui/core/ListItemIcon"; -import ListItemText from "@material-ui/core/ListItemText"; import { + Box, + Button, + ClickAwayListener, Divider, - List, + Grow, IconButton, - MenuList, + List, MenuItem, - Button, - Popper, - Grow, + MenuList, Paper, - ClickAwayListener, - Box, + Popper, } from "@material-ui/core"; -import withModulesManager from "../../helpers/modules"; +import MuiAccordion from "@material-ui/core/Accordion"; +import MuiAccordionDetails from "@material-ui/core/AccordionDetails"; +import MuiAccordionSummary from "@material-ui/core/AccordionSummary"; +import ListItem from "@material-ui/core/ListItem"; +import ListItemIcon from "@material-ui/core/ListItemIcon"; +import ListItemText from "@material-ui/core/ListItemText"; +import Typography from "@material-ui/core/Typography"; +import { withStyles, withTheme } from "@material-ui/core/styles"; +import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; +import PropTypes from "prop-types"; +import React, { Component, Fragment } from "react"; +import { useIntl } from "react-intl"; +import { useLocation } from "react-router-dom"; import { _historyPush } from "../../helpers/history"; +import withModulesManager from "../../helpers/modules"; import UsePageTitle from "../hooks/usePageTitle"; const styles = (theme) => ({ @@ -149,25 +151,13 @@ class MainMenuContribution extends Component { - {this.props.entries.map((entry, idx) => ( -
- this.handleMenuSelect(e, entry.route)} - component="a" - href={`${process.env.PUBLIC_URL || ""}${entry.route}`} - passHref - > - {entry.icon} - - - {entry.withDivider && ( - - )} -
- ))} + this.handleMenuSelect({}, route)} + isAppBar={true} + />
@@ -187,23 +177,12 @@ class MainMenuContribution extends Component { - {this.props.entries.map((entry, idx) => ( - - { - this.redirect(entry.route); - }} - > - {entry.icon} - - - {entry.withDivider && ( - - )} - - ))} + this.redirect(route)} + /> @@ -228,14 +207,32 @@ MainMenuContribution.propTypes = { const ButtonMenu = ({ state, toggleExpanded, props }) => { const page = UsePageTitle(); + const intl = useIntl(); + + const translateKey = (key) => { + if (!key) return key; + try { + const translated = intl.formatMessage({ id: key }); + return translated !== key ? translated : key; + } catch { + return key; + } + }; + + const translatedParent = translateKey(page.parent); + const translatedHeader = translateKey(props.header); return ( <> @@ -243,4 +240,116 @@ const ButtonMenu = ({ state, toggleExpanded, props }) => { ); }; +const isMenuItemActive = (entryRoute, currentPathname, allEntries) => { + if (!entryRoute || !currentPathname) { + return false; + } + + if (currentPathname === entryRoute) { + return true; + } + + const hasMoreSpecificMatch = allEntries.some((otherEntry) => { + const otherRoute = otherEntry.route; + if (!otherRoute || otherRoute === entryRoute) { + return false; + } + + if (otherRoute.length > entryRoute.length && currentPathname.startsWith(otherRoute)) { + const nextChar = currentPathname[otherRoute.length]; + if (nextChar === "/" || nextChar === undefined) { + return true; + } + } + return false; + }); + + if (hasMoreSpecificMatch) { + return false; + } + + if (currentPathname.startsWith(entryRoute) && entryRoute !== "/") { + const nextChar = currentPathname[entryRoute.length]; + return nextChar === "/" || nextChar === undefined; + } + + return false; +}; + +const MenuItemsList = ({ entries, header, classes, redirect, isAppBar = false }) => { + const location = useLocation(); + const page = UsePageTitle(); + const currentPath = location.pathname; + + return ( + <> + {entries.map((entry, idx) => { + const isActive = isMenuItemActive(entry.route, currentPath, entries); + + if (isAppBar) { + return ( +
+ { + e.stopPropagation(); + e.preventDefault(); + redirect(entry.route); + }} + component="a" + href={`${process.env.PUBLIC_URL || ""}${entry.route}`} + passHref + selected={isActive} + style={{ + backgroundColor: isActive ? "rgba(255, 159, 28, 0.1)" : "transparent", + }} + > + {entry.icon} + + + {entry.withDivider && } +
+ ); + } + + return ( + + { + redirect(entry.route); + }} + selected={isActive} + style={{ + backgroundColor: isActive ? "rgba(255, 159, 28, 0.1)" : "transparent", + borderLeft: isActive ? "3px solid #ff9f1c" : "3px solid transparent", + }} + > + {entry.icon} + + + {entry.withDivider && } + + ); + })} + + ); +}; + export default withModulesManager(withTheme(withStyles(styles)(MainMenuContribution))); diff --git a/src/components/hooks/pageTitle.js b/src/components/hooks/pageTitle.js index efa79875..0e6e3df0 100644 --- a/src/components/hooks/pageTitle.js +++ b/src/components/hooks/pageTitle.js @@ -5,22 +5,55 @@ import UsePageTitle from "./usePageTitle"; const useStyles = makeStyles((theme) => ({ container: theme.page, + parentTitle: { + fontSize: "0.875rem", + color: theme.palette.text.secondary, + fontWeight: 500, + textTransform: "uppercase", + letterSpacing: "0.5px", + marginBottom: theme.spacing(0.5), + }, + mainTitle: { + fontSize: "1.75rem", + fontWeight: 600, + color: theme.palette.text.primary, + marginBottom: theme.spacing(0.5), + }, + subtitle: { + fontSize: "0.9375rem", + color: theme.palette.text.secondary, + fontWeight: 400, + marginTop: theme.spacing(0.5), + }, })); function PageTitle() { const classes = useStyles(); const page = UsePageTitle(); - if (!page.parent) { + if (!page.parent && !page.title) { return <>; } return ( - - {page.parent} - {page.title} + + {page.parent && ( + + {page.parent} + + )} + {page.title && ( + + {page.title} + + )} + {page.subtitle && ( + + {page.subtitle} + + )} diff --git a/src/components/hooks/routes.js b/src/components/hooks/routes.js index fdbf717d..bcd0378a 100644 --- a/src/components/hooks/routes.js +++ b/src/components/hooks/routes.js @@ -1,296 +1,433 @@ const affiliation = [ { - parent: "Affiliation", + parent: "insuree.mainMenu", path: "/insuree/families", - title: "Liste des familles", + title: "insuree.menu.familiesOrGroups", + subtitle: "core.routes.affiliation.families.subtitle", }, { - parent: "Affiliation", + parent: "insuree.mainMenu", path: "/insuree/insurees", - title: "Liste des assurés", + title: "insuree.menu.insurees", + subtitle: "core.routes.affiliation.insurees.subtitle", }, { - parent: "Affiliation", + parent: "insuree.mainMenu", path: "/policy/policies", - title: "Polices", + title: "policy.menu.policies", + subtitle: "core.routes.affiliation.policies.subtitle", }, { - parent: "Affiliation", - title: "Affectation d'un utilisateur", - path: "insuree/insurees/PendingApprovalAssignemnt", + parent: "insuree.mainMenu", + title: "core.routes.affiliation.assignment.title", + path: "/insuree/insurees/PendingApprovalAssignemnt", + subtitle: "core.routes.affiliation.assignment.subtitle", }, ]; const administration = [ { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/users", - title: "Utilisateurs", + title: "admin.menu.users", + subtitle: "core.routes.administration.users.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/bank", - title: "Bank", + title: "core.routes.administration.bank.title", + subtitle: "core.routes.administration.bank.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/fosaConfiguration", - title: "Catégories des Fosa", + title: "core.routes.administration.fosaCategories.title", + subtitle: "core.routes.administration.fosaCategories.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/operation", - title: "Opération Management", + title: "core.routes.administration.operations.title", + subtitle: "core.routes.administration.operations.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/serviceActs", - title: "Medical services category management", + title: "core.routes.administration.medicalServices.title", + subtitle: "core.routes.administration.medicalServices.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/location/locations", - title: "Localisations geographiques", + title: "admin.menu.locations", + subtitle: "core.routes.administration.locations.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/location/centers", - title: "Centres", + title: "core.routes.administration.centers.title", + subtitle: "core.routes.administration.centers.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/roles", - title: "Gestion des roles", + title: "core.routes.administration.roles.title", + subtitle: "core.routes.administration.roles.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/policyHolderUsers", - title: "Administrateurs souscripteurs", + title: "core.routes.administration.policyholderAdmins.title", + subtitle: "core.routes.administration.policyholderAdmins.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/dashboard", - title: "Dashboard", + title: "core.routes.administration.dashboard.title", + subtitle: "core.routes.administration.dashboard.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/fosa/users", - title: "Utilisateurs Fosa", + title: "core.routes.administration.fosaUsers.title", + subtitle: "core.routes.administration.fosaUsers.subtitle", }, { - parent: "Administration", + parent: "admin.mainMenu", path: "/admin/policyholder/users", - title: "Utilisateurs souscripteurs", + title: "core.routes.administration.policyholderUsers.title", + subtitle: "core.routes.administration.policyholderUsers.subtitle", + }, + { + parent: "admin.mainMenu", + path: "/admin/fosa/user-functionalities", + title: "core.routes.administration.fosaUserFunctionalities.title", + subtitle: "core.routes.administration.fosaUserFunctionalities.subtitle", + }, + { + parent: "admin.mainMenu", + path: "/admin/fosa/user-specialties", + title: "core.routes.administration.fosaUserSpecialties.title", + subtitle: "core.routes.administration.fosaUserSpecialties.subtitle", }, ]; const demandePayement = [ { - parent: "Demande de paiement", + parent: "claim.mainMenu", path: "/claim/reviews", - title: "Controle et paiement des factures", + title: "claim.menu.reviews", + subtitle: "core.routes.payment.reviews.subtitle", }, { - parent: "Demande de paiement", + parent: "claim.mainMenu", path: "/claim_batch", - title: "Evaluation par lots", + title: "claim_batch.menu.claim_batch", + subtitle: "core.routes.payment.batch.subtitle", }, { - parent: "Demande de paiement", + parent: "claim.mainMenu", path: "/claim/healthFacilities", - title: "Demande de paiement", + title: "claim.menu.healthFacilityClaims", + subtitle: "core.routes.payment.requests.subtitle", }, { - parent: "Demande de paiement", + parent: "claim.mainMenu", path: "/claim/invoiceApproval", - title: "Invoices", + title: "core.routes.payment.invoices.title", + subtitle: "core.routes.payment.invoices.subtitle", }, ]; const category = [ { - parent: "Category des assurés", - title: "Category des assurés", + parent: "admin.productMenu", + title: "admin.menu.products", path: "/admin/products", + subtitle: "core.routes.category.products.subtitle", }, { - parent: "Category des assurés", - title: "Cotisations", + parent: "admin.productMenu", + title: "core.routes.category.contributions.title", path: "/contributionPlans", + subtitle: "core.routes.category.contributions.subtitle", }, { - parent: "Category des assurés", - title: "Taux/forfait cotisations", + parent: "admin.productMenu", + title: "core.routes.category.contributionBundles.title", path: "/contributionPlanBundles", + subtitle: "core.routes.category.contributionBundles.subtitle", + }, + { + parent: "admin.productMenu", + path: "/front/admin/products", + title: "core.routes.category.adminProducts.title", + subtitle: "core.routes.category.adminProducts.subtitle", + }, + { + parent: "admin.productMenu", + path: "/admin/declarations-audit", + title: "core.routes.category.declarationsAudit.title", + subtitle: "core.routes.category.declarationsAudit.subtitle", }, ]; const fosa = [ { - parent: "Fosa", - title: "Formation sanitaire", + parent: "admin.fosaMenu", + title: "admin.menu.healthFacilities", path: "/location/healthFacilities", + subtitle: "core.routes.fosa.healthFacilities.subtitle", }, { - parent: "Fosa", - title: "Paquet de soins : actes des soins", + parent: "admin.fosaMenu", + title: "admin.menu.medicalServicesPrices", path: "/medical/pricelists/services", + subtitle: "core.routes.fosa.medicalServicesPrices.subtitle", }, { - parent: "Fosa", - title: "Paquet de soins: produits medicaux", + parent: "admin.fosaMenu", + title: "admin.menu.medicalItemsPrices", path: "/medical/pricelists/items", + subtitle: "core.routes.fosa.medicalItemsPrices.subtitle", }, { - parent: "Fosa", - title: "Actes des soins", + parent: "admin.fosaMenu", + title: "admin.menu.medicalServices", path: "/medical/medicalServices", + subtitle: "core.routes.fosa.medicalServices.subtitle", }, { - parent: "Fosa", - title: "Produits medicaux", + parent: "admin.fosaMenu", + title: "admin.menu.medicalItems", path: "/medical/medicalItems", + subtitle: "core.routes.fosa.medicalItems.subtitle", }, { - parent: "Fosa", - title: "Verification", + parent: "admin.fosaMenu", + title: "core.routes.fosa.verification.title", path: "/insuree/insurees/verifyinsuree", + subtitle: "core.routes.fosa.verification.subtitle", + }, + { + parent: "admin.fosaMenu", + title: "core.routes.fosa.userFunctionalities.title", + path: "/fosa/user-functionalities", + subtitle: "core.routes.fosa.userFunctionalities.subtitle", + }, + { + parent: "admin.fosaMenu", + title: "core.routes.fosa.userSpecialties.title", + path: "/fosa/user-specialties", + subtitle: "core.routes.fosa.userSpecialties.subtitle", + }, + { + parent: "admin.fosaMenu", + title: "admin.menu.mainDiagnoses", + path: "/medical/medicalPathologies", + subtitle: "core.routes.fosa.pathologies.subtitle", + }, + { + parent: "admin.fosaMenu", + title: "core.routes.fosa.pathologiesBundle.title", + path: "/medical/medicalPathologiesBundle", + subtitle: "core.routes.fosa.pathologiesBundle.subtitle", + }, + { + parent: "admin.fosaMenu", + title: "admin.menu.conventionnements", + path: "/location/conventionnements", + subtitle: "core.routes.fosa.conventionnements.subtitle", + }, + { + parent: "admin.fosaMenu", + path: "/claim/preauthorization", + title: "core.routes.fosa.preauthorization.title", + subtitle: "core.routes.fosa.preauthorization.subtitle", + }, + { + parent: "admin.fosaMenu", + path: "/claim/preauthorization/approval", + title: "core.routes.fosa.preauthorizationApproval.title", + subtitle: "core.routes.fosa.preauthorizationApproval.subtitle", + }, +]; + +const location = [ + { + parent: "core.routes.location.mainMenu", + title: "core.routes.location.title", + path: "/location", + subtitle: "core.routes.location.subtitle", }, ]; const outils = [ { - parent: "Outils", + parent: "tools.mainMenu", path: "/tools/registers", - title: "Registres", + title: "tools.menu.registers", + subtitle: "core.routes.tools.registers.subtitle", }, { - parent: "Outils", + parent: "tools.mainMenu", path: "/tools/extracts", - title: "Extraits", + title: "tools.menu.extracts", + subtitle: "core.routes.tools.extracts.subtitle", }, { - parent: "Outils", + parent: "tools.mainMenu", path: "/tools/reports", - title: "Rapports", + title: "core.routes.tools.reports.title", + subtitle: "core.routes.tools.reports.subtitle", }, { - parent: "Outils", + parent: "tools.mainMenu", path: "/tools/manualSync", - title: "Manuels Synchronisation", + title: "core.routes.tools.manualSync.title", + subtitle: "core.routes.tools.manualSync.subtitle", }, ]; const profile = [ { - parent: "Profil", + parent: "profile.mainMenu", + path: "/profile", + title: "core.routes.profile.main.title", + subtitle: "core.routes.profile.main.subtitle", + }, + { + parent: "profile.mainMenu", path: "/profile/myProfile", - title: "Information", + title: "profile.menu.myProfile", + subtitle: "core.routes.profile.myProfile.subtitle", }, { - parent: "Profil", + parent: "profile.mainMenu", path: "/profile/changePassword", - title: "Changer mot de passe", + title: "profile.menu.changePassword", + subtitle: "core.routes.profile.changePassword.subtitle", + }, +]; + +const souscripteursBase = [ + { + parent: "core.routes.policyholder.mainMenu", + path: "/souscripteurs", + title: "core.routes.policyholder.title", + subtitle: "core.routes.policyholder.subtitle", }, ]; const souscripteurs = [ { - parent: "Souscripteurs", + parent: "policyHolder.mainmenu", path: "/contribution/contributions", - title: "Contributions", + title: "policy.menu.contributions", + subtitle: "core.routes.policyholder.contributions.subtitle", }, { - parent: "Souscripteurs", + parent: "policyHolder.mainmenu", path: "/policyHolders", - title: "Immatriculation", - }, - { - parent: "Souscripteurs", - path: "/contribution/contributions", - title: "Contributions", + title: "core.routes.policyholder.registration.title", + subtitle: "core.routes.policyholder.registration.subtitle", }, { - parent: "Souscripteurs", + parent: "policyHolder.mainmenu", path: "/payment/payments", - title: "Recouvrements", + title: "payment.menu.payments", + subtitle: "core.routes.policyholder.recoveries.subtitle", }, { - parent: "Souscripteurs", + parent: "policyHolder.mainmenu", path: "/paymentApproval", - title: "Paiement par approbation", + title: "policyHolder.menu.paymentForApproval", + subtitle: "core.routes.policyholder.paymentApproval.subtitle", }, { - parent: "Souscripteurs", + parent: "policyHolder.mainmenu", path: "/contracts", - title: "Déclaration", + title: "core.routes.policyholder.declaration.title", + subtitle: "core.routes.policyholder.declaration.subtitle", }, { - parent: "Souscripteurs", + parent: "policyHolder.mainmenu", path: "/declaration", - title: "Rapport de déclaration", + title: "core.routes.policyholder.declarationReport.title", + subtitle: "core.routes.policyholder.declarationReport.subtitle", }, { - parent: "Souscripteurs", + parent: "policyHolder.mainmenu", path: "/policyholderRequest", - title: "Nouveau souscripteur demandes", + title: "core.routes.policyholder.newRequests.title", + subtitle: "core.routes.policyholder.newRequests.subtitle", }, ]; const juridique = [ { - parent: "Juridique et financier", + parent: "core.routes.legal.mainMenu", path: "/invoices", - title: "Factures", + title: "core.routes.legal.invoices.title", + subtitle: "core.routes.legal.invoices.subtitle", }, { - parent: "Juridique et financier", + parent: "core.routes.legal.mainMenu", path: "/bills", - title: "Factures", + title: "core.routes.legal.bills.title", + subtitle: "core.routes.legal.bills.subtitle", }, { - parent: "Juridique et financier", + parent: "core.routes.legal.mainMenu", path: "/paymentPlans", - title: "Plans de paiement", + title: "core.routes.legal.paymentPlans.title", + subtitle: "core.routes.legal.paymentPlans.subtitle", }, { - parent: "Juridique et financier", + parent: "core.routes.legal.mainMenu", path: "/payment/paymentpenalty", - title: "Pénalité de sanction", + title: "core.routes.legal.penalty.title", + subtitle: "core.routes.legal.penalty.subtitle", }, ]; const exceptions = [ { - parent: "Exceptions", + parent: "core.routes.exceptions.mainMenu", path: "/exception", - title: "Exception pour les assurés", + title: "core.routes.exceptions.insuree.title", + subtitle: "core.routes.exceptions.insuree.subtitle", }, { - parent: "Exceptions", + parent: "core.routes.exceptions.mainMenu", path: "/exception/policyholder", - title: "Exception pour les souscripteurs", + title: "core.routes.exceptions.policyholder.title", + subtitle: "core.routes.exceptions.policyholder.subtitle", }, { - parent: "Exceptions", + parent: "core.routes.exceptions.mainMenu", path: "/exception/pendingapproval", - title: "En attente d'approbation", + title: "core.routes.exceptions.pendingApproval.title", + subtitle: "core.routes.exceptions.pendingApproval.subtitle", }, ]; export const routePages = [ { - "path": "home", - "title": "", - "parent": "", + path: "/home", + title: "core.routes.home.title", + parent: "core.routes.home.parent", + subtitle: "core.routes.home.subtitle", }, ...affiliation, ...demandePayement, ...administration, ...category, ...fosa, + ...location, ...outils, ...profile, + ...souscripteursBase, ...souscripteurs, ...juridique, ...exceptions, diff --git a/src/components/hooks/usePageTitle.js b/src/components/hooks/usePageTitle.js index 337ae3de..15bae634 100644 --- a/src/components/hooks/usePageTitle.js +++ b/src/components/hooks/usePageTitle.js @@ -1,28 +1,102 @@ import React from "react"; +import { useIntl } from "react-intl"; import { useLocation } from "react-router-dom"; import { routePages } from "../hooks/routes"; +const compareRoutesByLength = (firstRoute, secondRoute) => { + const firstRoutePath = firstRoute.path || ""; + const secondRoutePath = secondRoute.path || ""; + return secondRoutePath.length - firstRoutePath.length; +}; + +const isExactMatch = (routePath, currentPathname) => { + return routePath === currentPathname; +}; + +const isParameterizedMatch = (routePath, currentPathname) => { + const pathPattern = routePath.replace(/:[^/]+/g, "[^/]+"); + const regex = new RegExp(`^${pathPattern}(/.*)?$`); + return regex.test(currentPathname); +}; + +const isPrefixMatch = (routePath, currentPathname, allRoutes) => { + if (!currentPathname.startsWith(routePath) || routePath === "/") { + return false; + } + + const hasMoreSpecificMatch = allRoutes.some((otherRoute) => { + const otherRoutePath = otherRoute.path; + if (!otherRoutePath || otherRoutePath === routePath) { + return false; + } + + if (otherRoutePath.length > routePath.length && currentPathname.startsWith(otherRoutePath)) { + const nextChar = currentPathname[otherRoutePath.length]; + if (nextChar === "/" || nextChar === undefined) { + return true; + } + } + return false; + }); + + if (hasMoreSpecificMatch) { + return false; + } + + const nextChar = currentPathname[routePath.length]; + return nextChar === "/" || nextChar === undefined; +}; + +const doesRouteMatch = (route, currentPathname, allRoutes) => { + const routePath = route.path; + if (!routePath) { + return false; + } + + return ( + isExactMatch(routePath, currentPathname) || + isParameterizedMatch(routePath, currentPathname) || + isPrefixMatch(routePath, currentPathname, allRoutes) + ); +}; + +const findMatchingRoute = (routes, currentPathname) => { + const sortedRoutes = [...routes].sort(compareRoutesByLength); + return sortedRoutes.find((route) => doesRouteMatch(route, currentPathname, sortedRoutes)) || null; +}; + function UsePageTitle() { const location = useLocation(); const { pathname } = location; - const [page, setPage] = React.useState({}); + const intl = useIntl(); + const [page, setPage] = React.useState({ path: pathname }); React.useEffect(() => { - const routes = routePages.find((item) => { - if (item.path === pathname) { - return item; - } + const matchedRoute = findMatchingRoute(routePages, pathname); - if (pathname.startsWith(item.path)) { - return item; - } + if (matchedRoute) { + const translateKey = (key) => { + if (!key) return key; + try { + const translated = intl.formatMessage({ id: key }); + return translated !== key ? translated : key; + } catch { + return key; + } + }; - return null; - }); - if (routes) { - setPage((prev) => ({ ...routes })); + const translatedRoute = { + ...matchedRoute, + path: pathname, + parent: translateKey(matchedRoute.parent), + title: translateKey(matchedRoute.title), + subtitle: translateKey(matchedRoute.subtitle), + }; + setPage((previousPage) => translatedRoute); + } else { + setPage({ path: pathname }); } - }, [pathname]); + }, [pathname, intl]); return page; } diff --git a/src/translations/en.json b/src/translations/en.json index c08c25fa..f9072ea5 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -75,5 +75,115 @@ "core.common.Copy": "Copy", "core.title": "Notifications", "core.clearAll": "Clear All", - "core.emptyNotification": "No Notification" + "core.emptyNotification": "No Notification", + "core.routes.home.parent": "CAMU IMS", + "core.routes.home.title": "Home", + "core.routes.home.subtitle": "Main dashboard", + "core.routes.affiliation.families.subtitle": "Manage and view insured families", + "core.routes.affiliation.insurees.subtitle": "Manage and view individual insureds", + "core.routes.affiliation.policies.subtitle": "Manage insurance policies", + "core.routes.affiliation.assignment.title": "User assignment", + "core.routes.affiliation.assignment.subtitle": "Assign users to pending approvals", + "core.routes.administration.users.subtitle": "Manage system users", + "core.routes.administration.bank.title": "Bank", + "core.routes.administration.bank.subtitle": "Manage banking information", + "core.routes.administration.fosaCategories.title": "FOSA Categories", + "core.routes.administration.fosaCategories.subtitle": "Configure health facility categories", + "core.routes.administration.operations.title": "Operation Management", + "core.routes.administration.operations.subtitle": "Manage system operations", + "core.routes.administration.medicalServices.title": "Medical services category management", + "core.routes.administration.medicalServices.subtitle": "Manage medical service categories", + "core.routes.administration.locations.subtitle": "Manage geographic locations", + "core.routes.administration.centers.title": "Centers", + "core.routes.administration.centers.subtitle": "Manage geographic centers", + "core.routes.administration.roles.title": "Role Management", + "core.routes.administration.roles.subtitle": "Manage roles and permissions", + "core.routes.administration.policyholderAdmins.title": "Policyholder Administrators", + "core.routes.administration.policyholderAdmins.subtitle": "Manage policyholder administrators", + "core.routes.administration.dashboard.title": "Dashboard", + "core.routes.administration.dashboard.subtitle": "Administrative dashboard", + "core.routes.administration.fosaUsers.title": "FOSA Users", + "core.routes.administration.fosaUsers.subtitle": "Manage health facility users", + "core.routes.administration.policyholderUsers.title": "Policyholder Users", + "core.routes.administration.policyholderUsers.subtitle": "Manage policyholder users", + "core.routes.administration.fosaUserFunctionalities.title": "FOSA User Functionalities", + "core.routes.administration.fosaUserFunctionalities.subtitle": "Manage FOSA user functionalities", + "core.routes.administration.fosaUserSpecialties.title": "FOSA User Specialties", + "core.routes.administration.fosaUserSpecialties.subtitle": "Manage FOSA user specialties", + "core.routes.payment.reviews.subtitle": "Control and approve invoices for payment", + "core.routes.payment.batch.subtitle": "Evaluate payment requests by batch", + "core.routes.payment.requests.subtitle": "Manage health facility payment requests", + "core.routes.payment.invoices.title": "Invoices", + "core.routes.payment.invoices.subtitle": "Approve and manage invoices", + "core.routes.category.products.subtitle": "Manage insured categories", + "core.routes.category.contributions.title": "Contributions", + "core.routes.category.contributions.subtitle": "Manage contribution plans", + "core.routes.category.contributionBundles.title": "Contribution rates/bundles", + "core.routes.category.contributionBundles.subtitle": "Manage contribution rates and bundles", + "core.routes.category.adminProducts.title": "Products", + "core.routes.category.adminProducts.subtitle": "Manage administrative products", + "core.routes.category.declarationsAudit.title": "Declarations Audit", + "core.routes.category.declarationsAudit.subtitle": "View declarations audit", + "core.routes.fosa.healthFacilities.subtitle": "Manage health facilities", + "core.routes.fosa.medicalServicesPrices.subtitle": "Manage care packages for medical acts", + "core.routes.fosa.medicalItemsPrices.subtitle": "Manage care packages for medical products", + "core.routes.fosa.medicalServices.subtitle": "Manage available medical acts", + "core.routes.fosa.medicalItems.subtitle": "Manage available medical products", + "core.routes.fosa.verification.title": "Verification", + "core.routes.fosa.verification.subtitle": "Verify insured eligibility", + "core.routes.fosa.userFunctionalities.title": "User Functionalities", + "core.routes.fosa.userFunctionalities.subtitle": "Manage FOSA user functionalities", + "core.routes.fosa.userSpecialties.title": "User Specialties", + "core.routes.fosa.userSpecialties.subtitle": "Manage FOSA user specialties", + "core.routes.fosa.pathologies.subtitle": "Manage medical pathologies", + "core.routes.fosa.pathologiesBundle.title": "Pathology Bundles", + "core.routes.fosa.pathologiesBundle.subtitle": "Manage medical pathology bundles", + "core.routes.fosa.conventionnements.subtitle": "Manage health facility agreements", + "core.routes.fosa.preauthorization.title": "Pre-authorization", + "core.routes.fosa.preauthorization.subtitle": "Manage pre-authorization requests", + "core.routes.fosa.preauthorizationApproval.title": "Pre-authorization Approval", + "core.routes.fosa.preauthorizationApproval.subtitle": "Approve pre-authorization requests", + "core.routes.location.mainMenu": "Location", + "core.routes.location.title": "Location", + "core.routes.location.subtitle": "Manage locations", + "core.routes.tools.registers.subtitle": "View and manage registers", + "core.routes.tools.extracts.subtitle": "Generate and view extracts", + "core.routes.tools.reports.title": "Reports", + "core.routes.tools.reports.subtitle": "Generate and view reports", + "core.routes.tools.manualSync.title": "Manual Synchronization", + "core.routes.tools.manualSync.subtitle": "Perform manual synchronizations", + "core.routes.profile.main.title": "Profile", + "core.routes.profile.main.subtitle": "Manage your user profile", + "core.routes.profile.myProfile.subtitle": "View and modify your personal information", + "core.routes.profile.changePassword.subtitle": "Change your password", + "core.routes.policyholder.mainMenu": "Policyholders", + "core.routes.policyholder.title": "Policyholders", + "core.routes.policyholder.subtitle": "Manage policyholders", + "core.routes.policyholder.contributions.subtitle": "Manage policyholder contributions", + "core.routes.policyholder.registration.title": "Registration", + "core.routes.policyholder.registration.subtitle": "Manage policyholder registration", + "core.routes.policyholder.recoveries.subtitle": "Manage payment recoveries", + "core.routes.policyholder.paymentApproval.subtitle": "Approve policyholder payments", + "core.routes.policyholder.declaration.title": "Declaration", + "core.routes.policyholder.declaration.subtitle": "Manage contract declarations", + "core.routes.policyholder.declarationReport.title": "Declaration Report", + "core.routes.policyholder.declarationReport.subtitle": "View declaration reports", + "core.routes.policyholder.newRequests.title": "New Policyholder Requests", + "core.routes.policyholder.newRequests.subtitle": "Manage new policyholder requests", + "core.routes.legal.mainMenu": "Legal and Financial", + "core.routes.legal.invoices.title": "Invoices", + "core.routes.legal.invoices.subtitle": "Manage system invoices", + "core.routes.legal.bills.title": "Bills", + "core.routes.legal.bills.subtitle": "View and manage bills", + "core.routes.legal.paymentPlans.title": "Payment Plans", + "core.routes.legal.paymentPlans.subtitle": "Manage payment plans", + "core.routes.legal.penalty.title": "Penalty and Sanction", + "core.routes.legal.penalty.subtitle": "Manage payment penalties and sanctions", + "core.routes.exceptions.mainMenu": "Exceptions", + "core.routes.exceptions.insuree.title": "Exception for Insureds", + "core.routes.exceptions.insuree.subtitle": "Manage exceptions for insureds", + "core.routes.exceptions.policyholder.title": "Exception for Policyholders", + "core.routes.exceptions.policyholder.subtitle": "Manage exceptions for policyholders", + "core.routes.exceptions.pendingApproval.title": "Pending Approval", + "core.routes.exceptions.pendingApproval.subtitle": "View exceptions pending approval" } diff --git a/src/translations/fr.json b/src/translations/fr.json index 8a1a37b3..9faf552e 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -1,17 +1,127 @@ { - "core.ForgotPasswordPage.backButton": "Retour à la connexion", - "core.SetPasswordPage.pageTitle": "Définir un nouveau mot de passe", - "core.SetPasswordPage.username.label": "Nom d'utilisateur", - "core.SetPasswordPage.password.label": "Mot de passe", - "core.SetPasswordPage.confirmPassword.label": "Confirmer le mot de passe", - "core.SetPasswordPage.error": "Unknown error", - "core.SetPasswordPage.submitBtn": "Soumettre", - "core.ForgotPasswordPage.pageTitle": "Mot de passe oublié ?", - "core.ForgotPasswordPage.submitBtn": "Soumettre", - "core.ForgotPasswordPage.username.label": "Nom d'utilisateur", - "core.ForgotPasswordPage.done": "Done ! Check your inbox and click on the verification link to reset your password.", - "core.ForgotPasswordPage.done.Verification": "Un e-mail contenant le lien de vérification a été envoyé à votre adresse e-mail", - "core.ForgotPasswordPage.done.Administrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur", - "core.ForgotPasswordPage.recoverTitle": "Récupérer votre compte", - "core.ForgotPasswordPage.explanationMessage": "Saisissez votre nom d'utilisateur pour pouvoir récupérer votre compte. Un e-mail contenant les instructions sera envoyé à votre adresse e-mail." -} \ No newline at end of file + "core.ForgotPasswordPage.backButton": "Retour à la connexion", + "core.SetPasswordPage.pageTitle": "Définir un nouveau mot de passe", + "core.SetPasswordPage.username.label": "Nom d'utilisateur", + "core.SetPasswordPage.password.label": "Mot de passe", + "core.SetPasswordPage.confirmPassword.label": "Confirmer le mot de passe", + "core.SetPasswordPage.error": "Unknown error", + "core.SetPasswordPage.submitBtn": "Soumettre", + "core.ForgotPasswordPage.pageTitle": "Mot de passe oublié ?", + "core.ForgotPasswordPage.submitBtn": "Soumettre", + "core.ForgotPasswordPage.username.label": "Nom d'utilisateur", + "core.ForgotPasswordPage.done": "Done ! Check your inbox and click on the verification link to reset your password.", + "core.ForgotPasswordPage.done.Verification": "Un e-mail contenant le lien de vérification a été envoyé à votre adresse e-mail", + "core.ForgotPasswordPage.done.Administrator": "Si vous ne recevez pas d'e-mail, veuillez contacter votre administrateur", + "core.ForgotPasswordPage.recoverTitle": "Récupérer votre compte", + "core.ForgotPasswordPage.explanationMessage": "Saisissez votre nom d'utilisateur pour pouvoir récupérer votre compte. Un e-mail contenant les instructions sera envoyé à votre adresse e-mail.", + "core.routes.home.parent": "CAMU IMS", + "core.routes.home.title": "Accueil", + "core.routes.home.subtitle": "Tableau de bord principal", + "core.routes.affiliation.families.subtitle": "Gérer et consulter les familles d'assurés", + "core.routes.affiliation.insurees.subtitle": "Gérer et consulter les assurés individuels", + "core.routes.affiliation.policies.subtitle": "Gérer les polices d'assurance", + "core.routes.affiliation.assignment.title": "Affectation d'un utilisateur", + "core.routes.affiliation.assignment.subtitle": "Affecter des utilisateurs aux approbations en attente", + "core.routes.administration.users.subtitle": "Gérer les utilisateurs du système", + "core.routes.administration.bank.title": "Bank", + "core.routes.administration.bank.subtitle": "Gérer les informations bancaires", + "core.routes.administration.fosaCategories.title": "Catégories des Fosa", + "core.routes.administration.fosaCategories.subtitle": "Configurer les catégories des formations sanitaires", + "core.routes.administration.operations.title": "Opération Management", + "core.routes.administration.operations.subtitle": "Gérer les opérations du système", + "core.routes.administration.medicalServices.title": "Medical services category management", + "core.routes.administration.medicalServices.subtitle": "Gérer les catégories de services médicaux", + "core.routes.administration.locations.subtitle": "Gérer les localisations géographiques", + "core.routes.administration.centers.title": "Centres", + "core.routes.administration.centers.subtitle": "Gérer les centres géographiques", + "core.routes.administration.roles.title": "Gestion des roles", + "core.routes.administration.roles.subtitle": "Gérer les rôles et permissions", + "core.routes.administration.policyholderAdmins.title": "Administrateurs souscripteurs", + "core.routes.administration.policyholderAdmins.subtitle": "Gérer les administrateurs des souscripteurs", + "core.routes.administration.dashboard.title": "Dashboard", + "core.routes.administration.dashboard.subtitle": "Tableau de bord administratif", + "core.routes.administration.fosaUsers.title": "Utilisateurs Fosa", + "core.routes.administration.fosaUsers.subtitle": "Gérer les utilisateurs des formations sanitaires", + "core.routes.administration.policyholderUsers.title": "Utilisateurs souscripteurs", + "core.routes.administration.policyholderUsers.subtitle": "Gérer les utilisateurs des souscripteurs", + "core.routes.administration.fosaUserFunctionalities.title": "Fonctionnalités utilisateur FOSA", + "core.routes.administration.fosaUserFunctionalities.subtitle": "Gérer les fonctionnalités des utilisateurs FOSA", + "core.routes.administration.fosaUserSpecialties.title": "Spécialités utilisateur FOSA", + "core.routes.administration.fosaUserSpecialties.subtitle": "Gérer les spécialités des utilisateurs FOSA", + "core.routes.payment.reviews.subtitle": "Contrôler et approuver les factures pour paiement", + "core.routes.payment.batch.subtitle": "Évaluer les demandes de paiement par lots", + "core.routes.payment.requests.subtitle": "Gérer les demandes de paiement des formations sanitaires", + "core.routes.payment.invoices.title": "Invoices", + "core.routes.payment.invoices.subtitle": "Approuver et gérer les factures", + "core.routes.category.products.subtitle": "Gérer les catégories d'assurés", + "core.routes.category.contributions.title": "Cotisations", + "core.routes.category.contributions.subtitle": "Gérer les plans de cotisation", + "core.routes.category.contributionBundles.title": "Taux/forfait cotisations", + "core.routes.category.contributionBundles.subtitle": "Gérer les taux et forfaits de cotisation", + "core.routes.category.adminProducts.title": "Produits", + "core.routes.category.adminProducts.subtitle": "Gérer les produits administratifs", + "core.routes.category.declarationsAudit.title": "Audit des déclarations", + "core.routes.category.declarationsAudit.subtitle": "Consulter l'audit des déclarations", + "core.routes.fosa.healthFacilities.subtitle": "Gérer les formations sanitaires", + "core.routes.fosa.medicalServicesPrices.subtitle": "Gérer les paquets de soins pour les actes médicaux", + "core.routes.fosa.medicalItemsPrices.subtitle": "Gérer les paquets de soins pour les produits médicaux", + "core.routes.fosa.medicalServices.subtitle": "Gérer les actes médicaux disponibles", + "core.routes.fosa.medicalItems.subtitle": "Gérer les produits médicaux disponibles", + "core.routes.fosa.verification.title": "Verification", + "core.routes.fosa.verification.subtitle": "Vérifier l'éligibilité des assurés", + "core.routes.fosa.userFunctionalities.title": "Fonctionnalités utilisateur", + "core.routes.fosa.userFunctionalities.subtitle": "Gérer les fonctionnalités des utilisateurs FOSA", + "core.routes.fosa.userSpecialties.title": "Spécialités utilisateur", + "core.routes.fosa.userSpecialties.subtitle": "Gérer les spécialités des utilisateurs FOSA", + "core.routes.fosa.pathologies.subtitle": "Gérer les pathologies médicales", + "core.routes.fosa.pathologiesBundle.title": "Paquets de pathologies", + "core.routes.fosa.pathologiesBundle.subtitle": "Gérer les paquets de pathologies médicales", + "core.routes.fosa.conventionnements.subtitle": "Gérer les conventionnements des formations sanitaires", + "core.routes.fosa.preauthorization.title": "Pré-autorisation", + "core.routes.fosa.preauthorization.subtitle": "Gérer les demandes de pré-autorisation", + "core.routes.fosa.preauthorizationApproval.title": "Approbation pré-autorisation", + "core.routes.fosa.preauthorizationApproval.subtitle": "Approuver les demandes de pré-autorisation", + "core.routes.location.mainMenu": "Localisation", + "core.routes.location.title": "Localisation", + "core.routes.location.subtitle": "Gérer les localisations", + "core.routes.tools.registers.subtitle": "Consulter et gérer les registres", + "core.routes.tools.extracts.subtitle": "Générer et consulter les extraits", + "core.routes.tools.reports.title": "Rapports", + "core.routes.tools.reports.subtitle": "Générer et consulter les rapports", + "core.routes.tools.manualSync.title": "Manuels Synchronisation", + "core.routes.tools.manualSync.subtitle": "Effectuer des synchronisations manuelles", + "core.routes.profile.main.title": "Profil", + "core.routes.profile.main.subtitle": "Gérer votre profil utilisateur", + "core.routes.profile.myProfile.subtitle": "Consulter et modifier vos informations personnelles", + "core.routes.profile.changePassword.subtitle": "Modifier votre mot de passe", + "core.routes.policyholder.mainMenu": "Souscripteurs", + "core.routes.policyholder.title": "Souscripteurs", + "core.routes.policyholder.subtitle": "Gérer les souscripteurs", + "core.routes.policyholder.contributions.subtitle": "Gérer les contributions des souscripteurs", + "core.routes.policyholder.registration.title": "Immatriculation", + "core.routes.policyholder.registration.subtitle": "Gérer l'immatriculation des souscripteurs", + "core.routes.policyholder.recoveries.subtitle": "Gérer les recouvrements de paiement", + "core.routes.policyholder.paymentApproval.subtitle": "Approuver les paiements des souscripteurs", + "core.routes.policyholder.declaration.title": "Déclaration", + "core.routes.policyholder.declaration.subtitle": "Gérer les déclarations de contrat", + "core.routes.policyholder.declarationReport.title": "Rapport de déclaration", + "core.routes.policyholder.declarationReport.subtitle": "Consulter les rapports de déclaration", + "core.routes.policyholder.newRequests.title": "Nouveau souscripteur demandes", + "core.routes.policyholder.newRequests.subtitle": "Gérer les demandes de nouveaux souscripteurs", + "core.routes.legal.mainMenu": "Juridique et financier", + "core.routes.legal.invoices.title": "Factures", + "core.routes.legal.invoices.subtitle": "Gérer les factures du système", + "core.routes.legal.bills.title": "Factures", + "core.routes.legal.bills.subtitle": "Consulter et gérer les factures", + "core.routes.legal.paymentPlans.title": "Plans de paiement", + "core.routes.legal.paymentPlans.subtitle": "Gérer les plans de paiement", + "core.routes.legal.penalty.title": "Pénalité de sanction", + "core.routes.legal.penalty.subtitle": "Gérer les pénalités et sanctions de paiement", + "core.routes.exceptions.mainMenu": "Exceptions", + "core.routes.exceptions.insuree.title": "Exception pour les assurés", + "core.routes.exceptions.insuree.subtitle": "Gérer les exceptions pour les assurés", + "core.routes.exceptions.policyholder.title": "Exception pour les souscripteurs", + "core.routes.exceptions.policyholder.subtitle": "Gérer les exceptions pour les souscripteurs", + "core.routes.exceptions.pendingApproval.title": "En attente d'approbation", + "core.routes.exceptions.pendingApproval.subtitle": "Consulter les exceptions en attente d'approbation" +} From 9f3815abcbbf93cf293dae13ad0348777e204813 Mon Sep 17 00:00:00 2001 From: Christoffert Moussounda Date: Mon, 22 Dec 2025 09:59:05 +0100 Subject: [PATCH 109/111] feat: add health service management route to Fosa section --- src/components/hooks/routes.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/hooks/routes.js b/src/components/hooks/routes.js index fdbf717d..75bc89b0 100644 --- a/src/components/hooks/routes.js +++ b/src/components/hooks/routes.js @@ -151,6 +151,11 @@ const fosa = [ title: "Produits medicaux", path: "/medical/medicalItems", }, + { + parent: "Fosa", + title: "Gestion des Actes de Soins", + path: "/healthServiceManagement", + }, { parent: "Fosa", title: "Verification", From 2ccb760dcefa26c42044514d8009f44d3cf288e3 Mon Sep 17 00:00:00 2001 From: sancty Date: Mon, 22 Dec 2025 13:59:17 +0100 Subject: [PATCH 110/111] style: enhance button and menu item transitions for improved user experience - Added transition effects for background color on buttons and menu items across various components. - Updated LogoutButton and MainMenuContribution to include hover effects for better interactivity. - Refactored RequireAuth and PageTitle components to streamline imports and improve readability. - Adjusted translations for home route subtitles in both English and French to remove default text. --- src/components/App.css | 6 ++ src/components/LogoutButton.js | 10 +++- src/components/RequireAuth.js | 59 +++++++++++-------- .../generics/MainMenuContribution.js | 57 +++++++++++++++++- src/components/hooks/pageTitle.js | 16 ++++- src/translations/en.json | 2 +- src/translations/fr.json | 2 +- 7 files changed, 119 insertions(+), 33 deletions(-) diff --git a/src/components/App.css b/src/components/App.css index b41d297c..32a427ba 100644 --- a/src/components/App.css +++ b/src/components/App.css @@ -31,3 +31,9 @@ transform: rotate(360deg); } } + +.MuiMenuItem-root, +.MuiListItem-button, +.MuiButton-root { + transition: background-color 0.3s ease !important; +} diff --git a/src/components/LogoutButton.js b/src/components/LogoutButton.js index eadc2cb4..68968d36 100644 --- a/src/components/LogoutButton.js +++ b/src/components/LogoutButton.js @@ -1,8 +1,8 @@ -import React from "react"; -import { makeStyles } from "@material-ui/core/styles"; -import { useDispatch,useSelector } from "react-redux"; import { IconButton } from "@material-ui/core"; +import { makeStyles } from "@material-ui/core/styles"; import { ExitToApp } from "@material-ui/icons"; +import React from "react"; +import { useDispatch, useSelector } from "react-redux"; import { CheckAssignedProfile, logout } from "../actions"; import { useHistory } from "../helpers/history"; @@ -10,6 +10,10 @@ const useStyles = makeStyles((theme) => ({ button: { margin: theme.spacing(2), color: theme.palette.secondary.main, + transition: "background-color 0.3s ease", + "&:hover": { + backgroundColor: "rgba(255, 159, 28, 0.2)", + }, }, })); diff --git a/src/components/RequireAuth.js b/src/components/RequireAuth.js index be961346..8abd29d7 100644 --- a/src/components/RequireAuth.js +++ b/src/components/RequireAuth.js @@ -1,39 +1,36 @@ -import React, { useMemo, useState, useEffect } from "react"; -import { BrowserRouter as Router, Switch, Route, Link, useRouteMatch, useParams, useLocation } from "react-router-dom"; +import React, { useEffect, useMemo, useState } from "react"; +import { useLocation } from "react-router-dom"; -import withWidth from "@material-ui/core/withWidth"; -import { Redirect } from "../helpers/history"; -import { alpha, useTheme, makeStyles } from "@material-ui/core/styles"; -import { useModulesManager } from "../helpers/modules"; -import LogoutButton from "./LogoutButton"; -import Help from "../pages/Help"; -import clsx from "clsx"; import { AppBar, - Toolbar, - IconButton, - Typography, - Drawer, - Divider, - Tooltip, Button, - Hidden, ClickAwayListener, + Divider, + Drawer, + Hidden, + IconButton, + Toolbar, + Tooltip, + Typography, } from "@material-ui/core"; +import { alpha, makeStyles, useTheme } from "@material-ui/core/styles"; +import withWidth from "@material-ui/core/withWidth"; import MenuIcon from "@material-ui/icons/Menu"; -import Contributions from "./generics/Contributions"; -import FormattedMessage from "./generics/FormattedMessage"; -import JournalDrawer from "./JournalDrawer"; -import { useBoolean, useAuthentication } from "../helpers/hooks"; -import { useGraphqlQuery } from "@openimis/fe-core"; -import { formatMessageWithValues, withModulesManager, withHistory, historyPush } from "@openimis/fe-core"; import NotificationsIcon from "@material-ui/icons/Notifications"; -import { useDispatch, useSelector } from "react-redux"; +import { useGraphqlQuery } from "@openimis/fe-core"; +import clsx from "clsx"; import { useIdleTimer } from "react-idle-timer/dist/index.legacy.cjs.js"; // otherwise not building: https://github.com/SupremeTechnopriest/react-idle-timer/issues/350 +import { useDispatch, useSelector } from "react-redux"; import { CheckAssignedProfile, logout } from "../actions"; +import { Redirect } from "../helpers/history"; +import { useAuthentication, useBoolean } from "../helpers/hooks"; +import { useModulesManager } from "../helpers/modules"; import NotificationDialog from "./dialogs/NotificationDialog"; -import PageTitle from "./hooks/pageTitle"; import GedAlertBanner from "./GedAlertBanner"; +import Contributions from "./generics/Contributions"; +import PageTitle from "./hooks/pageTitle"; +import JournalDrawer from "./JournalDrawer"; +import LogoutButton from "./LogoutButton"; // npm i cookie_js import cookie from "cookie_js"; @@ -71,6 +68,10 @@ const useStyles = makeStyles((theme) => ({ menuButton: { margin: theme.spacing(0, 1, 0, 1), padding: 0, + transition: "background-color 0.3s ease", + "&:hover": { + backgroundColor: "rgba(255, 159, 28, 0.2)", + }, }, autoHideMenuButton: { [theme.breakpoints.up("md")]: { @@ -113,6 +114,10 @@ const useStyles = makeStyles((theme) => ({ color: theme.palette.secondary.main, textTransform: "none", fontSize: theme.typography.title.fontSize, + transition: "background-color 0.3s ease", + "&:hover": { + backgroundColor: "rgba(255, 159, 28, 0.2)", + }, }, appVersionsBox: { padding: 0, @@ -167,6 +172,12 @@ const useStyles = makeStyles((theme) => ({ position: "relative", cursor: "pointer", margin: "3px 9px 0 0", + padding: "8px", + borderRadius: "50%", + transition: "background-color 0.3s ease", + "&:hover": { + backgroundColor: "rgba(255, 159, 28, 0.2)", + }, }, iconBtn: { position: "absolute", diff --git a/src/components/generics/MainMenuContribution.js b/src/components/generics/MainMenuContribution.js index 7738a279..c49e6ba4 100644 --- a/src/components/generics/MainMenuContribution.js +++ b/src/components/generics/MainMenuContribution.js @@ -46,6 +46,11 @@ const styles = (theme) => ({ color: theme.palette.text.second, paddingTop: theme.menu.appBar.fontSize / 2, textTransform: "none", + transition: "all 0.3s ease", + "&:hover": { + backgroundColor: "rgba(255, 159, 28, 0.2)", + color: "#ff9f1c", + }, }, appBarMenuPaper: { borderTopLeftRadius: 0, @@ -79,9 +84,13 @@ const AccordionSummary = withStyles({ borderBottom: "1px solid rgba(0, 0, 0, .125)", marginBottom: -1, minHeight: 56, + transition: "background-color 0.3s ease", "&$expanded": { minHeight: 56, }, + "&:hover": { + backgroundColor: "rgba(255, 159, 28, 0.2)", + }, }, content: { "&$expanded": { @@ -301,15 +310,37 @@ const MenuItemsList = ({ entries, header, classes, redirect, isAppBar = false }) selected={isActive} style={{ backgroundColor: isActive ? "rgba(255, 159, 28, 0.1)" : "transparent", + transition: "background-color 0.3s ease", + }} + onMouseEnter={(e) => { + if (!isActive) { + e.currentTarget.style.backgroundColor = "rgba(255, 159, 28, 0.15)"; + const icon = e.currentTarget.querySelector(".MuiListItemIcon-root"); + const text = e.currentTarget.querySelector(".MuiListItemText-primary"); + if (icon) icon.style.color = "#ff9f1c"; + if (text) text.style.color = "#ff9f1c"; + } + }} + onMouseLeave={(e) => { + if (!isActive) { + e.currentTarget.style.backgroundColor = "transparent"; + const icon = e.currentTarget.querySelector(".MuiListItemIcon-root"); + const text = e.currentTarget.querySelector(".MuiListItemText-primary"); + if (icon) icon.style.color = "inherit"; + if (text) text.style.color = "inherit"; + } }} > - {entry.icon} + + {entry.icon} + @@ -331,15 +362,37 @@ const MenuItemsList = ({ entries, header, classes, redirect, isAppBar = false }) style={{ backgroundColor: isActive ? "rgba(255, 159, 28, 0.1)" : "transparent", borderLeft: isActive ? "3px solid #ff9f1c" : "3px solid transparent", + transition: "background-color 0.3s ease", + }} + onMouseEnter={(e) => { + if (!isActive) { + e.currentTarget.style.backgroundColor = "rgba(255, 159, 28, 0.15)"; + const icon = e.currentTarget.querySelector(".MuiListItemIcon-root"); + const text = e.currentTarget.querySelector(".MuiListItemText-primary"); + if (icon) icon.style.color = "#ff9f1c"; + if (text) text.style.color = "#ff9f1c"; + } + }} + onMouseLeave={(e) => { + if (!isActive) { + e.currentTarget.style.backgroundColor = "transparent"; + const icon = e.currentTarget.querySelector(".MuiListItemIcon-root"); + const text = e.currentTarget.querySelector(".MuiListItemText-primary"); + if (icon) icon.style.color = "inherit"; + if (text) text.style.color = "inherit"; + } }} > - {entry.icon} + + {entry.icon} + diff --git a/src/components/hooks/pageTitle.js b/src/components/hooks/pageTitle.js index 0e6e3df0..a9555301 100644 --- a/src/components/hooks/pageTitle.js +++ b/src/components/hooks/pageTitle.js @@ -1,6 +1,8 @@ import { Box, Grid, Typography } from "@material-ui/core"; import { makeStyles } from "@material-ui/styles"; import React from "react"; +import { useSelector } from "react-redux"; +import { useLocation } from "react-router-dom"; import UsePageTitle from "./usePageTitle"; const useStyles = makeStyles((theme) => ({ @@ -30,11 +32,21 @@ const useStyles = makeStyles((theme) => ({ function PageTitle() { const classes = useStyles(); const page = UsePageTitle(); + const location = useLocation(); + const user = useSelector((state) => state.core.user); if (!page.parent && !page.title) { return <>; } + const isHomePage = location.pathname === "/home" || location.pathname === "/front/home"; + const username = user?.i_user?.username || user?.username || ""; + + let displaySubtitle = page.subtitle; + if (isHomePage && username) { + displaySubtitle = `Bienvenue sur le compte ${username} !`; + } + return ( @@ -49,9 +61,9 @@ function PageTitle() { {page.title} )} - {page.subtitle && ( + {displaySubtitle && ( - {page.subtitle} + {displaySubtitle} )} diff --git a/src/translations/en.json b/src/translations/en.json index f9072ea5..25dca1f4 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -78,7 +78,7 @@ "core.emptyNotification": "No Notification", "core.routes.home.parent": "CAMU IMS", "core.routes.home.title": "Home", - "core.routes.home.subtitle": "Main dashboard", + "core.routes.home.subtitle": "", "core.routes.affiliation.families.subtitle": "Manage and view insured families", "core.routes.affiliation.insurees.subtitle": "Manage and view individual insureds", "core.routes.affiliation.policies.subtitle": "Manage insurance policies", diff --git a/src/translations/fr.json b/src/translations/fr.json index 9faf552e..b710767e 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -16,7 +16,7 @@ "core.ForgotPasswordPage.explanationMessage": "Saisissez votre nom d'utilisateur pour pouvoir récupérer votre compte. Un e-mail contenant les instructions sera envoyé à votre adresse e-mail.", "core.routes.home.parent": "CAMU IMS", "core.routes.home.title": "Accueil", - "core.routes.home.subtitle": "Tableau de bord principal", + "core.routes.home.subtitle": "", "core.routes.affiliation.families.subtitle": "Gérer et consulter les familles d'assurés", "core.routes.affiliation.insurees.subtitle": "Gérer et consulter les assurés individuels", "core.routes.affiliation.policies.subtitle": "Gérer les polices d'assurance", From 7d9af9edd156e9b32efab80ac95bea495a0645d0 Mon Sep 17 00:00:00 2001 From: tom hikari Date: Mon, 22 Dec 2025 14:41:36 +0100 Subject: [PATCH 111/111] refactor: remove unused GraphQL mutation for user verification and password update - Deleted the `verifyUserAndUpdatePassword` mutation as it is no longer needed in the application. --- const { mutate } = useGraphqlMutation( | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 const { mutate } = useGraphqlMutation( diff --git a/const { mutate } = useGraphqlMutation( b/const { mutate } = useGraphqlMutation( deleted file mode 100644 index a0ad3c30..00000000 --- a/const { mutate } = useGraphqlMutation( +++ /dev/null @@ -1,11 +0,0 @@ -const { mutate } = useGraphqlMutation( - ` - mutation verifyUserAndUpdatePassword($password: String!, $token: String!, $userId: String!) { - verifyUserAndUpdatePassword(password: $password, token: $token, userId: $userId) { - success - message - } - } - `, - { wait: false }, - ); \ No newline at end of file