diff --git a/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx b/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx index f922cb1ce2f99aed1e069ea04521dbcec4e033d6..577a4932ce4f5f05cf82611e0f7622d8e6992f49 100644 --- a/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx +++ b/src/components/Connection/ExpiredConsentModal/ExpiredConsentModal.tsx @@ -54,9 +54,13 @@ const ExpiredConsentModal = ({ }) ) dispatch(setShouldRefreshConsent(true)) + toggleModal() + navigate(`/consumption/${FluidType[fluidType].toLocaleLowerCase()}`) + } + if (fluidType === FluidType.GAS) { + toggleModal() + navigate(`/connect/${FluidType[fluidType].toLocaleLowerCase()}`) } - toggleModal() - navigate(`/consumption/${FluidType[fluidType].toLocaleLowerCase()}`) }, [dispatch, fluidStatus, fluidType, navigate, toggleModal]) return ( diff --git a/src/components/Connection/GRDFConnect/GrdfWaitConsent.tsx b/src/components/Connection/GRDFConnect/GrdfWaitConsent.tsx index 057aebf90c04486335ba1d20f38638240da26c77..2f829315f6d3ca9835fc606257dbe435f2275408 100644 --- a/src/components/Connection/GRDFConnect/GrdfWaitConsent.tsx +++ b/src/components/Connection/GRDFConnect/GrdfWaitConsent.tsx @@ -4,29 +4,23 @@ import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidType } from 'enums' import { AccountGRDFData, FluidConnection } from 'models' -import React, { useEffect, useState } from 'react' +import React from 'react' import { updateFluidConnection } from 'store/global/global.slice' import { useAppDispatch, useAppSelector } from 'store/hooks' import './GrdfWaitConsent.scss' -export const GrdfWaitConsent = ({ - showRelaunch, -}: { - showRelaunch: boolean -}) => { +export const GrdfWaitConsent = () => { const { t } = useI18n() const dispatch = useAppDispatch() const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const currentFluidStatus = fluidStatus[FluidType.GAS] - const account = currentFluidStatus.connection.account - const [consentEmail, setConsentEmail] = useState('') + const authData = currentFluidStatus.connection.account + ?.auth as AccountGRDFData const updateKonnector = async () => { const updatedConnection: FluidConnection = { ...currentFluidStatus.connection, - // TODO : investigate is this is duplicate ? shouldLaunchKonnector: true, - isUpdating: true, } dispatch( updateFluidConnection({ @@ -36,16 +30,6 @@ export const GrdfWaitConsent = ({ ) } - useEffect(() => { - if (account?.auth) { - const auth = account.auth - const authData = auth as AccountGRDFData - if (authData.email) { - setConsentEmail(authData.email) - } - } - }, [account]) - return ( <div className="grdfWait"> <div className="text-18-normal"> @@ -54,7 +38,7 @@ export const GrdfWaitConsent = ({ <div className="text-16-normal"> {t('auth.grdfgrandlyon.waiting.mailDelay')} </div> - <span className="emailContainer">{consentEmail}</span> + <span className="emailContainer">{authData.email || ''}</span> <StyledIcon size={80} icon={GRDFMail} /> <div className="text-18-normal"> <span className="text-18-bold green"> @@ -63,11 +47,9 @@ export const GrdfWaitConsent = ({ <br /> <span>{t('auth.grdfgrandlyon.waiting.comeback')}</span> </div> - {showRelaunch && ( - <Button className="btnPrimary" onClick={updateKonnector}> - {t('auth.grdfgrandlyon.waiting.button_done')} - </Button> - )} + <Button className="btnPrimary" onClick={updateKonnector}> + {t('auth.grdfgrandlyon.waiting.button_done')} + </Button> </div> ) } diff --git a/src/components/Consumption/ConsumptionView.tsx b/src/components/Consumption/ConsumptionView.tsx index 0510564bcbfedd6db98123654b1274e249bd651d..4e8f415f752f5f37835786b0e09f7444f9b2a697 100644 --- a/src/components/Consumption/ConsumptionView.tsx +++ b/src/components/Consumption/ConsumptionView.tsx @@ -1,5 +1,4 @@ import ExpiredConsentModal from 'components/Connection/ExpiredConsentModal/ExpiredConsentModal' -import { GrdfWaitConsent } from 'components/Connection/GRDFConnect/GrdfWaitConsent' import Content from 'components/Content/Content' import CustomPopupModal from 'components/CustomPopup/CustomPopupModal' import DateNavigator from 'components/DateNavigator/DateNavigator' @@ -225,16 +224,10 @@ const ConsumptionView = ({ fluidType }: { fluidType: FluidType }) => { <Content> <FluidButtons activeFluid={fluidType} key={updateKey} /> - {isWaitingForConsent ? ( - <GrdfWaitConsent showRelaunch={true} /> - ) : ( + {showOfflineData && !isWaitingForConsent && ( <> - {showOfflineData && ( - <> - <FluidChart fluidType={fluidType} key={lastDataDateKey} /> - <ConsumptionDetails fluidType={fluidType} /> - </> - )} + <FluidChart fluidType={fluidType} key={lastDataDateKey} /> + <ConsumptionDetails fluidType={fluidType} /> </> )} {!isMulti && <KonnectorViewerCard fluidType={fluidType} />} diff --git a/src/components/Konnector/ConnectionResult/ConnectionResult.tsx b/src/components/Konnector/ConnectionResult/ConnectionResult.tsx index 6907cc99ff3dbfad069752f1dcf94c6ed76a43d3..232a418355a9ac57925d69043d25d7e8d4358818 100644 --- a/src/components/Konnector/ConnectionResult/ConnectionResult.tsx +++ b/src/components/Konnector/ConnectionResult/ConnectionResult.tsx @@ -6,7 +6,7 @@ import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidType, KonnectorUpdate } from 'enums' import { DateTime } from 'luxon' -import { Account, AccountSgeData, FluidConnection, FluidStatus } from 'models' +import { AccountSgeData, FluidConnection, FluidStatus } from 'models' import React, { useCallback, useEffect, useState } from 'react' import AccountService from 'services/account.service' import DateChartService from 'services/dateChart.service' @@ -34,7 +34,7 @@ const ConnectionResult = ({ const dispatch = useAppDispatch() const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const currentFluidStatus = fluidStatus[fluidType] - const account: Account | null = currentFluidStatus.connection.account + const account = currentFluidStatus.connection.account const [deleting, setDeleting] = useState<boolean>(false) const [lastExecutionDate, setLastExecutionDate] = useState<string | DateTime>( diff --git a/src/components/Konnector/KonnectorModal.spec.tsx b/src/components/Konnector/KonnectorModal.spec.tsx index d3f7fbe830276eb3a1094476d6b55d6ce5d6a24e..bd2f5cacac53519318ffdbdbc6cc4952b35729b3 100644 --- a/src/components/Konnector/KonnectorModal.spec.tsx +++ b/src/components/Konnector/KonnectorModal.spec.tsx @@ -18,7 +18,6 @@ describe('KonnectorModal component', () => { <Provider store={store}> <KonnectorModal open={true} - isUpdating={false} state={null} error={null} fluidType={FluidType.ELECTRICITY} @@ -36,7 +35,6 @@ describe('KonnectorModal component', () => { <Provider store={store}> <KonnectorModal open={true} - isUpdating={true} state={null} error={null} fluidType={FluidType.ELECTRICITY} @@ -56,7 +54,6 @@ describe('KonnectorModal component', () => { <Provider store={store}> <KonnectorModal open={true} - isUpdating={false} state="errored" error={null} fluidType={FluidType.ELECTRICITY} @@ -77,7 +74,6 @@ describe('KonnectorModal component', () => { <Provider store={store}> <KonnectorModal open={true} - isUpdating={false} state="error" error={KonnectorError.LOGIN_FAILED} fluidType={FluidType.ELECTRICITY} @@ -97,7 +93,6 @@ describe('KonnectorModal component', () => { <Provider store={store}> <KonnectorModal open={true} - isUpdating={false} state="error" error={null} fluidType={FluidType.ELECTRICITY} @@ -115,7 +110,6 @@ describe('KonnectorModal component', () => { <Provider store={store}> <KonnectorModal open={true} - isUpdating={true} state={null} error={null} fluidType={FluidType.WATER} @@ -130,4 +124,22 @@ describe('KonnectorModal component', () => { baseElement.getElementsByClassName('waiting-text')[0] ).toBeInTheDocument() }) + + it('should render nothing if error is CHALLENGE_ASKED on Gas', () => { + render( + <Provider store={store}> + <KonnectorModal + open={true} + state={null} + error={KonnectorError.CHALLENGE_ASKED} + fluidType={FluidType.GAS} + handleCloseClick={mockHandleCloseClick} + isVerifyingIdentity={false} + account={null} + handleAccountDeletion={jest.fn()} + /> + </Provider> + ) + expect(screen.queryByRole('dialog')).toBeNull() + }) }) diff --git a/src/components/Konnector/KonnectorModal.tsx b/src/components/Konnector/KonnectorModal.tsx index 2cf2ede9993268e238fb3f6e47cc010694af9fbf..df53e6c64396724c7d187e5ee6500f9280165246 100644 --- a/src/components/Konnector/KonnectorModal.tsx +++ b/src/components/Konnector/KonnectorModal.tsx @@ -17,13 +17,13 @@ import { FluidType, KonnectorError } from 'enums' import { shuffle } from 'lodash' import { Account } from 'models' import React, { useCallback, useEffect, useMemo, useState } from 'react' +import { useAppSelector } from 'store/hooks' import { getFluidName } from 'utils/utils' import KonnectorModalFooter from './KonnectorModalFooter' import './konnectorModal.scss' interface KonnectorModalProps { open: boolean - isUpdating: boolean /** Only used for SGE when searching for user identity */ isVerifyingIdentity: boolean state: string | null @@ -36,7 +36,6 @@ interface KonnectorModalProps { const KonnectorModal = ({ open, - isUpdating, isVerifyingIdentity, state, error, @@ -47,6 +46,8 @@ const KonnectorModal = ({ }: KonnectorModalProps) => { const { t } = useI18n() const fluidName = getFluidName(fluidType) + const { fluidStatus } = useAppSelector(state => state.ecolyo.global) + const isUpdating = fluidStatus[fluidType].connection.isUpdating const [index, setIndex] = useState<number>(0) /** Only used for enedis to see common errors */ const [showCommonErrors, setShowCommonErrors] = useState(false) @@ -140,6 +141,10 @@ const KonnectorModal = ({ } }, [open, state]) + if (fluidType === FluidType.GAS && error === KonnectorError.CHALLENGE_ASKED) { + return null + } + return ( <Dialog open={open} @@ -165,8 +170,7 @@ const KonnectorModal = ({ <Loader fluidType={fluidType} /> {!isVerifyingIdentity && ( <div className="kmodal-content-text text-16-normal"> - {/* TODO remove kc-wait */} - <div className="kc-wait text-16-bold"> + <div className="text-16-bold"> {t( `konnector_modal.loading_data${isUpdating ? '_update' : ''}` )} diff --git a/src/components/Konnector/KonnectorViewerCard.tsx b/src/components/Konnector/KonnectorViewerCard.tsx index e598bbdbf8442ba8067e40539290920655d4ded5..3e5a4bff1729b430aec22a3b8d07e473818e7eba 100644 --- a/src/components/Konnector/KonnectorViewerCard.tsx +++ b/src/components/Konnector/KonnectorViewerCard.tsx @@ -12,6 +12,7 @@ import OfflinePicto from 'assets/icons/visu/offline-param.svg' import classNames from 'classnames' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import Connection from 'components/Connection/Connection' +import { GrdfWaitConsent } from 'components/Connection/GRDFConnect/GrdfWaitConsent' import KonnectorModal from 'components/Konnector/KonnectorModal' import { useClient } from 'cozy-client' import { isKonnectorRunning } from 'cozy-harvest-lib/dist/helpers/triggers' @@ -81,7 +82,6 @@ const KonnectorViewerCard = ({ const currentFluidName = FluidType[currentFluidStatus.fluidType].toLowerCase() const [openModal, setOpenModal] = useState(false) - const [isUpdating, setIsUpdating] = useState(false) const [isVerifyingIdentity, setIsVerifyingIdentity] = useState( fluidType === FluidType.ELECTRICITY ) @@ -164,8 +164,11 @@ const KonnectorViewerCard = ({ dispatch, ]) + /** Close modal, update fluid status and reset error state */ const handleConnectionEnd = useCallback( async (isSuccess?: boolean) => { + const { account, isUpdating } = currentFluidStatus.connection + // CASE FOR GLOBAL LOGIN FAILED const isGlobalLoginFailed = konnectorErrorDescription === KonnectorError.LOGIN_FAILED || @@ -182,19 +185,14 @@ const KonnectorViewerCard = ({ const shouldDeleteAccount = account && !isSuccess && - currentFluidStatus && - currentFluidStatus.connection.account && + account && (isGlobalLoginFailed || isEnedisCodeInseeError) if (shouldDeleteAccount) { logApp('info', `shouldDeleteAccount`) // KEEP LAST LOGIN FOR EPGL - if ( - fluidSlug === FluidSlugType.WATER && - currentFluidStatus.connection.account?.auth - ) { - const auth = currentFluidStatus.connection.account - .auth as AccountEGLData + if (fluidSlug === FluidSlugType.WATER && account?.auth) { + const auth = account.auth as AccountEGLData const lastEpglLogin = auth.login dispatch(setLastEpglLogin(lastEpglLogin)) } @@ -213,10 +211,8 @@ const KonnectorViewerCard = ({ setKonnectorErrorDescription(null) }, [ - account, konnectorErrorDescription, currentFluidStatus, - isUpdating, fluidType, fluidSlug, client, @@ -250,7 +246,10 @@ const KonnectorViewerCard = ({ ) } - if (fluidState === FluidState.KONNECTOR_NOT_FOUND && !isUpdating) { + if ( + fluidState === FluidState.KONNECTOR_NOT_FOUND && + !currentFluidStatus.connection.isUpdating + ) { return <ConnectionNotFound konnectorSlug={fluidSlug} /> } @@ -269,12 +268,12 @@ const KonnectorViewerCard = ({ } }, [ account, + currentFluidStatus.connection.isUpdating, currentFluidStatus.status, fluidSlug, fluidState, fluidType, handleAccountDeletion, - isUpdating, showOfflineData, t, toggleModalConnection, @@ -298,14 +297,19 @@ const KonnectorViewerCard = ({ await updateGlobalFluidStatus(), ]) - setKonnectorState(_state) - /** If waiting for consent, close Konnector modal first and handle connection closed */ + /** + * If waiting for consent, close Konnector modal first and handle connection closed + * Calling handleConnectionEnd here because it won't be called in the KonnectorModal since we don't show it + * + * Else set error for KonnectorModal + */ if ( - updatedFluidStatus[2].connection.triggerState?.last_error === - KonnectorError.CHALLENGE_ASKED + fluidType === FluidType.GAS && + updatedFluidStatus[2].status == FluidState.CHALLENGE_ASKED ) { - setOpenModal(false) - handleConnectionEnd(false) + await handleConnectionEnd(false) + } else { + setKonnectorState(_state) } } }, @@ -313,6 +317,7 @@ const KonnectorViewerCard = ({ currentFluidStatus.connection, currentFluidStatus.fluidType, dispatch, + fluidType, handleConnectionEnd, refreshChallengeState, updateGlobalFluidStatus, @@ -400,8 +405,9 @@ const KonnectorViewerCard = ({ !isKonnectorRunning(trigger) ) { if (subscribed) { - if (currentFluidStatus.connection.isUpdating) setIsUpdating(true) setOpenModal(true) + // Reset any error that might have been set after handleConnectionEnd + setKonnectorErrorDescription(null) const updatedConnection: FluidConnection = { ...currentFluidStatus.connection, shouldLaunchKonnector: false, @@ -415,10 +421,9 @@ const KonnectorViewerCard = ({ } const connectionFlow = new ConnectionFlow(client, trigger, konnector) await connectionFlow.launch() - console.log('connectionFlow', connectionFlow.jobWatcher) - connectionFlow.jobWatcher.on(ERROR_EVENT, () => { + connectionFlow.jobWatcher.on(ERROR_EVENT, async () => { + await callbackResponse(ERROR_EVENT) setKonnectorErrorDescription(connectionFlow.jobWatcher.on()._error) - callbackResponse(ERROR_EVENT) }) connectionFlow.jobWatcher.on(LOGIN_SUCCESS_EVENT, () => { setIsVerifyingIdentity(false) @@ -455,8 +460,11 @@ const KonnectorViewerCard = ({ return ( <div className="konnector-section-root"> - {!showOfflineData && <Connection fluidType={fluidType} />} - {showOfflineData && !isWaitingForConsent && ( + {isWaitingForConsent && <GrdfWaitConsent />} + {!isWaitingForConsent && !showOfflineData && ( + <Connection fluidType={fluidType} /> + )} + {!isWaitingForConsent && showOfflineData && ( <Accordion expanded={showConnectionDetails} onChange={toggleAccordion} @@ -503,7 +511,6 @@ const KonnectorViewerCard = ({ )} <KonnectorModal open={openModal} - isUpdating={isUpdating} isVerifyingIdentity={isVerifyingIdentity} state={konnectorState} error={konnectorErrorDescription} diff --git a/src/components/Konnector/__snapshots__/KonnectorModal.spec.tsx.snap b/src/components/Konnector/__snapshots__/KonnectorModal.spec.tsx.snap index 26f5020cdb92ac0164ac456a16d31a10b1bb99d1..0afd9d36255efb8a46293bc32d038cedd180b19a 100644 --- a/src/components/Konnector/__snapshots__/KonnectorModal.spec.tsx.snap +++ b/src/components/Konnector/__snapshots__/KonnectorModal.spec.tsx.snap @@ -65,7 +65,7 @@ exports[`KonnectorModal component should be rendered correctly 1`] = ` class="kmodal-content-text text-16-normal" > <div - class="kc-wait text-16-bold" + class="text-16-bold" > konnector_modal.loading_data </div> diff --git a/src/components/Konnector/konnectorModal.scss b/src/components/Konnector/konnectorModal.scss index fdbaab03c5e96cd3b82721b07bfaa0d7b6bad8db..832aa7c48d32f01259eff7d255a2c4aadb34640c 100644 --- a/src/components/Konnector/konnectorModal.scss +++ b/src/components/Konnector/konnectorModal.scss @@ -22,10 +22,6 @@ min-height: 11.25rem; text-align: center; - .kc-wait { - margin-bottom: 2rem; - } - .waiting-text { display: none; diff --git a/src/components/Quiz/QuizFinish/QuizFinish.tsx b/src/components/Quiz/QuizFinish/QuizFinish.tsx index 3603c0710a1201c2f4fc0c160a384f8a74833198..c2c1d8ebec6a7fa203fd2208fc38db4e75a389fa 100644 --- a/src/components/Quiz/QuizFinish/QuizFinish.tsx +++ b/src/components/Quiz/QuizFinish/QuizFinish.tsx @@ -17,10 +17,7 @@ const QuizFinish = ({ userChallenge }: { userChallenge: UserChallenge }) => { const client = useClient() const navigate = useNavigate() const dispatch = useAppDispatch() - const challengeService: ChallengeService = useMemo( - () => new ChallengeService(client), - [client] - ) + const challengeService = useMemo(() => new ChallengeService(client), [client]) const retryQuiz = useCallback(async () => { const userChallengeUpdated = await challengeService.updateUserChallenge( diff --git a/src/models/fluid.model.ts b/src/models/fluid.model.ts index a99af34eb156a60a32ba5ba763421c78c326b0c9..d8ba653c6723780a77904288d76998a1705b2c00 100644 --- a/src/models/fluid.model.ts +++ b/src/models/fluid.model.ts @@ -3,8 +3,19 @@ import { DateTime } from 'luxon' import { Account, Konnector, KonnectorConfig, Trigger } from 'models' import { TriggerState } from './trigger.model' +export interface FluidStatus { + fluidType: FluidType + status: FluidState + maintenance: boolean + firstDataDate: DateTime | null + lastDataDate: DateTime | null + connection: FluidConnection +} + export interface FluidConnection { + /** This toggles the launch of the konnector when set to true */ shouldLaunchKonnector: boolean + /** When enabled, alters the texts of Konnector Modal */ isUpdating: boolean konnector: Konnector | null account: Account | null @@ -12,11 +23,3 @@ export interface FluidConnection { triggerState: TriggerState | null konnectorConfig: KonnectorConfig } -export interface FluidStatus { - fluidType: FluidType - status: FluidState - maintenance: boolean - firstDataDate: DateTime | null - lastDataDate: DateTime | null - connection: FluidConnection -} diff --git a/src/services/fluid.service.ts b/src/services/fluid.service.ts index 25a5b9ad0e15935e4bf4cfe938daa8ace3f19d1b..f22c17dc550c959396a9838018e09139865a5837 100644 --- a/src/services/fluid.service.ts +++ b/src/services/fluid.service.ts @@ -97,7 +97,6 @@ export default class FluidService { waterTrigger ? triggerService.fetchTriggerState(waterTrigger) : null, gasTrigger ? triggerService.fetchTriggerState(gasTrigger) : null, ]) - console.log('🚀 ~ FluidService ~ gasStatus:', gasStatus) const firstDataDates = await consumptionService.fetchAllFirstDateData(allFluids) const lastDataDates =