diff --git a/src/components/Action/ActionBegin.tsx b/src/components/Action/ActionBegin.tsx index f039432d32f51e9730e63b429b794135cfd00e86..52b1c8a3f7d5733d24ea840c4fede9e526357f86 100644 --- a/src/components/Action/ActionBegin.tsx +++ b/src/components/Action/ActionBegin.tsx @@ -7,9 +7,8 @@ import { Client, useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { Ecogesture, UserChallenge } from 'models' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import ActionService from 'services/action.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { importIconById } from 'utils/utils' import './actionBegin.scss' @@ -29,7 +28,7 @@ const ActionBegin = ({ const { global: { fluidTypes }, profile: { isProfileTypeCompleted }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const [currentAction, setCurrentAction] = useState<Ecogesture>() const [actionIcon, setActionIcon] = useState<string>('') const [openLaunchModal, setOpenLaunchModal] = useState<boolean>(false) diff --git a/src/components/Action/ActionCard.tsx b/src/components/Action/ActionCard.tsx index 9b491e035b0c55d4bd4a7484e9bf5fd38e5970ad..18da28fd620b1fe2ab5dcc762726931815cb793d 100644 --- a/src/components/Action/ActionCard.tsx +++ b/src/components/Action/ActionCard.tsx @@ -6,9 +6,8 @@ import { useClient } from 'cozy-client' import { UsageEventType } from 'enum/usageEvent.enum' import { Ecogesture } from 'models' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { importIconById } from 'utils/utils' import './actionList.scss' @@ -26,9 +25,7 @@ const ActionCard = ({ const [actionIcon, setActionIcon] = useState<string>('') const [openEcogestureModal, setOpenEcogestureModal] = useState<boolean>(false) const client = useClient() - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) + const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const toggleModal = useCallback(() => { setOpenEcogestureModal(prev => !prev) }, []) diff --git a/src/components/Action/ActionDone.spec.tsx b/src/components/Action/ActionDone.spec.tsx index 8cd504e7c9d89458e16bd10ad3fcf3885f36435d..49823ad467041e17bf9e1b452e90f667a555c345 100644 --- a/src/components/Action/ActionDone.spec.tsx +++ b/src/components/Action/ActionDone.spec.tsx @@ -2,7 +2,6 @@ import { Button } from '@material-ui/core' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import UsageEventService from 'services/usageEvent.service' import * as challengeActions from 'store/challenge/challenge.slice' @@ -46,13 +45,11 @@ describe('ActionDone component', () => { expect(toJson(wrapper)).toMatchSnapshot() }) it('should click on button and update action to done', async () => { - const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') const updateChallengeSpy = jest.spyOn( challengeActions, 'updateUserChallengeList' ) mockupdateUserChallenge.mockResolvedValueOnce(userChallengeData[1]) - useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> <ActionDone currentChallenge={userChallengeData[1]} /> diff --git a/src/components/Action/ActionDone.tsx b/src/components/Action/ActionDone.tsx index b1ee82f5b446e46c0a157b5908804c326163ed20..450868a8efe6117160dd6ccfb597a3a95df0eb9d 100644 --- a/src/components/Action/ActionDone.tsx +++ b/src/components/Action/ActionDone.tsx @@ -6,14 +6,13 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { toggleChallengeActionNotification } from 'store/global/global.slice' +import { useAppDispatch } from 'store/hooks' import './actionDone.scss' const ActionDone = ({ @@ -23,7 +22,7 @@ const ActionDone = ({ }) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const navigate = useNavigate() const handleEndAction = useCallback(async () => { const challengeService = new ChallengeService(client) diff --git a/src/components/Action/ActionList.tsx b/src/components/Action/ActionList.tsx index b218dd7b11acd4343b427657b4f45b6673c2f996..a5cb263d1d6781a37abeb7df1371af425425d130 100644 --- a/src/components/Action/ActionList.tsx +++ b/src/components/Action/ActionList.tsx @@ -2,9 +2,8 @@ import ActionCard from 'components/Action/ActionCard' import { Client, useClient } from 'cozy-client' import { Ecogesture } from 'models' import React, { useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import ActionService from 'services/action.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import './actionBegin.scss' interface ActionListProps { @@ -17,7 +16,7 @@ const ActionList = ({ setSelectedAction, setShowList }: ActionListProps) => { const { global: { fluidTypes }, profile: { isProfileTypeCompleted }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const [actions, setActions] = useState<Ecogesture[]>() useEffect(() => { diff --git a/src/components/Action/ActionModal.spec.tsx b/src/components/Action/ActionModal.spec.tsx index 153acd6faacf0805e9c0edf874fa3a1f60d4b3e5..f0159a064f6aab649ee6a01dcdbf1ad3ae4b63ae 100644 --- a/src/components/Action/ActionModal.spec.tsx +++ b/src/components/Action/ActionModal.spec.tsx @@ -2,7 +2,6 @@ import { Button } from '@material-ui/core' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import UsageEventService from 'services/usageEvent.service' import * as challengeActions from 'store/challenge/challenge.slice' @@ -46,14 +45,11 @@ describe('ActionModal component', () => { expect(toJson(wrapper)).toMatchSnapshot() }) it('should click on button and update action to ongoing', async () => { - const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') const updateChallengeSpy = jest.spyOn( challengeActions, 'updateUserChallengeList' ) - mockupdateUserChallenge.mockResolvedValueOnce(userChallengeData[1]) - useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> diff --git a/src/components/Action/ActionModal.tsx b/src/components/Action/ActionModal.tsx index b58e54f40a0fe4dee367da8ab58d2bc9c89c38e2..01aa9f3ec10ac2cbd39e060b8a675c481ba153f0 100644 --- a/src/components/Action/ActionModal.tsx +++ b/src/components/Action/ActionModal.tsx @@ -6,11 +6,10 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { Ecogesture, UserChallenge } from 'models' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback } from 'react' import ChallengeService from 'services/challenge.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch } from 'store/hooks' import './actionModal.scss' interface ActionModalProps { @@ -26,9 +25,9 @@ const ActionModal = ({ handleCloseClick, userChallenge, }: ActionModalProps) => { - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const client = useClient() const { t } = useI18n() + const dispatch = useAppDispatch() const launchAction = useCallback(async () => { const challengeService = new ChallengeService(client) const updatedChallenge: UserChallenge = diff --git a/src/components/Action/ActionView.tsx b/src/components/Action/ActionView.tsx index 03ecb1cb19bb7539d422dcb87bc06a55015e0884..ba49a638363016e9d2efe67c77781bb41b593ed5 100644 --- a/src/components/Action/ActionView.tsx +++ b/src/components/Action/ActionView.tsx @@ -7,14 +7,11 @@ import Header from 'components/Header/Header' import { UserActionState } from 'enum/userAction.enum' import { UserChallenge } from 'models' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' const ActionView = () => { + const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const [headerHeight, setHeaderHeight] = useState<number>(0) - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) const defineHeaderHeight = useCallback((height: number) => { setHeaderHeight(height) }, []) diff --git a/src/components/Analysis/AnalysisView.spec.tsx b/src/components/Analysis/AnalysisView.spec.tsx index 9e8e469ea309c49fca1c0afedbfc6ec49c6395e7..e112899bb8a35eef9b99eeb9f941b0689c3b602f 100644 --- a/src/components/Analysis/AnalysisView.spec.tsx +++ b/src/components/Analysis/AnalysisView.spec.tsx @@ -1,9 +1,9 @@ import AnalysisView from 'components/Analysis/AnalysisView' import { mount } from 'enzyme' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import * as globalActions from 'store/global/global.slice' +import * as storeHooks from 'store/hooks' import * as profileActions from 'store/profile/profile.actions' import { createMockEcolyoStore, @@ -30,8 +30,7 @@ jest.mock('react-router-dom', () => ({ }), })) -const useSelectorSpy = jest.spyOn(reactRedux, 'useSelector') -const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') +const mockAppDispatch = jest.spyOn(storeHooks, 'useAppDispatch') const toggleAnalysisNotificationSpy = jest.spyOn( globalActions, 'toggleAnalysisNotification' @@ -42,14 +41,12 @@ describe('AnalysisView component', () => { const store = createMockEcolyoStore() beforeEach(() => { store.clearActions() - useSelectorSpy.mockClear() - useDispatchSpy.mockClear() + mockAppDispatch.mockClear() toggleAnalysisNotificationSpy.mockClear() updateProfileSpy.mockClear() }) it('should be rendered correctly', () => { - useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> <AnalysisView /> @@ -68,7 +65,7 @@ describe('AnalysisView component', () => { global: { analysisNotification: true }, profile: { ...mockProfileState, haveSeenLastAnalysis: true }, }) - useDispatchSpy.mockReturnValue(jest.fn()) + mockAppDispatch.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> <AnalysisView /> diff --git a/src/components/Analysis/AnalysisView.tsx b/src/components/Analysis/AnalysisView.tsx index 58ef3f06c7fe886c55457ab32356216fd2dc6dc0..dea8806b2a678843e5cf493f6c984f6d83c84f5f 100644 --- a/src/components/Analysis/AnalysisView.tsx +++ b/src/components/Analysis/AnalysisView.tsx @@ -7,28 +7,27 @@ import { useClient } from 'cozy-client' import { TimeStep } from 'enum/timeStep.enum' import { UsageEventType } from 'enum/usageEvent.enum' import { DateTime } from 'luxon' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import { useLocation } from 'react-router-dom' import DateChartService from 'services/dateChart.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { setAnalysisMonth } from 'store/analysis/analysis.slice' import { toggleAnalysisNotification } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { updateProfile } from 'store/profile/profile.actions' import { isLastDateReached } from 'utils/date' import './analysisView.scss' const AnalysisView = () => { const client = useClient() - const [headerHeight, setHeaderHeight] = useState<number>(0) const { analysis: { analysisMonth }, chart: { selectedDate }, global: { analysisNotification }, profile: { monthlyAnalysisDate, mailToken }, - } = useSelector((state: AppStore) => state.ecolyo) - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + } = useAppSelector(state => state.ecolyo) + const dispatch = useAppDispatch() + const [headerHeight, setHeaderHeight] = useState<number>(0) const defineHeaderHeight = useCallback((height: number) => { setHeaderHeight(height) }, []) diff --git a/src/components/Analysis/Comparison/Comparison.tsx b/src/components/Analysis/Comparison/Comparison.tsx index 1a200e9d84710b0397e7cf037929f21a47d165a0..b9bad0ee5613f6e877b8d391b3a7425d2df00e29 100644 --- a/src/components/Analysis/Comparison/Comparison.tsx +++ b/src/components/Analysis/Comparison/Comparison.tsx @@ -5,11 +5,10 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { PerformanceIndicator } from 'models' -import React, { Dispatch, useEffect, useMemo, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useEffect, useMemo, useState } from 'react' import ConsumptionService from 'services/consumption.service' -import { AppActionsTypes, AppStore } from 'store' import { setPeriod } from 'store/analysis/analysis.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import FluidPerformanceIndicator from './FluidPerformanceIndicator' import './comparison.scss' @@ -25,8 +24,8 @@ const Comparison = ({ const { global: { fluidTypes }, analysis: { period, analysisMonth }, - } = useSelector((state: AppStore) => state.ecolyo) - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + } = useAppSelector(state => state.ecolyo) + const dispatch = useAppDispatch() const [yearPerformanceIndicators, setYearPerformanceIndicators] = useState< PerformanceIndicator[] >([]) diff --git a/src/components/Analysis/ElecHalfHourMonthlyAnalysis/ElecHalfHourMonthlyAnalysis.tsx b/src/components/Analysis/ElecHalfHourMonthlyAnalysis/ElecHalfHourMonthlyAnalysis.tsx index 2c3fb28c24d8eaf71d0396e994c4b9b173f04119..a62f302fa0383a4b45ab3c69693ab79c9609ab77 100644 --- a/src/components/Analysis/ElecHalfHourMonthlyAnalysis/ElecHalfHourMonthlyAnalysis.tsx +++ b/src/components/Analysis/ElecHalfHourMonthlyAnalysis/ElecHalfHourMonthlyAnalysis.tsx @@ -15,11 +15,10 @@ import { EnedisMonthlyAnalysisData, } from 'models/enedisMonthlyAnalysis' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import ConsumptionService from 'services/consumption.service' import EnedisMonthlyAnalysisDataService from 'services/enedisMonthlyAnalysisData.service' import FluidPricesService from 'services/fluidsPrices.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { getNavPicto } from 'utils/picto' import ElecHalfHourChart from './ElecHalfHourChart' import ElecInfoModal from './ElecInfoModal' @@ -32,9 +31,7 @@ const ElecHalfHourMonthlyAnalysis = ({ }) => { const { t } = useI18n() const client = useClient() - const { analysisMonth } = useSelector( - (state: AppStore) => state.ecolyo.analysis - ) + const { analysisMonth } = useAppSelector(state => state.ecolyo.analysis) const [isWeekend, setIsWeekend] = useState<boolean>(true) const [isHalfHourActivated, setIsHalfHourActivated] = useState<boolean>(true) const [isLoading, setIsLoading] = useState<boolean>(true) diff --git a/src/components/Analysis/MaxConsumptionCard/MaxConsumptionCard.tsx b/src/components/Analysis/MaxConsumptionCard/MaxConsumptionCard.tsx index f64e1c96d92ab8d43d71adf25cc1541a760da3b7..6f4999904aa63d587f394ef9492e80e4ee3f3498 100644 --- a/src/components/Analysis/MaxConsumptionCard/MaxConsumptionCard.tsx +++ b/src/components/Analysis/MaxConsumptionCard/MaxConsumptionCard.tsx @@ -14,11 +14,10 @@ import { DataloadSectionType } from 'enum/dataload.enum' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { Datachart, Dataload, TimePeriod } from 'models' -import React, { Dispatch, useEffect, useRef, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useEffect, useRef, useState } from 'react' import ConsumptionDataManager from 'services/consumption.service' -import { AppActionsTypes, AppStore } from 'store' import { setSelectedDate } from 'store/chart/chart.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import './maxConsumptionCard.scss' const MaxConsumptionCard = ({ @@ -28,10 +27,8 @@ const MaxConsumptionCard = ({ }) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { analysisMonth } = useSelector( - (state: AppStore) => state.ecolyo.analysis - ) + const dispatch = useAppDispatch() + const { analysisMonth } = useAppSelector(state => state.ecolyo.analysis) const [isLoading, setIsLoading] = useState<boolean>(false) const [maxDayData, setMaxDayData] = useState<Dataload | null>(null) const [chartData, setChartData] = useState<Datachart>({ diff --git a/src/components/Analysis/MonthlyAnalysis.tsx b/src/components/Analysis/MonthlyAnalysis.tsx index 7a0cb57b78fc41347d1c26fc8d3d8a150220da01..d61f48fde12b559d998343da38477cc2a5e7d588 100644 --- a/src/components/Analysis/MonthlyAnalysis.tsx +++ b/src/components/Analysis/MonthlyAnalysis.tsx @@ -4,10 +4,9 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { PerformanceIndicator, TimePeriod } from 'models' import React, { useEffect, useMemo, useState } from 'react' -import { useSelector } from 'react-redux' import ConsumptionService from 'services/consumption.service' import PerformanceIndicatorService from 'services/performanceIndicator.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import Comparison from './Comparison/Comparison' import ElecHalfHourMonthlyAnalysis from './ElecHalfHourMonthlyAnalysis/ElecHalfHourMonthlyAnalysis' import MaxConsumptionCard from './MaxConsumptionCard/MaxConsumptionCard' @@ -25,9 +24,7 @@ const MonthlyAnalysis = ({ scrollPosition, }: MonthlyAnalysisProps) => { const client = useClient() - const { analysisMonth } = useSelector( - (state: AppStore) => state.ecolyo.analysis - ) + const { analysisMonth } = useAppSelector(state => state.ecolyo.analysis) const consumptionService = useMemo( () => new ConsumptionService(client), diff --git a/src/components/Analysis/ProfileComparator/ProfileComparator.tsx b/src/components/Analysis/ProfileComparator/ProfileComparator.tsx index 88249ad39e662f99030710aaf0cc07831a6cd289..081ec1053b62ff87ef3db02b708d4b2c698d09e5 100644 --- a/src/components/Analysis/ProfileComparator/ProfileComparator.tsx +++ b/src/components/Analysis/ProfileComparator/ProfileComparator.tsx @@ -17,11 +17,10 @@ import { FluidType } from 'enum/fluid.enum' import { PerformanceIndicator } from 'models' import { MonthlyForecast, ProfileType } from 'models/profileType.model' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import ProfileTypeService from 'services/profileType.service' import ProfileTypeEntityService from 'services/profileTypeEntity.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import ProfileComparatorRow from './ProfileComparatorRow' import './profileComparator.scss' @@ -43,7 +42,7 @@ const ProfileComparator = ({ const { analysis: { analysisMonth }, profile, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const [homePriceConsumption, setHomePriceConsumption] = useState<number>(0) const [forecast, setForecast] = useState<MonthlyForecast | null>(null) const [isLoading, setIsLoading] = useState<boolean>(true) diff --git a/src/components/Analysis/TotalAnalysisChart/TotalAnalysisChart.tsx b/src/components/Analysis/TotalAnalysisChart/TotalAnalysisChart.tsx index 1f0e646ee821fdbc5a0f0beaa2c289e7e7f38e0e..f25be50174073041626d02f60b0dbe6acafffb7e 100644 --- a/src/components/Analysis/TotalAnalysisChart/TotalAnalysisChart.tsx +++ b/src/components/Analysis/TotalAnalysisChart/TotalAnalysisChart.tsx @@ -6,9 +6,8 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DataloadValueDetail, TimePeriod } from 'models' import React, { useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import ConsumptionDataManager from 'services/consumption.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { getNavPicto } from 'utils/picto' import { formatNumberValues, getMonthNameWithPrep } from 'utils/utils' import PieChart from './PieChart' @@ -19,15 +18,13 @@ const TotalAnalysisChart = ({ }: { fluidsWithData: FluidType[] }) => { - const { analysisMonth } = useSelector( - (state: AppStore) => state.ecolyo.analysis - ) + const { t } = useI18n() + const client = useClient() + const { analysisMonth } = useAppSelector(state => state.ecolyo.analysis) const [dataLoadValueDetailArray, setDataLoadValueDetailArray] = useState< DataloadValueDetail[] | null >(null) const [totalLoadValue, setTotalLoadValue] = useState<number>(0) - const client = useClient() - const { t } = useI18n() const [openEstimationModal, setOpenEstimationModal] = useState<boolean>(false) const arcWidth = 30 const radius = Math.min(375, innerWidth - 100) diff --git a/src/components/App.tsx b/src/components/App.tsx index e3ffd41d0636c51f923d58942248df61f0862159..5cfeb0f21cd9c288dd8b4c81fadedac567abdc3d 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -5,9 +5,8 @@ import WelcomeModal from 'components/WelcomeModal/WelcomeModal' import { useWebviewIntent } from 'cozy-intent' import { Layout } from 'cozy-ui/transpiled/react/Layout' import React, { useEffect } from 'react' -import { useSelector } from 'react-redux' import { useLocation } from 'react-router-dom' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import MatomoTracker from 'utils/matomoTracker' interface AppProps { @@ -19,7 +18,7 @@ export const App = ({ tracker }: AppProps) => { const { global: { termsStatus }, profile: { onboarding }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const webviewIntent = useWebviewIntent() useEffect(() => { diff --git a/src/components/Challenge/ChallengeCardOnGoing.tsx b/src/components/Challenge/ChallengeCardOnGoing.tsx index 54eeab6a7d2bceb6d7d9874a3d591ad045c40ba4..4157be83ea7ad8987725f0302133d840e56cc801 100644 --- a/src/components/Challenge/ChallengeCardOnGoing.tsx +++ b/src/components/Challenge/ChallengeCardOnGoing.tsx @@ -16,12 +16,11 @@ import { UserDuelState } from 'enum/userDuel.enum' import { UserExplorationState } from 'enum/userExploration.enum' import { UserQuizState } from 'enum/userQuiz.enum' import { UserChallenge } from 'models' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' -import { AppActionsTypes, AppStore } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { getChallengeTitleWithLineReturn, importIconById } from 'utils/utils' import ChallengeNoFluidModal from './ChallengeNoFluidModal' import StarsContainer from './StarsContainer' @@ -34,16 +33,16 @@ const ChallengeCardOnGoing = ({ }) => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() + const dispatch = useAppDispatch() + const { + challenge: { currentDataload }, + global: { fluidTypes, fluidStatus }, + } = useAppSelector(state => state.ecolyo) const [isOneFluidUp, setIsOneFluidUp] = useState<boolean>(true) const [challengeIcon, setChallengeIcon] = useState<string>(defaultIcon) const [isDone, setIsDone] = useState<boolean>(false) const [isLoading, setIsLoading] = useState<boolean>(false) - const { - challenge: { currentDataload }, - global: { fluidTypes, fluidStatus }, - } = useSelector((state: AppStore) => state.ecolyo) const { progress: { actionProgress, explorationProgress, quizProgress }, target, diff --git a/src/components/Challenge/ChallengeCardUnlocked.tsx b/src/components/Challenge/ChallengeCardUnlocked.tsx index dc76880064e5c52a9e680bf394130e73ba743dd2..4276b6d540a85aa20f54d7c59dbc9093a22f9ff6 100644 --- a/src/components/Challenge/ChallengeCardUnlocked.tsx +++ b/src/components/Challenge/ChallengeCardUnlocked.tsx @@ -6,12 +6,11 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidState } from 'enum/fluid.enum' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallenge } from 'models' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { getChallengeTitleWithLineReturn, importIconById } from 'utils/utils' import ChallengeNoFluidModal from './ChallengeNoFluidModal' import './challengeCardUnlocked.scss' @@ -23,12 +22,12 @@ const ChallengeCardUnlocked = ({ }) => { const { t } = useI18n() const client: Client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const [openNoFluidModal, setopenNoFluidModal] = useState(false) const { - global: { fluidTypes, fluidStatus }, challenge: { currentChallenge }, - } = useSelector((state: AppStore) => state.ecolyo) + global: { fluidTypes, fluidStatus }, + } = useAppSelector(state => state.ecolyo) + const dispatch = useAppDispatch() + const [openNoFluidModal, setopenNoFluidModal] = useState(false) const [challengeIcon, setChallengeIcon] = useState(defaultIcon) let statusRequirementOk = false diff --git a/src/components/Challenge/ChallengeView.tsx b/src/components/Challenge/ChallengeView.tsx index 94673b49562f4f32338b9c073ca73032bd37894a..daa50f41730a2e2c0763447f85e99fc92da13176 100644 --- a/src/components/Challenge/ChallengeView.tsx +++ b/src/components/Challenge/ChallengeView.tsx @@ -7,16 +7,13 @@ import Header from 'components/Header/Header' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UserChallengeState } from 'enum/userChallenge.enum' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import ChallengeCard from './ChallengeCard' import './challengeView.scss' const ChallengeView = () => { const { t } = useI18n() - const { userChallengeList } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) + const { userChallengeList } = useAppSelector(state => state.ecolyo.challenge) const marginPx = 16 const cardWidth = diff --git a/src/components/Charts/AxisBottom.spec.tsx b/src/components/Charts/AxisBottom.spec.tsx index 11d3d39ca94cede74ba42344b19ed5fed5bf0d98..8e11560598d3c7ee3102b0341205abef4d319362 100644 --- a/src/components/Charts/AxisBottom.spec.tsx +++ b/src/components/Charts/AxisBottom.spec.tsx @@ -3,7 +3,6 @@ import { TimeStep } from 'enum/timeStep.enum' import { mount } from 'enzyme' import { DateTime } from 'luxon' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { graphData } from '../../../tests/__mocks__/chartData.mock' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' @@ -22,8 +21,6 @@ const mockProps = { marginBottom: 10, } -const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') - describe('AxisBottom component test', () => { const store = createMockEcolyoStore({ chart: { @@ -34,7 +31,6 @@ describe('AxisBottom component test', () => { }) beforeEach(() => { store.clearActions() - useDispatchSpy.mockClear() }) it('should correctly render YEAR format of AxisBottom', () => { diff --git a/src/components/Charts/AxisBottom.tsx b/src/components/Charts/AxisBottom.tsx index 0fcdc71c016200d196c21ee80a8b32b7f117327e..4e69f565b86bf1ac47bd575b0d69ec367d069185 100644 --- a/src/components/Charts/AxisBottom.tsx +++ b/src/components/Charts/AxisBottom.tsx @@ -4,9 +4,8 @@ import { capitalize } from 'lodash' import { DateTime } from 'luxon' import { Dataload } from 'models' import React from 'react' -import { useSelector } from 'react-redux' import DateChartService from 'services/dateChart.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' interface TextTypeProps { index: number @@ -139,7 +138,7 @@ const AxisBottom = ({ marginBottom, isDuel = false, }: AxisBottomProps) => { - const { selectedDate } = useSelector((state: AppStore) => state.ecolyo.chart) + const { selectedDate } = useAppSelector(state => state.ecolyo.chart) const dashArray = `${height / 30} ${height / 30}` const dateChartService = new DateChartService() const displayAllDays: boolean = isDuel && data.length <= 15 diff --git a/src/components/Charts/Bar.spec.tsx b/src/components/Charts/Bar.spec.tsx index 6ac99f422b455ab7dd481e74130f47518ebf7d2c..764fef2381197d5767c2aa61ae8dc86efc1a0dc7 100644 --- a/src/components/Charts/Bar.spec.tsx +++ b/src/components/Charts/Bar.spec.tsx @@ -4,7 +4,6 @@ import { TimeStep } from 'enum/timeStep.enum' import { mount } from 'enzyme' import { DateTime } from 'luxon' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import * as chartActions from 'store/chart/chart.slice' import { graphData } from '../../../tests/__mocks__/chartData.mock' @@ -34,7 +33,6 @@ const mockParam = { isDuel: false, } -const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') const setSelectedDateSpy = jest.spyOn(chartActions, 'setSelectedDate') const setCurrentDatachartIndexSpy = jest.spyOn( chartActions, @@ -44,7 +42,6 @@ const setCurrentDatachartIndexSpy = jest.spyOn( describe('Bar component test', () => { beforeEach(() => { store.clearActions() - useDispatchSpy.mockClear() setSelectedDateSpy.mockClear() setCurrentDatachartIndexSpy.mockClear() }) diff --git a/src/components/Charts/Bar.tsx b/src/components/Charts/Bar.tsx index 57f86f31795bfd07f5f6b49479b6b62e8eb6f689..8b8a12f732647ae222a7c51155b61992a6e1179a 100644 --- a/src/components/Charts/Bar.tsx +++ b/src/components/Charts/Bar.tsx @@ -4,14 +4,13 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Dataload } from 'models' -import React, { Dispatch, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useEffect, useState } from 'react' import DateChartService from 'services/dateChart.service' -import { AppActionsTypes, AppStore } from 'store' import { setCurrentDataChartIndex, setSelectedDate, } from 'store/chart/chart.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' interface BarProps { index: number @@ -46,8 +45,8 @@ const Bar = ({ weekdays, clickable = true, }: BarProps) => { - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { selectedDate } = useSelector((state: AppStore) => state.ecolyo.chart) + const dispatch = useAppDispatch() + const { selectedDate } = useAppSelector(state => state.ecolyo.chart) const [clicked, setClicked] = useState(false) const [animationEnded, setAnimationEnded] = useState(false) const [compareAnimationEnded, setCompareAnimationEnded] = useState(false) diff --git a/src/components/Charts/BarChart.tsx b/src/components/Charts/BarChart.tsx index 9483e03da8756f0359fb2eba52e6975a8d59834e..8cc731f8b494b9b0158cf1564517580ebfed0c5d 100644 --- a/src/components/Charts/BarChart.tsx +++ b/src/components/Charts/BarChart.tsx @@ -8,8 +8,7 @@ import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Datachart } from 'models' import React from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' export interface BarChartProps { chartData: Datachart @@ -38,7 +37,7 @@ const BarChart = ({ isSwitching, clickable = true, }: BarChartProps) => { - const { showCompare } = useSelector((state: AppStore) => state.ecolyo.chart) + const { showCompare } = useAppSelector(state => state.ecolyo.chart) const getContentWidth = () => { return width - marginLeft - marginRight } diff --git a/src/components/Connection/Connection.spec.tsx b/src/components/Connection/Connection.spec.tsx index 05bc2fcbbb4d4b339f44783b37b8fb7f92da2d9c..51cf0a26426928887f225058ce68541145e7ed24 100644 --- a/src/components/Connection/Connection.spec.tsx +++ b/src/components/Connection/Connection.spec.tsx @@ -2,7 +2,6 @@ import Connection from 'components/Connection/Connection' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { fluidStatusConnectedData } from '../../../tests/__mocks__/fluidStatusData.mock' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' @@ -29,7 +28,7 @@ jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: () => mockedNavigate, })) -const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') + describe('Connection component test', () => { const store = createMockEcolyoStore() it('should call GrdfInit', () => { @@ -42,7 +41,6 @@ describe('Connection component test', () => { }) it('should call EpglInit', () => { - useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> <Connection fluidStatus={fluidStatusConnectedData[0]} /> diff --git a/src/components/Connection/Connection.tsx b/src/components/Connection/Connection.tsx index bf29cd77bfb42391eff47d60a1db908da2d616c1..9a14f999e68b5fbd32a21faac6079ff6723fc105 100644 --- a/src/components/Connection/Connection.tsx +++ b/src/components/Connection/Connection.tsx @@ -1,16 +1,15 @@ import { FluidType } from 'enum/fluid.enum' import { FluidConnection, FluidStatus } from 'models' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch } from 'react-redux' -import { AppActionsTypes } from 'store' +import React, { useCallback } from 'react' import { updateFluidConnection } from 'store/global/global.slice' +import { useAppDispatch } from 'store/hooks' import EpglInit from './EPGLConnect/EpglInit' import GrdfInit from './GRDFConnect/GrdfInit' import SgeInit from './SGEConnect/SgeInit' import './connection.scss' const Connection = ({ fluidStatus }: { fluidStatus: FluidStatus }) => { - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const handleSuccess = useCallback(async () => { const updatedConnection: FluidConnection = { diff --git a/src/components/Connection/ConnectionResult.tsx b/src/components/Connection/ConnectionResult.tsx index 5a5390ec3a4a91b8c916f1ef592d0896586aaece..2c9684851ec40de434ff93ce8af0e91f5293424f 100644 --- a/src/components/Connection/ConnectionResult.tsx +++ b/src/components/Connection/ConnectionResult.tsx @@ -14,17 +14,16 @@ import { FluidStatus, Trigger, } from 'models' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import AccountService from 'services/account.service' import DateChartService from 'services/dateChart.service' import TriggerService from 'services/triggers.service' -import { AppActionsTypes } from 'store' import { setShouldRefreshConsent, updateFluidConnection, updateSgeStore, } from 'store/global/global.slice' +import { useAppDispatch } from 'store/hooks' import { getKonnectorUpdateError } from 'utils/utils' import DeleteGRDFAccountModal from './DeleteGRDFAccountModal' import './connectionResult.scss' @@ -42,7 +41,7 @@ const ConnectionResult = ({ }: ConnectionResultProps) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const account: Account | null = fluidStatus.connection.account const [deleting, setDeleting] = useState<boolean>(false) diff --git a/src/components/Connection/EPGLConnect/EpglBill.tsx b/src/components/Connection/EPGLConnect/EpglBill.tsx index ae01998eb4b042ecc3ab9e13e29d318eb2653066..f39634b2c9cd96c81e6aec0452fe7f456c53c981 100644 --- a/src/components/Connection/EPGLConnect/EpglBill.tsx +++ b/src/components/Connection/EPGLConnect/EpglBill.tsx @@ -3,17 +3,16 @@ import WaterBillIcon from 'assets/icons/visu/onboarding/water_bill.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidStatus } from 'models' -import React, { Dispatch } from 'react' -import { useDispatch } from 'react-redux' -import { AppActionsTypes } from 'store' +import React from 'react' import { setShowOfflineData } from 'store/chart/chart.slice' +import { useAppDispatch } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' import { decoreText } from 'utils/decoreText' import '../connection.scss' const EpglBill = ({ fluidStatus }: { fluidStatus: FluidStatus }) => { const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() return ( <div className="connection-form"> diff --git a/src/components/Connection/EPGLConnect/EpglInit.tsx b/src/components/Connection/EPGLConnect/EpglInit.tsx index be04c95c0c4aaad34b39624357d7a7b71942480c..23a1057a3130c3f67238ca017090c8d812096f96 100644 --- a/src/components/Connection/EPGLConnect/EpglInit.tsx +++ b/src/components/Connection/EPGLConnect/EpglInit.tsx @@ -1,18 +1,15 @@ import EpglConnectModal from 'components/Connection/PartnerConnectModal/EpglConnectModal' import { FluidStatus } from 'models' -import React, { Dispatch, useCallback, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { AppActionsTypes, AppStore } from 'store' +import React, { useCallback, useState } from 'react' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' import '../connection.scss' import EpglBill from './EpglBill' import EpglForm from './EpglForm' const EpglInit = ({ fluidStatus }: { fluidStatus: FluidStatus }) => { - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { - modal: { isConnectionModalOpen }, - } = useSelector((state: AppStore) => state.ecolyo) + const dispatch = useAppDispatch() + const { isConnectionModalOpen } = useAppSelector(state => state.ecolyo.modal) const siteLink: string = fluidStatus.connection.konnectorConfig.siteLink const [showForm, setShowForm] = useState(false) diff --git a/src/components/Connection/ExpiredConsentModal.spec.tsx b/src/components/Connection/ExpiredConsentModal.spec.tsx index a6f9f8fd42ab06fd5d8c2457600ce0b0c7355500..0e87a5e2b6b85622ccab0638ff690b18b9359ee6 100644 --- a/src/components/Connection/ExpiredConsentModal.spec.tsx +++ b/src/components/Connection/ExpiredConsentModal.spec.tsx @@ -3,8 +3,8 @@ import { FluidType } from 'enum/fluid.enum' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' +import * as storeHooks from 'store/hooks' import { fluidStatusConnectedData } from '../../../tests/__mocks__/fluidStatusData.mock' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import ExpiredConsentModal from './ExpiredConsentModal' @@ -19,17 +19,15 @@ jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: () => mockedNavigate, })) +const mockAppDispatch = jest.spyOn(storeHooks, 'useAppDispatch') const mockToggleModal = jest.fn() const mockHandleCloseClick = jest.fn() describe('ExpiredConsentModal component', () => { - const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') - useDispatchSpy.mockReturnValue(jest.fn()) const store = createMockEcolyoStore() beforeEach(() => { mockedNavigate.mockReset() - store.clearActions() - useDispatchSpy.mockClear() + mockAppDispatch.mockClear() }) it('should be rendered correctly', () => { const component = mount( @@ -56,7 +54,7 @@ describe('ExpiredConsentModal component', () => { </Provider> ) component.find(Button).at(1).simulate('click') - expect(useDispatchSpy).toHaveBeenCalledTimes(1) + expect(mockAppDispatch).toHaveBeenCalledTimes(1) expect(mockedNavigate).toHaveBeenCalledTimes(1) }) it('should launch the update consent process for Enedis', () => { @@ -74,7 +72,7 @@ describe('ExpiredConsentModal component', () => { </Provider> ) component.find(Button).at(1).simulate('click') - expect(useDispatchSpy).toHaveBeenCalledTimes(1) + expect(mockAppDispatch).toHaveBeenCalledTimes(1) expect(mockedNavigate).toHaveBeenCalledTimes(1) }) it('should click on close modal', () => { diff --git a/src/components/Connection/ExpiredConsentModal.tsx b/src/components/Connection/ExpiredConsentModal.tsx index 38b0f3c4bcc587acd85fb96513091be75d56e341..872b048a8b0176d8ba3ae4edc3d346b3736df005 100644 --- a/src/components/Connection/ExpiredConsentModal.tsx +++ b/src/components/Connection/ExpiredConsentModal.tsx @@ -7,14 +7,13 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { FluidType } from 'enum/fluid.enum' import { AccountSgeData } from 'models' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' -import { AppActionsTypes, AppStore } from 'store' import { setShouldRefreshConsent, updateSgeStore, } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { getFluidName } from 'utils/utils' import './expiredConsentModal.scss' @@ -33,9 +32,8 @@ const ExpiredConsentModal = ({ }: ExpiredConsentModalProps) => { const { t } = useI18n() const navigate = useNavigate() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) - + const dispatch = useAppDispatch() + const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const launchUpdateConsent = useCallback(() => { if (fluidType === FluidType.ELECTRICITY) { const accountData = fluidStatus[FluidType.ELECTRICITY].connection.account diff --git a/src/components/Connection/FormOAuth.tsx b/src/components/Connection/FormOAuth.tsx index 09fd2b99e645e170cf879826f53261c989609667..46df15916adea9eb0e8dffe7401e2fa016abefc2 100644 --- a/src/components/Connection/FormOAuth.tsx +++ b/src/components/Connection/FormOAuth.tsx @@ -4,11 +4,10 @@ import { OAuthWindow } from 'cozy-harvest-lib/dist/components/OAuthWindow' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { FluidStatus, Konnector } from 'models' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { setShouldRefreshConsent } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' interface FormOAuthProps { konnector: Konnector | null @@ -22,11 +21,9 @@ const FormOAuth = ({ konnector, onSuccess, fluidStatus }: FormOAuthProps) => { const { t } = useI18n() const client = useClient() + const { shouldRefreshConsent } = useAppSelector(state => state.ecolyo.global) + const dispatch = useAppDispatch() const [status, setStatus] = useState<string>(IDLE) - const { shouldRefreshConsent } = useSelector( - (state: AppStore) => state.ecolyo.global - ) - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const endOAuth = useCallback(() => { setStatus(IDLE) // Set back to false the variable that allows to automatically refresh the consent (deletes and recreates the account) diff --git a/src/components/Connection/GRDFConnect/GrdfBill.tsx b/src/components/Connection/GRDFConnect/GrdfBill.tsx index ad07fb26ee9cf63f400865201332c19f50a01f00..d547388ff58e8ad7be18c06f32157ec135c6f2d1 100644 --- a/src/components/Connection/GRDFConnect/GrdfBill.tsx +++ b/src/components/Connection/GRDFConnect/GrdfBill.tsx @@ -3,17 +3,16 @@ import GasBillIcon from 'assets/icons/visu/onboarding/gas_bill.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidStatus } from 'models' -import React, { Dispatch } from 'react' -import { useDispatch } from 'react-redux' -import { AppActionsTypes } from 'store' +import React from 'react' import { setShowOfflineData } from 'store/chart/chart.slice' +import { useAppDispatch } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' import { decoreText } from 'utils/decoreText' import '../connection.scss' const GrdfBill = ({ fluidStatus }: { fluidStatus: FluidStatus }) => { const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() return ( <div className="connection-form"> diff --git a/src/components/Connection/GRDFConnect/GrdfForm.tsx b/src/components/Connection/GRDFConnect/GrdfForm.tsx index b2f699e71838058c94363ef0388d709edcfdba60..070083929ac756efb6df51a5af879f4d8b00ab2a 100644 --- a/src/components/Connection/GRDFConnect/GrdfForm.tsx +++ b/src/components/Connection/GRDFConnect/GrdfForm.tsx @@ -2,15 +2,14 @@ import Button from '@material-ui/core/Button' import iconGrdfLogo from 'assets/icons/visu/grdf-logo.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import React, { Dispatch } from 'react' -import { useDispatch } from 'react-redux' -import { AppActionsTypes } from 'store' +import React from 'react' +import { useAppDispatch } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' import '../connection.scss' const GrdfForm = () => { const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() return ( <div className="connection-form"> diff --git a/src/components/Connection/GRDFConnect/GrdfInit.tsx b/src/components/Connection/GRDFConnect/GrdfInit.tsx index 764509c9a7f42028eb3c12e93ca25ddf7a17f3c7..d86b90fcabc390f3340eb91e893ca2785aac5d23 100644 --- a/src/components/Connection/GRDFConnect/GrdfInit.tsx +++ b/src/components/Connection/GRDFConnect/GrdfInit.tsx @@ -2,13 +2,12 @@ import GrdfConnectModal from 'components/Connection/PartnerConnectModal/GrdfConn import { useClient } from 'cozy-client' import { UsageEventType } from 'enum/usageEvent.enum' import { FluidConnection, FluidStatus, Konnector, Trigger } from 'models' -import React, { Dispatch, useCallback, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useState } from 'react' import AccountService from 'services/account.service' import TriggerService from 'services/triggers.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { updateFluidConnection } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' import '../connection.scss' import GrdfBill from './GrdfBill' @@ -21,10 +20,8 @@ interface GrdfInitProps { const GrdfInit = ({ fluidStatus, onSuccess }: GrdfInitProps) => { const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { - modal: { isConnectionModalOpen }, - } = useSelector((state: AppStore) => state.ecolyo) + const dispatch = useAppDispatch() + const { isConnectionModalOpen } = useAppSelector(state => state.ecolyo.modal) const [showForm, setShowForm] = useState(false) diff --git a/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx b/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx index a65895112383cc8f006d252cb591d0182d4218ab..ed87bc98d338451c668eb44bc26fee4f2c6d0b3c 100644 --- a/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx +++ b/src/components/Connection/SGEConnect/SgeConnectView.spec.tsx @@ -2,8 +2,8 @@ import { SgeStep } from 'enum/sgeStep.enum' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' +import * as storeHooks from 'store/hooks' import { createMockEcolyoStore, mockGlobalState, @@ -24,11 +24,11 @@ jest.mock('components/Content/Content', () => 'mock-content') jest.mock('components/FormGlobal/FormProgress', () => 'mock-formprogress') jest.mock('components/Header/CozyBar', () => 'mock-cozybar') -const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') +const mockAppDispatch = jest.spyOn(storeHooks, 'useAppDispatch') describe('SgeConnectView component', () => { beforeEach(() => { - useDispatchSpy.mockReset() + jest.clearAllMocks() }) it('should be rendered correctly', () => { const store = createMockEcolyoStore() @@ -104,9 +104,6 @@ describe('SgeConnectView component', () => { expect(wrapper.find('.stepIdentity')).toBeTruthy() }) describe('SgeConnectView Navigation methods', () => { - beforeEach(() => { - useDispatchSpy.mockReset() - }) const store = createMockEcolyoStore() it('should call nextStep method', () => { const wrapper = mount( @@ -115,7 +112,7 @@ describe('SgeConnectView component', () => { </Provider> ) wrapper.find('.profile-navigation-button').last().simulate('click') - expect(useDispatchSpy).toHaveBeenCalled() + expect(mockAppDispatch).toHaveBeenCalled() }) it('should not call disabled nextStep method', () => { const wrapper = mount( @@ -124,7 +121,7 @@ describe('SgeConnectView component', () => { </Provider> ) wrapper.find('.profile-navigation-button').last().simulate('click') - expect(useDispatchSpy).toHaveBeenCalled() + expect(mockAppDispatch).toHaveBeenCalled() }) }) }) diff --git a/src/components/Connection/SGEConnect/SgeConnectView.tsx b/src/components/Connection/SGEConnect/SgeConnectView.tsx index 9619c6b72aa8ba9b69c8eac8d02b415d4e102021..f4e08fb845bda0a3a374cbfb4ab5dc83083a74b4 100644 --- a/src/components/Connection/SGEConnect/SgeConnectView.tsx +++ b/src/components/Connection/SGEConnect/SgeConnectView.tsx @@ -5,10 +5,9 @@ import CozyBar from 'components/Header/CozyBar' import Header from 'components/Header/Header' import { SgeStep } from 'enum/sgeStep.enum' import { SgeStore } from 'models/sgeStore.model' -import React, { Dispatch, useCallback, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { AppActionsTypes, AppStore } from 'store' +import React, { useCallback, useState } from 'react' import { updateSgeStore } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import './SgeConnect.scss' import StepAddress from './StepAddress' import StepConsent from './StepConsent' @@ -25,17 +24,17 @@ export type SGEKeysForm = | 'pdlConfirm' const SgeConnectView = () => { - const [headerHeight, setHeaderHeight] = useState<number>(0) - const { sgeConnect } = useSelector((state: AppStore) => state.ecolyo.global) - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() + const { sgeConnect } = useAppSelector(state => state.ecolyo.global) + const [isLoading, setIsLoading] = useState(false) + const [currentSgeState, setCurrentSgeState] = useState<SgeStore>(sgeConnect) const [currentStep, setCurrentStep] = useState<SgeStep>( sgeConnect.currentStep ) - const [currentSgeState, setCurrentSgeState] = useState<SgeStore>(sgeConnect) + const [headerHeight, setHeaderHeight] = useState<number>(0) const defineHeaderHeight = useCallback((height: number) => { setHeaderHeight(height) }, []) - const [isLoading, setIsLoading] = useState(false) const isNextValid = useCallback(() => { switch (currentStep) { diff --git a/src/components/Connection/SGEConnect/SgeInit.tsx b/src/components/Connection/SGEConnect/SgeInit.tsx index ecec4ebab48cff9c64a784a8daaaed0c4db066be..6294b8d3a47f8131069d98bcfe0df35237103b72 100644 --- a/src/components/Connection/SGEConnect/SgeInit.tsx +++ b/src/components/Connection/SGEConnect/SgeInit.tsx @@ -4,15 +4,14 @@ import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import useKonnectorAuth from 'components/Hooks/useKonnectorAuth' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { Account, FluidStatus } from 'models' -import React, { Dispatch, useEffect } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useEffect } from 'react' import { useNavigate } from 'react-router-dom' -import { AppActionsTypes, AppStore } from 'store' import { setShowOfflineData } from 'store/chart/chart.slice' import { setShouldRefreshConsent, updateSgeStore, } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { decoreText } from 'utils/decoreText' const SgeInit = ({ fluidStatus }: { fluidStatus: FluidStatus }) => { @@ -20,9 +19,8 @@ const SgeInit = ({ fluidStatus }: { fluidStatus: FluidStatus }) => { const navigate = useNavigate() const konnectorSlug: string = fluidStatus.connection.konnectorConfig.slug const account: Account | null = fluidStatus.connection.account - const { sgeConnect } = useSelector((state: AppStore) => state.ecolyo.global) - - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const { sgeConnect } = useAppSelector(state => state.ecolyo.global) + const dispatch = useAppDispatch() const [connect, update] = useKonnectorAuth(fluidStatus) useEffect(() => { diff --git a/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx index d497f4279740b55cac3eb60cc1527c10f54b5aca..7fffa7d6a0d3b6844498229107b09688c01c2c31 100644 --- a/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/ConsumptionVisualizer.tsx @@ -3,8 +3,7 @@ import { FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' import { Dataload } from 'models' import React from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import InfoDataConsumptionVisualizer from './InfoDataConsumptionVisualizer' import './consumptionVisualizer.scss' @@ -19,7 +18,7 @@ const ConsumptionVisualizer = ({ const { chart: { currentDatachart, currentDatachartIndex }, global: { fluidStatus, fluidTypes }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const dataload: Dataload = currentDatachart.actualData[currentDatachartIndex] const compareDataload: Dataload | null = currentDatachart.comparisonData diff --git a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx index be0f81676b33701aa787dcf8c0556fb5519ccf95..af620801af7c88917e8db27f18aae89aa6b2ebcb 100644 --- a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.tsx @@ -2,8 +2,7 @@ import { DataloadSectionType, DataloadState } from 'enum/dataload.enum' import { FluidType } from 'enum/fluid.enum' import { Dataload } from 'models' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import DataloadNoValue from './DataloadNoValue' import DataloadSection from './DataloadSection' import EstimatedConsumptionModal from './EstimatedConsumptionModal' @@ -21,7 +20,7 @@ const DataloadConsumptionVisualizer = ({ compareDataload, setActive, }: DataloadConsumptionVisualizerProps) => { - const { showCompare } = useSelector((state: AppStore) => state.ecolyo.chart) + const { showCompare } = useAppSelector(state => state.ecolyo.chart) const [openEstimationModal, setOpenEstimationModal] = useState<boolean>(false) const toggleEstimationModal = useCallback(() => { setOpenEstimationModal(prev => !prev) diff --git a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx index 0de0cb23cc02573dd090caab5627a8c765ba9312..0c6bffa6d88961455df5a318f9ac327bb53dc074 100644 --- a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx +++ b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.spec.tsx @@ -5,8 +5,8 @@ import toJson from 'enzyme-to-json' import { DateTime } from 'luxon' import { Dataload } from 'models' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' +import * as storeHooks from 'store/hooks' import { baseDataLoad } from '../../../tests/__mocks__/chartData.mock' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import InfoDataConsumptionVisualizer from './InfoDataConsumptionVisualizer' @@ -18,7 +18,7 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => ({ })), })) -const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch') +const mockAppDispatch = jest.spyOn(storeHooks, 'useAppDispatch') describe('InfoDataConsumptionVisualizer component', () => { const mockLastDataDate = DateTime.fromISO('2020-10-01T00:00:00.000Z', { @@ -227,6 +227,6 @@ describe('InfoDataConsumptionVisualizer component', () => { </Provider> ) wrapper.find('.error-line').simulate('click') - expect(mockUseDispatch).toHaveBeenCalled() + expect(mockAppDispatch).toHaveBeenCalled() }) }) diff --git a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx index 4ac3bd9668d0f33d1072d2af5031e31b66b670af..0cb05b33247fa636cb8ed841a72d42120c50b354 100644 --- a/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx +++ b/src/components/ConsumptionVisualizer/InfoDataConsumptionVisualizer.tsx @@ -3,11 +3,10 @@ import { DataloadState } from 'enum/dataload.enum' import { FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' import { Dataload } from 'models' -import React, { Dispatch, useCallback, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useState } from 'react' import DateChartService from 'services/dateChart.service' -import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import NoDataModal from './NoDataModal' import './infoDataConsumptionVisualizer.scss' @@ -23,10 +22,8 @@ const InfoDataConsumptionVisualizer = ({ lastDataDate, }: InfoDataConsumptionVisualizerProps) => { const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { currentTimeStep } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) + const dispatch = useAppDispatch() + const { currentTimeStep } = useAppSelector(state => state.ecolyo.chart) const [openNodataModal, setopenNodataModal] = useState<boolean>(false) const toggleNoDataModal = useCallback(() => { diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx index da2111065187f3f116f51a620c5469d43eb2910a..72e9e0040b97df38bf8c5fa69e61fe5f5d9dc6b6 100644 --- a/src/components/Content/Content.tsx +++ b/src/components/Content/Content.tsx @@ -1,9 +1,8 @@ import FeedbackModal from 'components/Feedback/FeedbackModal' import { ScreenType } from 'enum/screen.enum' -import React, { Dispatch, useCallback, useEffect } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { AppActionsTypes, AppStore } from 'store' +import React, { useCallback, useEffect } from 'react' import { changeScreenType } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openFeedbackModal } from 'store/modal/modal.slice' import './content.scss' interface ContentProps { @@ -17,11 +16,11 @@ const Content = ({ height = 0, background = 'inherit', }: ContentProps) => { - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const { global: { screenType }, modal: { isFeedbacksOpen }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const cozyBarHeight = 48 const cozyNavHeight = 56 diff --git a/src/components/Duel/DuelBar.tsx b/src/components/Duel/DuelBar.tsx index 99cfce82752506906ef1cd3b18b888763c52a89c..7e2fb3d65224cbc9ac12f8cc55d3813e3c7cea56 100644 --- a/src/components/Duel/DuelBar.tsx +++ b/src/components/Duel/DuelBar.tsx @@ -8,8 +8,7 @@ import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Dataload, UserChallenge } from 'models' import React from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' export interface BarChartProps { userChallenge: UserChallenge @@ -36,9 +35,7 @@ const DuelBar = ({ marginTop = 20, marginBottom = 50, }: BarChartProps) => { - const { currentDataload } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) + const { currentDataload } = useAppSelector(state => state.ecolyo.challenge) const dataload: Dataload[] = finishedDataLoad ? finishedDataLoad : currentDataload diff --git a/src/components/Duel/DuelOngoing.tsx b/src/components/Duel/DuelOngoing.tsx index 98f13ec4bef5cfed2a2e840e4c6e3b2c0b4adc33..97804bdf20a5ee721eaeacbc616e0cd9448488df 100644 --- a/src/components/Duel/DuelOngoing.tsx +++ b/src/components/Duel/DuelOngoing.tsx @@ -15,24 +15,16 @@ import { } from 'enum/userChallenge.enum' import { UserDuelState } from 'enum/userDuel.enum' import { Dataload, UserChallenge, UserDuel } from 'models' -import React, { - Dispatch, - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { unlockNextUserChallenge, updateUserChallengeList, } from 'store/challenge/challenge.slice' import { toggleChallengeDuelNotification } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { formatNumberValues } from 'utils/utils' import './duelOngoing.scss' @@ -44,10 +36,10 @@ interface DuelOngoingProps { const DuelOngoing = ({ userChallenge, isFinished }: DuelOngoingProps) => { const client: Client = useClient() const { t } = useI18n() - const { currentDataload, userChallengeList } = useSelector( - (state: AppStore) => state.ecolyo.challenge + const { currentDataload, userChallengeList } = useAppSelector( + state => state.ecolyo.challenge ) - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const navigate = useNavigate() const [resultModal, setResultModal] = useState<boolean>(false) const [winChallenge, setWinChallenge] = useState<boolean>(false) diff --git a/src/components/Duel/DuelUnlocked.tsx b/src/components/Duel/DuelUnlocked.tsx index c4b16b9e0b10dc7818ed75cbb7cdfa12a01fd4c8..9ff52b9ecf8414b7e8f8a8057af195a7dd9eaf06 100644 --- a/src/components/Duel/DuelUnlocked.tsx +++ b/src/components/Duel/DuelUnlocked.tsx @@ -7,19 +7,18 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes } from 'store' import { setChallengeConsumption } from 'store/challenge/challenge.slice' +import { useAppDispatch } from 'store/hooks' import { formatNumberValues, importIconById } from 'utils/utils' import './duelUnlocked.scss' const DuelUnlocked = ({ userChallenge }: { userChallenge: UserChallenge }) => { - const client: Client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { t } = useI18n() + const client: Client = useClient() + const dispatch = useAppDispatch() const [duelIcon, setDuelIcon] = useState(defaultIcon) const average: string = formatNumberValues( diff --git a/src/components/Duel/DuelView.tsx b/src/components/Duel/DuelView.tsx index b5a269f172684c9e3c6bd968026265ff6e6b911f..4704f47a8d46699418944fba7bba51854ade6bcf 100644 --- a/src/components/Duel/DuelView.tsx +++ b/src/components/Duel/DuelView.tsx @@ -7,17 +7,14 @@ import { UserChallengeState } from 'enum/userChallenge.enum' import { UserDuelState } from 'enum/userDuel.enum' import { UserChallenge } from 'models' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' import { useLocation, useNavigate } from 'react-router-dom' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import DuelEmptyValueModal from './DuelEmptyValueModal' import DuelOngoing from './DuelOngoing' const DuelView = () => { + const { userChallengeList } = useAppSelector(state => state.ecolyo.challenge) const [headerHeight, setHeaderHeight] = useState<number>(0) - const { userChallengeList } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) const id = new URLSearchParams(useLocation().search).get('id') const challengeToDisplay: UserChallenge | undefined = userChallengeList.find( challenge => challenge.id === id diff --git a/src/components/Ecogesture/EcogestureModal.tsx b/src/components/Ecogesture/EcogestureModal.tsx index 64f363d9a26ab7bbc6e36a2c2b63aab8b431dfd0..43a412bc9b620fbd1152fcd5322fdff156ad5a3f 100644 --- a/src/components/Ecogesture/EcogestureModal.tsx +++ b/src/components/Ecogesture/EcogestureModal.tsx @@ -10,8 +10,7 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { Ecogesture } from 'models' import React, { useEffect, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { getPicto } from 'utils/picto' import { importIconById } from 'utils/utils' import EfficiencyRating from './EfficiencyRating' @@ -33,11 +32,9 @@ const EcogestureModal = ({ selectEcogesture, }: EcogestureModalProps) => { const { t } = useI18n() + const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const [ecogestureIcon, setEcogestureIcon] = useState('') const [isMoreDetail, setIsMoreDetail] = useState(false) - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) const [, setValidExploration] = useExploration() const toggleMoreDetail = () => { diff --git a/src/components/Ecogesture/EcogestureView.tsx b/src/components/Ecogesture/EcogestureView.tsx index 2ec75eacfa6b081fde5d28744ee3ec004d7debf3..d2d65a8f43b7f8b788a1efd1b4c2a36fc592f7bf 100644 --- a/src/components/Ecogesture/EcogestureView.tsx +++ b/src/components/Ecogesture/EcogestureView.tsx @@ -9,11 +9,10 @@ import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { EcogestureTab } from 'enum/ecogesture.enum' import { Ecogesture } from 'models' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import EcogestureService from 'services/ecogesture.service' -import { AppActionsTypes, AppStore } from 'store' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { updateProfile } from 'store/profile/profile.actions' import EcogestureEmptyList from './EcogestureEmptyList' import EcogestureInitModal from './EcogestureInitModal' @@ -46,9 +45,9 @@ const EcogestureView = () => { const { t } = useI18n() const client = useClient() const tab = new URLSearchParams(useLocation().search).get('tab') - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { profile, profileEcogesture, profileType } = useSelector( - (state: AppStore) => state.ecolyo + const dispatch = useAppDispatch() + const { profile, profileEcogesture, profileType } = useAppSelector( + state => state.ecolyo ) const [tabValue, setTabValue] = useState<EcogestureTab>( diff --git a/src/components/Ecogesture/SingleEcogesture.tsx b/src/components/Ecogesture/SingleEcogesture.tsx index 2dfef67887c5fbf4dbb76facec4ce16027a29eb2..a6c2f8fc42b64b7070f4e1995d1092a0ae177953 100644 --- a/src/components/Ecogesture/SingleEcogesture.tsx +++ b/src/components/Ecogesture/SingleEcogesture.tsx @@ -17,10 +17,9 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { Ecogesture } from 'models' import React, { useCallback, useEffect, useMemo, useState } from 'react' -import { useSelector } from 'react-redux' import { Location, useLocation, useNavigate, useParams } from 'react-router-dom' import EcogestureService from 'services/ecogesture.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { importIconById } from 'utils/utils' import EfficiencyRating from './EfficiencyRating' import './singleEcogesture.scss' @@ -49,9 +48,7 @@ const SingleEcogesture = () => { () => new EcogestureService(client), [client] ) - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) + const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const [headerHeight, setHeaderHeight] = useState<number>(0) const defineHeaderHeight = (height: number) => { setHeaderHeight(height) diff --git a/src/components/EcogestureForm/EcogestureFormEquipment.tsx b/src/components/EcogestureForm/EcogestureFormEquipment.tsx index b26bd8eec3c018ed818ea19796b30f15ff2f0d6b..44e57d700a40dde732f3d3bb24d7b3ba2001d961 100644 --- a/src/components/EcogestureForm/EcogestureFormEquipment.tsx +++ b/src/components/EcogestureForm/EcogestureFormEquipment.tsx @@ -6,8 +6,7 @@ import { EcogestureStepForm } from 'enum/ecogestureForm.enum' import { ProfileTypeStepForm } from 'enum/profileType.enum' import { ProfileEcogesture, ProfileType } from 'models' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import EquipmentIcon from './EquipmentIcon' import './ecogestureFormEquipment.scss' @@ -29,8 +28,8 @@ const EcogestureFormEquipment = ({ step, }: EcogestureFormEquipmentProps) => { const { t } = useI18n() - const { isProfileEcogestureCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile + const { isProfileEcogestureCompleted } = useAppSelector( + state => state.ecolyo.profile ) const previousEquipments = currentProfileType?.equipments || currentProfileEcogesture?.equipments || [] diff --git a/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx b/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx index ffcf2df03b700f465e69dc1bcfdeab2419ffafe0..e10245f146429f611123ff0ea8115576e33c58a4 100644 --- a/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx +++ b/src/components/EcogestureForm/EcogestureFormSingleChoice.spec.tsx @@ -1,9 +1,7 @@ -/* eslint-disable react/display-name */ import { Button } from '@material-ui/core' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { mockEcogestureAnswer, @@ -13,8 +11,6 @@ import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' import EcogestureFormSingleChoice from './EcogestureFormSingleChoice' -const useSelectorSpy = jest.spyOn(reactRedux, 'useSelector') - jest.mock('cozy-ui/transpiled/react/I18n', () => ({ useI18n: jest.fn(() => ({ t: (str: string) => str, diff --git a/src/components/EcogestureForm/EcogestureFormSingleChoice.tsx b/src/components/EcogestureForm/EcogestureFormSingleChoice.tsx index 5f1299666e89f4e2b82397ed0952840ec4922d03..f97c34100e39f31b2a1087bf03c687c31abcef47 100644 --- a/src/components/EcogestureForm/EcogestureFormSingleChoice.tsx +++ b/src/components/EcogestureForm/EcogestureFormSingleChoice.tsx @@ -9,8 +9,7 @@ import { ProfileEcogestureValues, } from 'models/profileEcogesture.model' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import './ecogestureFormSingleChoice.scss' interface EcogestureFormSingleChoiceProps { step: EcogestureStepForm @@ -30,8 +29,8 @@ const EcogestureFormSingleChoice = ({ setPreviousStep, }: EcogestureFormSingleChoiceProps) => { const { t } = useI18n() - const { isProfileEcogestureCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile + const { isProfileEcogestureCompleted } = useAppSelector( + state => state.ecolyo.profile ) const [answer, setAnswer] = useState<ProfileEcogestureValues>( isProfileEcogestureCompleted || step < viewedStep diff --git a/src/components/EcogestureForm/EcogestureFormView.spec.tsx b/src/components/EcogestureForm/EcogestureFormView.spec.tsx index 75c3f6529484f69c44dc9126f0f3a9ba199f6eb5..e8d5cf2950f7805da909c92f11bdca7a5535c203 100644 --- a/src/components/EcogestureForm/EcogestureFormView.spec.tsx +++ b/src/components/EcogestureForm/EcogestureFormView.spec.tsx @@ -5,6 +5,7 @@ import toJson from 'enzyme-to-json' import React from 'react' import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' +import * as storeHooks from 'store/hooks' import { mockProfileEcogesture } from '../../../tests/__mocks__/profileEcogesture.mock' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' @@ -23,6 +24,7 @@ jest.mock( () => 'mock-ecogesturelaunchmodal' ) const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch') +const mockAppDispatch = jest.spyOn(storeHooks, 'useAppDispatch') jest.mock('components/Content/Content', () => 'mock-content') const mockedNavigate = jest.fn() jest.mock('react-router-dom', () => ({ @@ -40,6 +42,7 @@ describe('EcogestureFormView component', () => { beforeEach(() => { store.clearActions() mockUseDispatch.mockClear() + mockAppDispatch.mockClear() }) it('should be rendered correctly', async () => { diff --git a/src/components/EcogestureForm/EcogestureFormView.tsx b/src/components/EcogestureForm/EcogestureFormView.tsx index b3faea70e482efb173af8a7949874f4c563d5f09..180018ebb9d6ef065610355337c4fa4249c5b554 100644 --- a/src/components/EcogestureForm/EcogestureFormView.tsx +++ b/src/components/EcogestureForm/EcogestureFormView.tsx @@ -15,19 +15,20 @@ import { ProfileEcogestureAnswer, } from 'models/profileEcogesture.model' import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import { useDispatch } from 'react-redux' import { useLocation, useNavigate } from 'react-router-dom' import ProfileEcogestureFormService from 'services/profileEcogestureForm.service' -import { AppActionsTypes, AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { updateProfile } from 'store/profile/profile.actions' import { newProfileEcogestureEntry } from 'store/profileEcogesture/profileEcogesture.actions' +import { AppActionsTypes } from 'store/store' const EcogestureFormView = () => { - const dispatch: Dispatch<AppActionsTypes> = useDispatch() const { profile: { isProfileTypeCompleted }, profileEcogesture, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) + const dispatch: Dispatch<AppActionsTypes> = useDispatch() const navigate = useNavigate() const [headerHeight, setHeaderHeight] = useState<number>(0) const defineHeaderHeight = (height: number) => { diff --git a/src/components/EcogestureSelection/EcogestureSelection.tsx b/src/components/EcogestureSelection/EcogestureSelection.tsx index a04d394156641b336a7a52541a33bb22663e438a..534f7cc7f5b47ffcd0a7c16244f9de82acebbe40 100644 --- a/src/components/EcogestureSelection/EcogestureSelection.tsx +++ b/src/components/EcogestureSelection/EcogestureSelection.tsx @@ -10,16 +10,16 @@ import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { Ecogesture } from 'models' import React, { useCallback, useEffect, useMemo, useState } from 'react' -import { useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import EcogestureService from 'services/ecogesture.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import './ecogestureSelection.scss' const EcogestureSelection = () => { const { t } = useI18n() const client = useClient() const navigate = useNavigate() + const { profileEcogesture } = useAppSelector(state => state.ecolyo) const [isLoading, setIsLoading] = useState(true) const [headerHeight, setHeaderHeight] = useState<number>(0) const [indexEcogesture, setIndexEcogesture] = useState<number>(0) @@ -37,9 +37,6 @@ const EcogestureSelection = () => { () => new EcogestureService(client), [client] ) - const profileEcogesture = useSelector( - (state: AppStore) => state.ecolyo.profileEcogesture - ) const getTitle = useCallback((): string => { if ( diff --git a/src/components/Exploration/ExplorationFinished.tsx b/src/components/Exploration/ExplorationFinished.tsx index d0382020c075a760250522d2e7f19f7950eec678..25750ed88c3216ad3e84b680cffc3db49200aa5f 100644 --- a/src/components/Exploration/ExplorationFinished.tsx +++ b/src/components/Exploration/ExplorationFinished.tsx @@ -7,14 +7,13 @@ import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserExplorationState } from 'enum/userExploration.enum' import { UserChallenge } from 'models' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { toggleChallengeExplorationNotification } from 'store/global/global.slice' +import { useAppDispatch } from 'store/hooks' import './explorationFinished.scss' interface ExplorationFinishedProps { @@ -22,9 +21,9 @@ interface ExplorationFinishedProps { } const ExplorationFinished = ({ userChallenge }: ExplorationFinishedProps) => { - const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const client: Client = useClient() + const dispatch = useAppDispatch() const navigate = useNavigate() const checkNotificationToEnd = useCallback(async () => { diff --git a/src/components/Exploration/ExplorationOngoing.tsx b/src/components/Exploration/ExplorationOngoing.tsx index 68bec1b732511e1a9d143647131db987522b0771..62d7c23a94d2e84ab72336de3fd6ab5d82e5145e 100644 --- a/src/components/Exploration/ExplorationOngoing.tsx +++ b/src/components/Exploration/ExplorationOngoing.tsx @@ -11,13 +11,12 @@ import { UserExplorationType, } from 'enum/userExploration.enum' import { UserChallenge } from 'models' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch } from 'store/hooks' import './explorationOngoing.scss' interface ExplorationOngoingProps { @@ -25,9 +24,9 @@ interface ExplorationOngoingProps { } const ExplorationOngoing = ({ userChallenge }: ExplorationOngoingProps) => { - const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const client: Client = useClient() + const dispatch = useAppDispatch() const navigate = useNavigate() const goBack = useCallback(() => { navigate(-1) diff --git a/src/components/Exploration/ExplorationView.tsx b/src/components/Exploration/ExplorationView.tsx index b08315fbbd9eb35b9b71449ea4342fb515bb102d..d10e22917db5fa37290119019f879bc3266a898f 100644 --- a/src/components/Exploration/ExplorationView.tsx +++ b/src/components/Exploration/ExplorationView.tsx @@ -4,17 +4,14 @@ import Header from 'components/Header/Header' import { UserExplorationState } from 'enum/userExploration.enum' import { UserChallenge } from 'models' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import ExplorationError from './ExplorationError' import ExplorationFinished from './ExplorationFinished' import ExplorationOngoing from './ExplorationOngoing' const ExplorationView = () => { + const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const [headerHeight, setHeaderHeight] = useState<number>(0) - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) const defineHeaderHeight = useCallback((height: number) => { setHeaderHeight(height) diff --git a/src/components/Feedback/FeedbackModal.spec.tsx b/src/components/Feedback/FeedbackModal.spec.tsx index 361b5689cfaf24e23a8476bcce200799597f4eb2..4f9602cee3dbea9ccd854e10dd17dff41dfb50fe 100644 --- a/src/components/Feedback/FeedbackModal.spec.tsx +++ b/src/components/Feedback/FeedbackModal.spec.tsx @@ -1,7 +1,6 @@ import FeedbackModal from 'components/Feedback/FeedbackModal' import { mount } from 'enzyme' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' @@ -25,8 +24,6 @@ jest.mock('services/environment.service', () => { const handleFeedbackModalClose = jest.fn() -const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch') - describe('FeedbackModal component', () => { const store = createMockEcolyoStore() beforeEach(() => { @@ -34,7 +31,6 @@ describe('FeedbackModal component', () => { }) it('should render the component', () => { // TODO fix empty snapshot - mockUseDispatch.mockReturnValue(jest.fn()) const component = mount( <Provider store={store}> <FeedbackModal @@ -48,7 +44,6 @@ describe('FeedbackModal component', () => { describe('FeedbackModal functionalities', () => { it('should close the modal', async () => { - mockUseDispatch.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> <FeedbackModal diff --git a/src/components/Feedback/FeedbackModal.tsx b/src/components/Feedback/FeedbackModal.tsx index e3858f129f868e2fd709e2dc1204071768ebd897..59f1f2b1dd7d76eef258b66d5f5291d16cf0cc4d 100644 --- a/src/components/Feedback/FeedbackModal.tsx +++ b/src/components/Feedback/FeedbackModal.tsx @@ -6,6 +6,7 @@ import ecolyoIcon from 'assets/icons/ico/ecolyo.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import useExploration from 'components/Hooks/useExploration' import { Client, useClient } from 'cozy-client' +// what is the type ? import { IuseI18n, useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { UserExplorationID } from 'enum/userExploration.enum' diff --git a/src/components/FluidChart/FluidChart.tsx b/src/components/FluidChart/FluidChart.tsx index 158f05147fa75b80d0ee524d3fa1d24be833e13a..9af86833846feb32ecdc714ce40afb796482fa44 100644 --- a/src/components/FluidChart/FluidChart.tsx +++ b/src/components/FluidChart/FluidChart.tsx @@ -11,19 +11,18 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { UsageEventType } from 'enum/usageEvent.enum' import { UserExplorationID } from 'enum/userExploration.enum' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import ConsumptionService from 'services/consumption.service' import DateChartService from 'services/dateChart.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setSelectedDate, setShowCompare, setShowOfflineData, } from 'store/chart/chart.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' import { getFluidName, getKonnectorSlug, isKonnectorActive } from 'utils/utils' import FluidChartSwipe from './FluidChartSwipe' @@ -40,8 +39,8 @@ const FluidChart = ({ fluidType, setActive }: FluidChartProps) => { const { chart: { currentTimeStep, selectedDate, showCompare }, global: { fluidStatus }, - } = useSelector((state: AppStore) => state.ecolyo) - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + } = useAppSelector(state => state.ecolyo) + const dispatch = useAppDispatch() const navigate = useNavigate() const currentFluidStatus = fluidStatus[fluidType] diff --git a/src/components/FluidChart/FluidChartSlide.tsx b/src/components/FluidChart/FluidChartSlide.tsx index 3218478982d6992111d99ad95b292aa6ccfb8634..22dcca206cc0db86f243c0f4618b44602d2fa7e4 100644 --- a/src/components/FluidChart/FluidChartSlide.tsx +++ b/src/components/FluidChart/FluidChartSlide.tsx @@ -6,12 +6,11 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Datachart } from 'models' -import React, { Dispatch, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useEffect, useState } from 'react' import ConsumptionService from 'services/consumption.service' import DateChartService from 'services/dateChart.service' -import { AppActionsTypes, AppStore } from 'store' import { setCurrentDataChart, setLoading } from 'store/chart/chart.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import './fluidChartSlide.scss' interface FluidChartSlideProps { @@ -32,11 +31,11 @@ const FluidChartSlide = ({ setActive, }: FluidChartSlideProps) => { const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const { chart: { currentTimeStep, currentIndex }, global: { fluidStatus, fluidTypes }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const [chartData, setChartData] = useState<Datachart>({ actualData: [], diff --git a/src/components/FluidChart/FluidChartSwipe.tsx b/src/components/FluidChart/FluidChartSwipe.tsx index 403d914b9de79fbe1cd75fbc1e6f86951a41d147..0649c71913b61752db8b3609fd02c67e183e2779 100644 --- a/src/components/FluidChart/FluidChartSwipe.tsx +++ b/src/components/FluidChart/FluidChartSwipe.tsx @@ -2,13 +2,12 @@ import FluidChartSlide from 'components/FluidChart/FluidChartSlide' import { useChartResize } from 'components/Hooks/useChartResize' import { FluidType } from 'enum/fluid.enum' import { DateTime } from 'luxon' -import React, { Dispatch, useEffect, useRef, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useEffect, useRef, useState } from 'react' import SwipeableViews from 'react-swipeable-views' import { virtualize } from 'react-swipeable-views-utils' import DateChartService from 'services/dateChart.service' -import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setSelectedDate } from 'store/chart/chart.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import './fluidChartSwipe.scss' const VirtualizeSwipeableViews = virtualize(SwipeableViews) @@ -19,10 +18,9 @@ interface FluidChartSwipeProps { } const FluidChartSwipe = ({ fluidType, setActive }: FluidChartSwipeProps) => { - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { currentIndex, currentTimeStep, selectedDate, loading } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) + const dispatch = useAppDispatch() + const { currentIndex, currentTimeStep, selectedDate, loading } = + useAppSelector(state => state.ecolyo.chart) const swipe = useRef<HTMLDivElement>(null) const [isSwitching, setIsSwitching] = useState(false) diff --git a/src/components/Header/CozyBar.tsx b/src/components/Header/CozyBar.tsx index 0c0ca007800e0706f7ab72ee5cfa920daa857694..7169d94f891116b76ea851942406f73093cf3b26 100644 --- a/src/components/Header/CozyBar.tsx +++ b/src/components/Header/CozyBar.tsx @@ -3,10 +3,9 @@ import FeedbackIcon from 'assets/icons/ico/feedback.svg' import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { ScreenType } from 'enum/screen.enum' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' -import { AppActionsTypes, AppStore } from 'store' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openFeedbackModal } from 'store/modal/modal.slice' import cozyBar from 'utils/cozyBar' @@ -24,9 +23,9 @@ const CozyBar = ({ }: CozyBarProps) => { const { t } = useI18n() const navigate = useNavigate() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const { BarLeft, BarCenter, BarRight } = cozyBar - const { screenType } = useSelector((state: AppStore) => state.ecolyo.global) + const dispatch = useAppDispatch() + const { screenType } = useAppSelector(state => state.ecolyo.global) const handleClickBack = useCallback(() => { if (backFunction) { diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 428868001f84e7c0efb8d60e5c46008e4e4c73b8..907185e2346debe24a88154d4c838cc5fa4b3203 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -4,10 +4,9 @@ import FeedbackIcon from 'assets/icons/ico/feedback.svg' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' import { ScreenType } from 'enum/screen.enum' -import React, { Dispatch, useCallback, useEffect, useRef } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useRef } from 'react' import { useNavigate } from 'react-router-dom' -import { AppActionsTypes, AppStore } from 'store' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openFeedbackModal } from 'store/modal/modal.slice' import './header.scss' @@ -32,9 +31,8 @@ const Header = ({ const { t } = useI18n() const navigate = useNavigate() const header = useRef<HTMLDivElement>(null) - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { screenType } = useSelector((state: AppStore) => state.ecolyo.global) - + const dispatch = useAppDispatch() + const { screenType } = useAppSelector(state => state.ecolyo.global) const cozyBarHeight = 48 const handleClickBack = useCallback(() => { diff --git a/src/components/Home/ConsumptionDetails.spec.tsx b/src/components/Home/ConsumptionDetails.spec.tsx index dc82714f2d0ace0aec0a92550e33708b3c268a3c..dbe7e2e9db55e7630bbbad4edad59cc41ec88a92 100644 --- a/src/components/Home/ConsumptionDetails.spec.tsx +++ b/src/components/Home/ConsumptionDetails.spec.tsx @@ -2,7 +2,6 @@ import { FluidType } from 'enum/fluid.enum' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { waitForComponentToPaint } from '../../../tests/__mocks__/testUtils' @@ -14,13 +13,10 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => ({ })), })) -const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') - describe('ConsumptionDetails component', () => { const store = createMockEcolyoStore() beforeEach(() => { store.clearActions() - mockUseSelector.mockClear() }) it('should be rendered correctly', async () => { const wrapper = mount( diff --git a/src/components/Home/ConsumptionDetails.tsx b/src/components/Home/ConsumptionDetails.tsx index 3d17fc62059044c64b543d436f9da187b4dc75b5..3781a45dabda3d7ff6f5d375c9b76651e45bcd55 100644 --- a/src/components/Home/ConsumptionDetails.tsx +++ b/src/components/Home/ConsumptionDetails.tsx @@ -3,15 +3,14 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import React from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { convertDateToShortDateString } from 'utils/date' import './consumptionDetails.scss' const ConsumptionDetails = ({ fluidType }: { fluidType: FluidType }) => { const { t } = useI18n() - const { currentTimeStep, currentDatachart, showCompare } = useSelector( - (state: AppStore) => state.ecolyo.chart + const { currentTimeStep, currentDatachart, showCompare } = useAppSelector( + state => state.ecolyo.chart ) return ( diff --git a/src/components/Home/ConsumptionView.spec.tsx b/src/components/Home/ConsumptionView.spec.tsx index a484849352b8b1cebf2836e25383a5ffe4e8d7fa..9cf225a5777845de671c9e28b0fe9bd771c79ace 100644 --- a/src/components/Home/ConsumptionView.spec.tsx +++ b/src/components/Home/ConsumptionView.spec.tsx @@ -3,7 +3,6 @@ import { FluidState, FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { mount } from 'enzyme' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import * as chartActions from 'store/chart/chart.slice' import { mockCustomPopup } from '../../../tests/__mocks__/customPopup.mock' @@ -62,7 +61,6 @@ jest.mock( () => 'mock-SgeConnectView' ) -const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') const setCurrentTimeStepSpy = jest.spyOn(chartActions, 'setCurrentTimeStep') const mockFluidStatus = mockInitialEcolyoState.global.fluidStatus @@ -74,7 +72,6 @@ describe('ConsumptionView component', () => { const store = createMockEcolyoStore() beforeEach(() => { store.clearActions() - useDispatchSpy.mockClear() setCurrentTimeStepSpy.mockClear() }) @@ -213,7 +210,6 @@ describe('ConsumptionView component', () => { }, modal: { partnersIssueModal: { enedis: false, grdf: false, egl: true } }, }) - useDispatchSpy.mockReturnValue(jest.fn()) mockUpdateProfile.mockResolvedValue(mockTestProfile1) const wrapper = mount( <Provider store={store}> @@ -233,7 +229,6 @@ describe('ConsumptionView component', () => { }, modal: mockModalState, }) - useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> <ConsumptionView fluidType={FluidType.GAS} /> @@ -252,7 +247,6 @@ describe('ConsumptionView component', () => { }, modal: mockModalState, }) - useDispatchSpy.mockReturnValue(jest.fn()) const wrapper = mount( <Provider store={store}> <ConsumptionView fluidType={FluidType.ELECTRICITY} /> @@ -273,7 +267,6 @@ describe('ConsumptionView component', () => { customPopupModal: mockCustomPopup, }, }) - useDispatchSpy.mockReturnValue(jest.fn()) mockUpdateProfile.mockResolvedValue(mockTestProfile1) const wrapper = mount( <Provider store={store}> @@ -294,7 +287,6 @@ describe('ConsumptionView component', () => { }, modal: mockModalState, }) - useDispatchSpy.mockReturnValue(jest.fn()) mockUpdateProfile.mockResolvedValue(mockTestProfile1) const wrapper = mount( <Provider store={store}> diff --git a/src/components/Home/ConsumptionView.tsx b/src/components/Home/ConsumptionView.tsx index c34985012334adde67c4d2c1013feee68e059aa1..5e4d8924c281b014abd849e4a82556615995e867 100644 --- a/src/components/Home/ConsumptionView.tsx +++ b/src/components/Home/ConsumptionView.tsx @@ -16,12 +16,10 @@ import { useClient } from 'cozy-client' import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import DateChartService from 'services/dateChart.service' import ProfileService from 'services/profile.service' -import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setCurrentTimeStep, @@ -29,6 +27,7 @@ import { setShowOfflineData, } from 'store/chart/chart.slice' import { showReleaseNotes } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openPartnersModal, setCustomPopup } from 'store/modal/modal.slice' import { isLastDateReached } from 'utils/date' import { @@ -42,7 +41,7 @@ import './consumptionView.scss' const ConsumptionView = ({ fluidType }: { fluidType: FluidType }) => { const navigate = useNavigate() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const isMulti = fluidType === FluidType.MULTIFLUID const { chart: { @@ -54,7 +53,7 @@ const ConsumptionView = ({ fluidType }: { fluidType: FluidType }) => { }, global: { fluidStatus, releaseNotes }, modal: { partnersIssueModal, customPopupModal }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const dateChartService = new DateChartService() diff --git a/src/components/Home/FluidButton.tsx b/src/components/Home/FluidButton.tsx index dcc93f5344cb85a26f2b9f95753b5e68ed24e731..9346e264fe20bcf2deb002cd85b607f9512baa3d 100644 --- a/src/components/Home/FluidButton.tsx +++ b/src/components/Home/FluidButton.tsx @@ -6,11 +6,10 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { FluidState, FluidType } from 'enum/fluid.enum' import { UsageEventType } from 'enum/usageEvent.enum' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import DateChartService from 'services/dateChart.service' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { getNavPicto } from 'utils/picto' import { getFluidName, isKonnectorActive } from 'utils/utils' @@ -21,9 +20,9 @@ interface FluidButtonProps { const FluidButton = ({ fluidType, isActive }: FluidButtonProps) => { const { t } = useI18n() - const navigate = useNavigate() - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) const client = useClient() + const navigate = useNavigate() + const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const [showError, setShowError] = useState<boolean>(false) const isConnected = useCallback(() => { diff --git a/src/components/Home/ReleaseNotesModal.tsx b/src/components/Home/ReleaseNotesModal.tsx index 13dac570ae33003d448fcaaaf5e2376182bfd6af..d775351c8e6e8b0891d487df0adaeac80e7bb19e 100644 --- a/src/components/Home/ReleaseNotesModal.tsx +++ b/src/components/Home/ReleaseNotesModal.tsx @@ -2,8 +2,7 @@ import Button from '@material-ui/core/Button' import Dialog from '@material-ui/core/Dialog' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import React from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { decoreText } from 'utils/decoreText' import './ReleaseNotesModal.scss' @@ -17,7 +16,7 @@ const ReleaseNotesModal = ({ handleCloseClick, }: ReleaseNotesModalProps) => { const { t } = useI18n() - const { releaseNotes } = useSelector((state: AppStore) => state.ecolyo.global) + const { releaseNotes } = useAppSelector(state => state.ecolyo.global) return ( <Dialog diff --git a/src/components/Hooks/useExploration.spec.tsx b/src/components/Hooks/useExploration.spec.tsx index 8124169d7a6da85771fc34babf4d922a769866bd..44f3be5635936e5be918723f99a13f8b1bba4d1b 100644 --- a/src/components/Hooks/useExploration.spec.tsx +++ b/src/components/Hooks/useExploration.spec.tsx @@ -1,19 +1,21 @@ import { act, renderHook } from '@testing-library/react-hooks' import useExploration from 'components/Hooks/useExploration' import { UserExplorationID } from 'enum/userExploration.enum' -import * as reactRedux from 'react-redux' +import React from 'react' +import { Provider } from 'react-redux' +import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { userChallengeExplo1OnGoing } from '../../../tests/__mocks__/userChallengeData.mock' -const dispatchMock = jest.fn() -const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') -const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch') - describe('useExploration Hooks', () => { it('should return "EXPLORATION001"', () => { - mockUseDispatch.mockReturnValue(dispatchMock) - mockUseSelector.mockReturnValue(userChallengeExplo1OnGoing) + const store = createMockEcolyoStore({ + challenge: { currentChallenge: userChallengeExplo1OnGoing }, + }) - const { result } = renderHook(() => useExploration()) + const wrapper = ({ children }: { children: JSX.Element }) => ( + <Provider store={store}>{children}</Provider> + ) + const { result } = renderHook(() => useExploration(), { wrapper }) act(() => { result.current[1](UserExplorationID.EXPLORATION001) diff --git a/src/components/Hooks/useExploration.tsx b/src/components/Hooks/useExploration.tsx index 8874651fd3d64c6d4f88a096e8117d958cb798d1..cb8dd408b68c4bd54006a7ba1d1368f630b486c1 100644 --- a/src/components/Hooks/useExploration.tsx +++ b/src/components/Hooks/useExploration.tsx @@ -1,19 +1,16 @@ import { Client, useClient } from 'cozy-client' import { UserExplorationState } from 'enum/userExploration.enum' -import { ChallengeState, UserExploration } from 'models' +import { UserExploration } from 'models' import { Dispatch, SetStateAction, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' import ExplorationService from 'services/exploration.service' -import { AppActionsTypes, AppStore } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { toggleChallengeExplorationNotification } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' const useExploration = (): [string, Dispatch<SetStateAction<string>>] => { const client: Client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { currentChallenge }: ChallengeState = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) + const dispatch = useAppDispatch() + const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const exploration: UserExploration | null = currentChallenge ? currentChallenge.exploration : null diff --git a/src/components/Hooks/useKonnectorAuth.tsx b/src/components/Hooks/useKonnectorAuth.tsx index 8d34bc5bfe44a77aa7e5d342888a18a9aabc2856..10ae4f8bc71afb509a0565d4470b1104240296dc 100644 --- a/src/components/Hooks/useKonnectorAuth.tsx +++ b/src/components/Hooks/useKonnectorAuth.tsx @@ -10,14 +10,13 @@ import { FluidStatus, UsageEvent, } from 'models' -import { Dispatch, useCallback, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import { useCallback, useState } from 'react' import AccountService from 'services/account.service' import ConnectionService from 'services/connection.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { setLoading } from 'store/chart/chart.slice' import { updateFluidConnection } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import logApp from 'utils/logger' const useKonnectorAuth = ( @@ -27,11 +26,10 @@ const useKonnectorAuth = ( ): [() => Promise<null | undefined>, () => Promise<void>, string] => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const konnectorSlug: FluidSlugType = fluidStatus.connection.konnectorConfig.slug - const { sgeConnect } = useSelector((state: AppStore) => state.ecolyo.global) - + const { sgeConnect } = useAppSelector(state => state.ecolyo.global) const [connectError, setError] = useState<string>('') const onSuccess = useCallback(async () => { diff --git a/src/components/Konnector/KonnectorViewerCard.tsx b/src/components/Konnector/KonnectorViewerCard.tsx index fb5d5e4dc24055dd600080cd3085e23066cf253b..54d1914237748acd3b7fee1d4c899956d64274f0 100644 --- a/src/components/Konnector/KonnectorViewerCard.tsx +++ b/src/components/Konnector/KonnectorViewerCard.tsx @@ -41,14 +41,7 @@ import { UsageEvent, } from 'models' import { PartnersInfo } from 'models/partnersInfo.model' -import React, { - Dispatch, - useCallback, - useEffect, - useMemo, - useState, -} from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' import AccountService from 'services/account.service' import ChallengeService from 'services/challenge.service' @@ -56,7 +49,6 @@ import DateChartService from 'services/dateChart.service' import FluidService from 'services/fluid.service' import PartnersInfoService from 'services/partnersInfo.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { setChallengeConsumption } from 'store/challenge/challenge.slice' import { setSelectedDate, setShowOfflineData } from 'store/chart/chart.slice' import { @@ -64,6 +56,7 @@ import { toggleChallengeDuelNotification, updatedFluidConnection, } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' import { getAddPicto, getParamPicto } from 'utils/picto' import { getKonnectorSlug } from 'utils/utils' @@ -90,7 +83,7 @@ const KonnectorViewerCard = ({ }: KonnectorViewerCardProps) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const navigate = useNavigate() const fluidSlug = fluidStatus.connection.konnectorConfig.slug @@ -101,7 +94,7 @@ const KonnectorViewerCard = ({ const { challenge: { currentChallenge }, global: { fluidStatus: statusArray, shouldRefreshConsent, partnersInfo }, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const [openModal, setOpenModal] = useState(false) const [isUpdating, setIsUpdating] = useState(false) diff --git a/src/components/Konnector/KonnectorViewerList.tsx b/src/components/Konnector/KonnectorViewerList.tsx index e4c0c6190ead10314feb40b986357b73821e3537..98acb829e127253d0af0a3a047fb85355349ded3 100644 --- a/src/components/Konnector/KonnectorViewerList.tsx +++ b/src/components/Konnector/KonnectorViewerList.tsx @@ -4,16 +4,15 @@ import Icon from 'cozy-ui/transpiled/react/Icon' import { FluidType } from 'enum/fluid.enum' import { FluidStatus } from 'models' import React, { useCallback } from 'react' -import { useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { getAddPicto } from 'utils/picto' import { getFluidName } from 'utils/utils' import './konnectorViewerList.scss' const KonnectorViewerList = () => { const { t } = useI18n() - const { fluidStatus } = useSelector((state: AppStore) => state.ecolyo.global) + const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const navigate = useNavigate() const goToFluid = useCallback( fluidType => { diff --git a/src/components/Navbar/Navbar.tsx b/src/components/Navbar/Navbar.tsx index 8a67ad38cee09c38990f77aee618d032d6e77919..23f01ebdabb3d937496f7ee6f37f4dbba93c9e13 100644 --- a/src/components/Navbar/Navbar.tsx +++ b/src/components/Navbar/Navbar.tsx @@ -15,10 +15,9 @@ import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import React, { useCallback } from 'react' -import { useSelector } from 'react-redux' import { NavLink, useLocation } from 'react-router-dom' import UsageEventService from 'services/usageEvent.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import './navBar.scss' export const Navbar = () => { @@ -28,7 +27,7 @@ export const Navbar = () => { challengeActionNotification, challengeDuelNotification, analysisNotification, - } = useSelector((state: AppStore) => state.ecolyo.global) + } = useAppSelector(state => state.ecolyo.global) const { pathname } = useLocation() const client = useClient() diff --git a/src/components/Options/HelpLink/HelpLink.tsx b/src/components/Options/HelpLink/HelpLink.tsx index d463ce5213c874808dce1bed554589738d594d68..3a1c82dd69eadb534edc582e629c39d1548b6ce0 100644 --- a/src/components/Options/HelpLink/HelpLink.tsx +++ b/src/components/Options/HelpLink/HelpLink.tsx @@ -2,15 +2,14 @@ import Link from '@material-ui/core/Link' import QuestionMarkIcon from 'assets/icons/ico/questionMark.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import React, { Dispatch } from 'react' -import { useDispatch } from 'react-redux' -import { AppActionsTypes } from 'store' +import React from 'react' +import { useAppDispatch } from 'store/hooks' import { openFeedbackModal } from 'store/modal/modal.slice' import './HelpLink.scss' const HelpLink = () => { const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() return ( <div diff --git a/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx b/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx index 79fab17416acdb05de78815e3c60dd48b7cd7a29..a09e959c0b0abfd6094496edc987e8eb72e009c1 100644 --- a/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx +++ b/src/components/Options/ProfileTypeOptions/ProfileTypeOptions.tsx @@ -20,15 +20,12 @@ import { } from 'enum/profileType.enum' import { UserExplorationID } from 'enum/userExploration.enum' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import './profileTypeOptions.scss' const ProfileTypeOptions = () => { - const { profile, profileType } = useSelector( - (state: AppStore) => state.ecolyo - ) + const { profile, profileType } = useAppSelector(state => state.ecolyo) const { t } = useI18n() const navigate = useNavigate() const [, setValidExploration] = useExploration() diff --git a/src/components/Options/ReportOptions/ReportOptions.tsx b/src/components/Options/ReportOptions/ReportOptions.tsx index f24ed8ad617ba3e00d17a6e691037208b78ba6ea..5853217c6b7b8fdf07cae9514dcd5024c6d6f666 100644 --- a/src/components/Options/ReportOptions/ReportOptions.tsx +++ b/src/components/Options/ReportOptions/ReportOptions.tsx @@ -6,21 +6,20 @@ import { FluidState, FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { DateTime } from 'luxon' import { Dataload, TimePeriod } from 'models' -import React, { Dispatch, useCallback, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useEffect, useState } from 'react' import ConsumptionDataManager from 'services/consumption.service' -import { AppActionsTypes, AppStore } from 'store' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { updateProfile } from 'store/profile/profile.actions' import './reportOptions.scss' const ReportOptions = () => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const { global: { fluidStatus }, profile, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const [maxDayData, setLastSemesterMaxDay] = useState<Dataload | null>(null) const updateProfileReport = async (value: boolean) => { diff --git a/src/components/Options/Unsubscribe/UnSubscribe.tsx b/src/components/Options/Unsubscribe/UnSubscribe.tsx index 1ce8beeaae6f58656ba78f755aec99863aeb804f..ed3637f2680f9ddc8eeecc274bfab6fa21ccd612 100644 --- a/src/components/Options/Unsubscribe/UnSubscribe.tsx +++ b/src/components/Options/Unsubscribe/UnSubscribe.tsx @@ -5,21 +5,20 @@ import Content from 'components/Content/Content' import CozyBar from 'components/Header/CozyBar' import Header from 'components/Header/Header' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import React, { Dispatch, useState } from 'react' -import { useDispatch } from 'react-redux' +import React, { useState } from 'react' import { useNavigate } from 'react-router-dom' -import { AppActionsTypes } from 'store' +import { useAppDispatch } from 'store/hooks' import { updateProfile } from 'store/profile/profile.actions' import './unSubscribe.scss' const UnSubscribe = () => { + const { t } = useI18n() + const navigate = useNavigate() + const dispatch = useAppDispatch() const [headerHeight, setHeaderHeight] = useState<number>(0) const defineHeaderHeight = (height: number) => { setHeaderHeight(height) } - const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const navigate = useNavigate() const unSubscribe = async () => { dispatch(updateProfile({ sendAnalysisNotification: false })) navigate('/consumption') diff --git a/src/components/ProfileType/ProfileTypeFinished.tsx b/src/components/ProfileType/ProfileTypeFinished.tsx index c47d58667093a21e73439766aeaff0f0fb7f25f3..e8a2b8fcf54d2c798f92cb06fb76bf7476819f62 100644 --- a/src/components/ProfileType/ProfileTypeFinished.tsx +++ b/src/components/ProfileType/ProfileTypeFinished.tsx @@ -12,26 +12,25 @@ import { UserExplorationID } from 'enum/userExploration.enum' import { DateTime } from 'luxon' import { TimePeriod } from 'models' import { ProfileType } from 'models/profileType.model' -import React, { Dispatch, useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useEffect, useState } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import ProfileTypeService from 'services/profileType.service' import ProfileTypeEntityService from 'services/profileTypeEntity.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { updateProfile } from 'store/profile/profile.actions' import { setProfileType } from 'store/profileType/profileType.slice' const ProfileTypeFinished = ({ profileType }: { profileType: ProfileType }) => { const { t } = useI18n() + const client = useClient() const location = useLocation() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() const navigate = useNavigate() - const client = useClient() + const dispatch = useAppDispatch() const { challenge: { currentChallenge }, profile, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const handleClick = () => { if (location?.pathname === '/ecogesture-form') { navigate('/ecogesture-selection') diff --git a/src/components/ProfileType/ProfileTypeFormMultiChoice.tsx b/src/components/ProfileType/ProfileTypeFormMultiChoice.tsx index 95c275ca6ed38d8739724fe4e400e87fb8f930c0..ffa3adc18c577852c36c46a4eb2d28529f241c72 100644 --- a/src/components/ProfileType/ProfileTypeFormMultiChoice.tsx +++ b/src/components/ProfileType/ProfileTypeFormMultiChoice.tsx @@ -7,8 +7,7 @@ import { ProfileTypeStepForm } from 'enum/profileType.enum' import { remove } from 'lodash' import { ProfileType, ProfileTypeAnswer } from 'models/profileType.model' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' interface ProfileTypeFormMultiChoiceProps { step: ProfileTypeStepForm @@ -28,8 +27,8 @@ const ProfileTypeFormMultiChoice = ({ setPreviousStep, }: ProfileTypeFormMultiChoiceProps) => { const { t } = useI18n() - const { isProfileTypeCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile + const { isProfileTypeCompleted } = useAppSelector( + state => state.ecolyo.profile ) const [answer, setAnswer] = useState<string[]>([]) diff --git a/src/components/ProfileType/ProfileTypeFormNumber.tsx b/src/components/ProfileType/ProfileTypeFormNumber.tsx index 2b700fedc1d03328846830491e6e6db9e0dbf3c6..bcbee75fdbaa8250fda7a5cb4a9449d4af181439 100644 --- a/src/components/ProfileType/ProfileTypeFormNumber.tsx +++ b/src/components/ProfileType/ProfileTypeFormNumber.tsx @@ -9,8 +9,7 @@ import { ProfileTypeValues, } from 'models/profileType.model' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' interface ProfileTypeFormNumberProps { step: ProfileTypeStepForm @@ -30,8 +29,8 @@ const ProfileTypeFormNumber = ({ setPreviousStep, }: ProfileTypeFormNumberProps) => { const { t } = useI18n() - const { isProfileTypeCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile + const { isProfileTypeCompleted } = useAppSelector( + state => state.ecolyo.profile ) const [answer, setAnswer] = useState<ProfileTypeValues>('') diff --git a/src/components/ProfileType/ProfileTypeFormNumberSelection.tsx b/src/components/ProfileType/ProfileTypeFormNumberSelection.tsx index 034e8bde4ea6aeb0e360891e97308b93bb5b6a94..16734ea06d25cc375877c4b268890513d49d2832 100644 --- a/src/components/ProfileType/ProfileTypeFormNumberSelection.tsx +++ b/src/components/ProfileType/ProfileTypeFormNumberSelection.tsx @@ -10,8 +10,7 @@ import { ProfileTypeValues, } from 'models/profileType.model' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' interface ProfileTypeFormNumberSelectionProps { step: ProfileTypeStepForm @@ -31,8 +30,8 @@ const ProfileTypeFormNumberSelection = ({ setPreviousStep, }: ProfileTypeFormNumberSelectionProps) => { const { t } = useI18n() - const { isProfileTypeCompleted } = useSelector( - (state: AppStore) => state.ecolyo.profile + const { isProfileTypeCompleted } = useAppSelector( + state => state.ecolyo.profile ) const [answer, setAnswer] = useState<ProfileTypeValues>('') const [index, setIndex] = useState<number>(0) diff --git a/src/components/ProfileType/ProfileTypeFormSingleChoice.tsx b/src/components/ProfileType/ProfileTypeFormSingleChoice.tsx index 85f3a0e17801a9d517d538f95cbc7c5ae9a8b105..d48e92b70bf84253137e4b89a2e7633888977459 100644 --- a/src/components/ProfileType/ProfileTypeFormSingleChoice.tsx +++ b/src/components/ProfileType/ProfileTypeFormSingleChoice.tsx @@ -11,8 +11,7 @@ import { ProfileTypeValues, } from 'models/profileType.model' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' interface ProfileTypeFormSingleChoiceProps { step: ProfileTypeStepForm @@ -35,7 +34,7 @@ const ProfileTypeFormSingleChoice = ({ const { profile: { isProfileTypeCompleted, isProfileEcogestureCompleted }, profileEcogesture, - } = useSelector((state: AppStore) => state.ecolyo) + } = useAppSelector(state => state.ecolyo) const [answer, setAnswer] = useState<ProfileTypeValues>('') const handlePrevious = useCallback(() => { diff --git a/src/components/ProfileType/ProfileTypeView.tsx b/src/components/ProfileType/ProfileTypeView.tsx index f5c18d2bc5a4d3812e6d8e4e499e1a20a887baf5..5fdbf3506f4211fd50454ecdee96c16d3e2f1b1b 100644 --- a/src/components/ProfileType/ProfileTypeView.tsx +++ b/src/components/ProfileType/ProfileTypeView.tsx @@ -27,14 +27,13 @@ import { import { DateTime } from 'luxon' import { ProfileType, ProfileTypeAnswer } from 'models' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import ProfileTypeFormService from 'services/profileTypeForm.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import ProfileTypeFormDateSelection from './ProfileTypeFormDateSelection' const ProfileTypeView = () => { - const { profile, profileType, profileEcogesture } = useSelector( - (state: AppStore) => state.ecolyo + const { profile, profileType, profileEcogesture } = useAppSelector( + state => state.ecolyo ) const [headerHeight, setHeaderHeight] = useState<number>(0) diff --git a/src/components/Quiz/QuizBegin.tsx b/src/components/Quiz/QuizBegin.tsx index 5ba3ea40ab895c1b1c6999bb9b4e2fe586a78b76..634f3242139954555d6b28fd85c2e24a7f740165 100644 --- a/src/components/Quiz/QuizBegin.tsx +++ b/src/components/Quiz/QuizBegin.tsx @@ -6,17 +6,16 @@ import { Client, useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React, { Dispatch } from 'react' -import { useDispatch } from 'react-redux' +import React from 'react' import ChallengeService from 'services/challenge.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch } from 'store/hooks' import './quizBegin.scss' const QuizBegin = ({ userChallenge }: { userChallenge: UserChallenge }) => { const client: Client = useClient() const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const launchQuiz = async () => { const challengeService: ChallengeService = new ChallengeService(client) const userChallengeUpdated: UserChallenge = diff --git a/src/components/Quiz/QuizCustomQuestionContent.tsx b/src/components/Quiz/QuizCustomQuestionContent.tsx index 1c4efae265ba27fc645e474a42e8bc20353c9ac6..21a37a7a60074192972072e7f92d56cf6f6866b4 100644 --- a/src/components/Quiz/QuizCustomQuestionContent.tsx +++ b/src/components/Quiz/QuizCustomQuestionContent.tsx @@ -8,13 +8,12 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UsageEventType } from 'enum/usageEvent.enum' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { Answer, QuestionEntity, UserChallenge, UserQuiz } from 'models' -import React, { Dispatch, useState } from 'react' -import { useDispatch } from 'react-redux' +import React, { useState } from 'react' import ChallengeService from 'services/challenge.service' import QuizService from 'services/quiz.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch } from 'store/hooks' import './quizQuestion.scss' interface QuizCustomQuestionContent { @@ -31,12 +30,12 @@ const QuizCustomQuestionContent = ({ isLoading, }: QuizCustomQuestionContent) => { const { t } = useI18n() + const client: Client = useClient() + const dispatch = useAppDispatch() + const [userChoice, setUserChoice] = useState<string>('') const [openModal, setOpenModal] = useState<boolean>(false) const [answerIndex, setAnswerIndex] = useState<number>(0) - const client: Client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const quizService: QuizService = new QuizService(client) const challengeService: ChallengeService = new ChallengeService(client) diff --git a/src/components/Quiz/QuizFinish.tsx b/src/components/Quiz/QuizFinish.tsx index e3abbcf0ae72a04aca396c055a72e576237c731d..65eac3431eebdf63dbf2af5a5b3206d1b6dbb197 100644 --- a/src/components/Quiz/QuizFinish.tsx +++ b/src/components/Quiz/QuizFinish.tsx @@ -5,19 +5,18 @@ import { Client, useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { UserChallenge } from 'models' -import React, { Dispatch, useCallback, useMemo } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback, useMemo } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch } from 'store/hooks' import './quizFinish.scss' const QuizFinish = ({ userChallenge }: { userChallenge: UserChallenge }) => { - const client: Client = useClient() const { t } = useI18n() + const client: Client = useClient() const navigate = useNavigate() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const challengeService: ChallengeService = useMemo( () => new ChallengeService(client), [client] diff --git a/src/components/Quiz/QuizQuestion.spec.tsx b/src/components/Quiz/QuizQuestion.spec.tsx index 8fade6b52c372b85258bbcf9fdc673275141fdcc..5f145d4dc948e5c393ae1d5579b4aaeeb4b847bc 100644 --- a/src/components/Quiz/QuizQuestion.spec.tsx +++ b/src/components/Quiz/QuizQuestion.spec.tsx @@ -2,7 +2,6 @@ import { UserQuestionState } from 'enum/userQuiz.enum' import { mount } from 'enzyme' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { userChallengeData } from '../../../tests/__mocks__/userChallengeData.mock' @@ -37,13 +36,11 @@ jest.mock('components/Quiz/QuizCustomQuestionContent', () => () => ( jest.mock('components/Quiz/QuizQuestionContent', () => () => ( <div id="quizquestioncontent" /> )) -const useSelectorSpy = jest.spyOn(reactRedux, 'useSelector') describe('QuizQuestion component', () => { const store = createMockEcolyoStore() beforeEach(() => { store.clearActions() - useSelectorSpy.mockClear() }) it('should be rendered correctly with question', () => { diff --git a/src/components/Quiz/QuizQuestion.tsx b/src/components/Quiz/QuizQuestion.tsx index b433733c0755e9337c4e57f985f9e26d6ece2ba3..fb4704664b68035a58ab7b16ff36a40eb2fefae5 100644 --- a/src/components/Quiz/QuizQuestion.tsx +++ b/src/components/Quiz/QuizQuestion.tsx @@ -3,10 +3,9 @@ import QuizQuestionContent from 'components/Quiz/QuizQuestionContent' import { Client, useClient } from 'cozy-client' import { QuestionEntity, UserChallenge } from 'models' import React, { useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import { useNavigate } from 'react-router-dom' import QuizService from 'services/quiz.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import './quizQuestion.scss' const QuizQuestion = ({ userChallenge }: { userChallenge: UserChallenge }) => { @@ -20,7 +19,7 @@ const QuizQuestion = ({ userChallenge }: { userChallenge: UserChallenge }) => { const [customQuestionLoading, setCustomQuestionLoading] = useState<boolean>(false) const client: Client = useClient() - const { fluidTypes } = useSelector((state: AppStore) => state.ecolyo.global) + const { fluidTypes } = useAppSelector(state => state.ecolyo.global) const navigate = useNavigate() const goBack = () => { diff --git a/src/components/Quiz/QuizQuestionContent.tsx b/src/components/Quiz/QuizQuestionContent.tsx index 3007c8cc292541e4bbbbec3f353aaf3f906fbc63..28842fe8cdf88958fb0b2848acaae6e37b6f4cf8 100644 --- a/src/components/Quiz/QuizQuestionContent.tsx +++ b/src/components/Quiz/QuizQuestionContent.tsx @@ -7,11 +7,10 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { UserChallengeUpdateFlag } from 'enum/userChallenge.enum' import { Answer, UserChallenge, UserQuiz } from 'models' import React, { Dispatch, SetStateAction, useCallback, useState } from 'react' -import { useDispatch } from 'react-redux' import ChallengeService from 'services/challenge.service' import QuizService from 'services/quiz.service' -import { AppActionsTypes } from 'store' import { updateUserChallengeList } from 'store/challenge/challenge.slice' +import { useAppDispatch } from 'store/hooks' import './quizQuestion.scss' interface QuizQuestionContent { @@ -26,6 +25,8 @@ const QuizQuestionContent = ({ goBack, }: QuizQuestionContent) => { const { t } = useI18n() + const client: Client = useClient() + const dispatch = useAppDispatch() const questionIndexLocked = userChallenge.quiz.questions.findIndex( answer => answer.result == 0 ) @@ -35,9 +36,6 @@ const QuizQuestionContent = ({ const [questionIndex, setQuestionIndex] = useState<number>(questionIndexLocked) - const client: Client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const quizService: QuizService = new QuizService(client) const challengeService: ChallengeService = new ChallengeService(client) diff --git a/src/components/Quiz/QuizView.spec.tsx b/src/components/Quiz/QuizView.spec.tsx index 9d3ccb2c8e88bf880afeb4b504342cc3802edcb9..afa4acf447d78ab75ee822555927550a9908094b 100644 --- a/src/components/Quiz/QuizView.spec.tsx +++ b/src/components/Quiz/QuizView.spec.tsx @@ -3,7 +3,6 @@ import { UserQuizState } from 'enum/userQuiz.enum' import { mount } from 'enzyme' import { ChallengeState } from 'models' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { challengeStateData } from '../../../tests/__mocks__/challengeStateData.mock' import { @@ -29,10 +28,8 @@ jest.mock('react-router-dom', () => ({ jest.mock('components/Header/CozyBar', () => 'mock-cozybar') jest.mock('components/Header/Header', () => 'mock-header') jest.mock('components/Content/Content', () => 'mock-content') -const mockUseSelector = jest.spyOn(reactRedux, 'useSelector') describe('QuizView component', () => { - const store = createMockEcolyoStore() it('should be rendered with QuizBegin component when quiz state = unlocked', () => { const updatedUserChallenge = { ...userChallengeData[0], diff --git a/src/components/Quiz/QuizView.tsx b/src/components/Quiz/QuizView.tsx index 4888e43e1e9d84b8fdd285290cbc3453a39dee07..05caa6e913ef82f0a7642b6b458cd935bf1f86c9 100644 --- a/src/components/Quiz/QuizView.tsx +++ b/src/components/Quiz/QuizView.tsx @@ -4,17 +4,14 @@ import Header from 'components/Header/Header' import { UserQuizState } from 'enum/userQuiz.enum' import { UserChallenge } from 'models' import React, { useCallback, useState } from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import QuizBegin from './QuizBegin' import QuizFinish from './QuizFinish' import QuizQuestion from './QuizQuestion' const QuizView = () => { + const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const [headerHeight, setHeaderHeight] = useState<number>(0) - const { currentChallenge } = useSelector( - (state: AppStore) => state.ecolyo.challenge - ) const defineHeaderHeight = useCallback((height: number) => { setHeaderHeight(height) diff --git a/src/components/Splash/SplashRoot.spec.tsx b/src/components/Splash/SplashRoot.spec.tsx index 66bceb6703cab18bf649273d3ceef2fba2cf077a..c07b9314a0caca8a0cd1b60c51fdfde22d7c4de1 100644 --- a/src/components/Splash/SplashRoot.spec.tsx +++ b/src/components/Splash/SplashRoot.spec.tsx @@ -1,7 +1,6 @@ import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import SplashRoot from './SplashRoot' @@ -17,12 +16,10 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => ({ t: (str: string) => str, })), })) -const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch') describe('SplashRoot component', () => { it('should be rendered correctly', async () => { const store = createMockEcolyoStore() - mockUseDispatch.mockReturnValue(jest.fn()) const component = mount( <Provider store={store}> <SplashRoot>children</SplashRoot> diff --git a/src/components/Splash/SplashRoot.tsx b/src/components/Splash/SplashRoot.tsx index 8dc9e0c7807355bc29a4ed74739a7390d11eade5..6d535d2245b98b78ab0ff3bd56446dc4ba8550be 100644 --- a/src/components/Splash/SplashRoot.tsx +++ b/src/components/Splash/SplashRoot.tsx @@ -38,7 +38,6 @@ import InitializationService from 'services/initialization.service' import PartnersInfoService from 'services/partnersInfo.service' import ProfileTypeEntityService from 'services/profileTypeEntity.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes } from 'store' import { setAnalysisMonth } from 'store/analysis/analysis.slice' import { setChallengeConsumption, @@ -59,6 +58,7 @@ import { openPartnersModal, setCustomPopup } from 'store/modal/modal.slice' import { updateProfile } from 'store/profile/profile.actions' import { updateProfileEcogestureSuccess } from 'store/profileEcogesture/profileEcogesture.actions' import { setProfileType } from 'store/profileType/profileType.slice' +import { AppActionsTypes } from 'store/store' import { logDuration } from 'utils/duration' import logApp from 'utils/logger' import { getTodayDate } from 'utils/utils' diff --git a/src/components/Terms/DataShareConsentContent.tsx b/src/components/Terms/DataShareConsentContent.tsx index 8a561a2652fc27aea34e396bbcfc360315b31157..8ea9515c07f4adc324f79c2cd529e92dea74a5b8 100644 --- a/src/components/Terms/DataShareConsentContent.tsx +++ b/src/components/Terms/DataShareConsentContent.tsx @@ -1,15 +1,12 @@ import { useI18n } from 'cozy-ui/transpiled/react/I18n' import React from 'react' -import { useSelector } from 'react-redux' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { decoreText } from 'utils/decoreText' import './termsView.scss' const DataShareConsentContent = () => { const { t } = useI18n() - const { isFirstConnection } = useSelector( - (state: AppStore) => state.ecolyo.profile - ) + const { isFirstConnection } = useAppSelector(state => state.ecolyo.profile) return ( <div className="dataShare-content-root"> diff --git a/src/components/Terms/TermsView.spec.tsx b/src/components/Terms/TermsView.spec.tsx index 1ed51854d8d8805f88411564f4ffde41f03422f1..a987bed917cd3bc518567d191082914ce2f7e092 100644 --- a/src/components/Terms/TermsView.spec.tsx +++ b/src/components/Terms/TermsView.spec.tsx @@ -2,8 +2,8 @@ import { Button } from '@material-ui/core' import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' +import * as storeHooks from 'store/hooks' import { createMockEcolyoStore } from '../../../tests/__mocks__/store' import { mockUpToDateTerm } from '../../../tests/__mocks__/termsData.mock' import TermsView from './TermsView' @@ -30,7 +30,7 @@ jest.mock('react-router-dom', () => ({ useNavigate: () => mockedNavigate, })) -const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch') +const mockAppDispatch = jest.spyOn(storeHooks, 'useAppDispatch') const mockUpdateProfile = jest.fn() jest.mock('services/profile.service', () => { @@ -63,7 +63,7 @@ describe('TermsView component', () => { expect(wrapper.find('input').at(1).props().checked).toEqual(true) expect(wrapper.find(Button).first().hasClass('disabled')).toBeFalsy() wrapper.find(Button).first().simulate('click') - expect(mockUseDispatch).toHaveBeenCalledTimes(3) + expect(mockAppDispatch).toHaveBeenCalledTimes(3) }) it('should be rendered correctly', () => { const component = mount( diff --git a/src/components/Terms/TermsView.tsx b/src/components/Terms/TermsView.tsx index 58e2860a0b81516048b4d9801dd904e50bebfc24..6e79eafa7c32b803f54581b88784e0ac15db7b35 100644 --- a/src/components/Terms/TermsView.tsx +++ b/src/components/Terms/TermsView.tsx @@ -2,12 +2,11 @@ import { Button } from '@material-ui/core' import classNames from 'classnames' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import React, { Dispatch, useCallback, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useCallback, useState } from 'react' import { useNavigate } from 'react-router-dom' import TermsService from 'services/terms.service' -import { AppActionsTypes, AppStore } from 'store' import { updateTermsStatus } from 'store/global/global.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { decoreText } from 'utils/decoreText' import CGUModal from './CGUModal' import DataShareConsentContent from './DataShareConsentContent' @@ -18,9 +17,9 @@ import './termsView.scss' const TermsView = () => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() - const { termsStatus } = useSelector((state: AppStore) => state.ecolyo.global) const navigate = useNavigate() + const dispatch = useAppDispatch() + const { termsStatus } = useAppSelector(state => state.ecolyo.global) const [GCUValidation, setGCUValidation] = useState<boolean>(false) const [dataConsentValidation, setDataConsentValidation] = useState<boolean>(false) diff --git a/src/components/TimeStepSelector/TimeStepSelector.spec.tsx b/src/components/TimeStepSelector/TimeStepSelector.spec.tsx index 5961840a97d09013de14a017776b2a3402705d4a..216566537690a0214df75ea1c990c49ffa229116 100644 --- a/src/components/TimeStepSelector/TimeStepSelector.spec.tsx +++ b/src/components/TimeStepSelector/TimeStepSelector.spec.tsx @@ -6,7 +6,6 @@ import { mount } from 'enzyme' import toJson from 'enzyme-to-json' import { DateTime } from 'luxon' import React from 'react' -import * as reactRedux from 'react-redux' import { Provider } from 'react-redux' import UsageEventService from 'services/usageEvent.service' import * as chartActions from 'store/chart/chart.slice' @@ -22,16 +21,12 @@ jest.mock('services/usageEvent.service') const mockAddEvent = jest.fn() UsageEventService.addEvent = mockAddEvent -const useSelectorSpy = jest.spyOn(reactRedux, 'useSelector') -const useDispatchSpy = jest.spyOn(reactRedux, 'useDispatch') const setCurrentTimeStepSpy = jest.spyOn(chartActions, 'setCurrentTimeStep') const setCurrentIndexSpy = jest.spyOn(chartActions, 'setCurrentIndex') const setSelectedDateSpy = jest.spyOn(chartActions, 'setSelectedDate') describe('TimeStepSelector component', () => { beforeEach(() => { - useSelectorSpy.mockClear() - useDispatchSpy.mockClear() setCurrentTimeStepSpy.mockClear() }) diff --git a/src/components/TimeStepSelector/TimeStepSelector.tsx b/src/components/TimeStepSelector/TimeStepSelector.tsx index 6a72bc1eb2f2c1ff068bec5e62eff491c1d50151..ff58ddf61bfcbc7b2671412915589c5cecbb8e03 100644 --- a/src/components/TimeStepSelector/TimeStepSelector.tsx +++ b/src/components/TimeStepSelector/TimeStepSelector.tsx @@ -5,25 +5,24 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { UsageEventType } from 'enum/usageEvent.enum' import { DateTime } from 'luxon' -import React, { Dispatch } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React from 'react' import DateChartService from 'services/dateChart.service' import UsageEventService from 'services/usageEvent.service' -import { AppActionsTypes, AppStore } from 'store' import { setCurrentIndex, setCurrentTimeStep, setSelectedDate, } from 'store/chart/chart.slice' +import { useAppDispatch, useAppSelector } from 'store/hooks' import { getFluidName } from 'utils/utils' import './timeStepSelector.scss' const TimeStepSelector = ({ fluidType }: { fluidType: FluidType }) => { - const { currentTimeStep, selectedDate } = useSelector( - (state: AppStore) => state.ecolyo.chart - ) const { t } = useI18n() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() + const { currentTimeStep, selectedDate } = useAppSelector( + state => state.ecolyo.chart + ) const dateChartService = new DateChartService() const client = useClient() const timeStepElecArray: TimeStep[] = [ diff --git a/src/components/TotalConsumption/TotalConsumption.tsx b/src/components/TotalConsumption/TotalConsumption.tsx index 032b6a78c8abf542b0480657790b67bfe6bf510a..6f82323b5b83004343c9e1cb75c6cf6a1e07f3b8 100644 --- a/src/components/TotalConsumption/TotalConsumption.tsx +++ b/src/components/TotalConsumption/TotalConsumption.tsx @@ -6,16 +6,15 @@ import { FluidType } from 'enum/fluid.enum' import { TimeStep } from 'enum/timeStep.enum' import { Dataload } from 'models' import React, { useCallback, useEffect, useState } from 'react' -import { useSelector } from 'react-redux' import ConsumptionService from 'services/consumption.service' import ConverterService from 'services/converter.service' -import { AppStore } from 'store' +import { useAppSelector } from 'store/hooks' import { formatNumberValues } from 'utils/utils' import './totalConsumption.scss' const TotalConsumption = ({ fluidType }: { fluidType: FluidType }) => { - const { currentTimeStep, showCompare, currentDatachart } = useSelector( - (state: AppStore) => state.ecolyo.chart + const { currentTimeStep, showCompare, currentDatachart } = useAppSelector( + state => state.ecolyo.chart ) const client = useClient() const [totalValue, setTotalValue] = useState<string>('-----') diff --git a/src/components/WelcomeModal/WelcomeModal.tsx b/src/components/WelcomeModal/WelcomeModal.tsx index a4fcf032d60a1827fe036c8022ad29388de970d3..3e8fdf83bc6c829bf1797578745f1da175535c01 100644 --- a/src/components/WelcomeModal/WelcomeModal.tsx +++ b/src/components/WelcomeModal/WelcomeModal.tsx @@ -5,11 +5,10 @@ import useUserInstanceSettings from 'components/Hooks/useUserInstanceSettings' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' -import React, { Dispatch, useCallback } from 'react' -import { useDispatch } from 'react-redux' +import React, { useCallback } from 'react' import EnvironmentService from 'services/environment.service' import MailService from 'services/mail.service' -import { AppActionsTypes } from 'store' +import { useAppDispatch } from 'store/hooks' import { updateProfile } from 'store/profile/profile.actions' import './welcomeModal.scss' @@ -23,7 +22,7 @@ interface WelcomeModalProps { const WelcomeModal = ({ open }: WelcomeModalProps) => { const { t } = useI18n() const client = useClient() - const dispatch = useDispatch<Dispatch<AppActionsTypes>>() + const dispatch = useAppDispatch() const { data: instanceSettings } = useUserInstanceSettings() const setWelcomeModalViewed = useCallback(async () => { diff --git a/src/store/hooks.ts b/src/store/hooks.ts new file mode 100644 index 0000000000000000000000000000000000000000..0bca4f1d36098142d9a157990c2e956946e276be --- /dev/null +++ b/src/store/hooks.ts @@ -0,0 +1,9 @@ +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' +import { AppDispatch, AppStore } from './store' + +// Typed hooks +// https://redux.js.org/tutorials/typescript-quick-start#define-typed-hooks + +export const useAppDispatch: () => AppDispatch = useDispatch +// TODO maybe use AppEcolyoStore +export const useAppSelector: TypedUseSelectorHook<AppStore> = useSelector diff --git a/src/store/profile/profile.actions.ts b/src/store/profile/profile.actions.ts index 4d3808f88bd9ad846956f91f837cfc8b9b34e595..a05d598b5238acc78c261095a036b2234f11afbf 100644 --- a/src/store/profile/profile.actions.ts +++ b/src/store/profile/profile.actions.ts @@ -2,7 +2,7 @@ import { Client } from 'cozy-client' import { Profile } from 'models' import { Dispatch } from 'react' import ProfileService from 'services/profile.service' -import { AppStore, defaultAction } from 'store' +import { AppStore, defaultAction } from 'store/store' export const UPDATE_PROFILE = 'UPDATE_PROFILE' diff --git a/src/store/profile/profile.reducer.spec.ts b/src/store/profile/profile.reducer.spec.ts index ed3adbd7f2a31816eb0d3e558180008bc0120ec9..7f3ef296d3edbd6368f79aba18ad0e09554ffa22 100644 --- a/src/store/profile/profile.reducer.spec.ts +++ b/src/store/profile/profile.reducer.spec.ts @@ -1,4 +1,4 @@ -import { defaultAction } from 'store' +import { defaultAction } from 'store/store' import { mockProfileState } from '../../../tests/__mocks__/store' import { UPDATE_PROFILE } from './profile.actions' import { profileReducer } from './profile.reducer' diff --git a/src/store/profileEcogesture/profileEcogesture.actions.ts b/src/store/profileEcogesture/profileEcogesture.actions.ts index 77140546584eca81839145ed7e8571534cf4c82c..6c170945fb16cac0d85618a2da3d1da1788011d4 100644 --- a/src/store/profileEcogesture/profileEcogesture.actions.ts +++ b/src/store/profileEcogesture/profileEcogesture.actions.ts @@ -3,7 +3,7 @@ import { PROFILEECOGESTURE_DOCTYPE } from 'doctypes/com-grandlyon-ecolyo-profile import { ProfileEcogesture } from 'models/profileEcogesture.model' import { Dispatch } from 'react' import ProfileEcogestureService from 'services/profileEcogesture.service' -import { AppStore, defaultAction } from 'store' +import { AppStore, defaultAction } from 'store/store' // TODO never used ? export const CREATE_NEW_PROFILE_ECOGESTURE = 'CREATE_NEW_PROFILE_ECOGESTURE' diff --git a/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts b/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts index 1158a9881f3f659e21808483c764c1a324095e8a..fad1d9947e64de3e11065bce36fee2d559efb7db 100644 --- a/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts +++ b/src/store/profileEcogesture/profileEcogesture.reducer.spec.ts @@ -1,4 +1,4 @@ -import { defaultAction } from 'store' +import { defaultAction } from 'store/store' import { mockProfileEcogesture, mockProfileEcogestureUpdated, diff --git a/src/store/index.ts b/src/store/store.ts similarity index 91% rename from src/store/index.ts rename to src/store/store.ts index 9bcaeb06d3647e83113d749ced0fa7d82ca47d6f..0e40d9fa049bf18fc780fd2699fc1fae2fb625b5 100644 --- a/src/store/index.ts +++ b/src/store/store.ts @@ -119,3 +119,8 @@ const configureStore = (client: Client, persistedState: any) => { return store } export default configureStore + +// Infer the `RootState` and `AppDispatch` types from the store itself +export type AppEcolyoState = ReturnType<typeof ecolyoReducer> // TODO should use "ReturnType<typeof store.getState>" when using configureStore +export type AppStores = ReturnType<typeof configureStore> +export type AppDispatch = AppStores['dispatch'] diff --git a/src/targets/browser/index.tsx b/src/targets/browser/index.tsx index d8800d9b42c840aacf87c62f71dbf5cc28899e77..54ba4fbb6d4764574a411db77efb2f4d79adfc06 100644 --- a/src/targets/browser/index.tsx +++ b/src/targets/browser/index.tsx @@ -20,7 +20,7 @@ import { render } from 'react-dom' import { Provider } from 'react-redux' import { HashRouter } from 'react-router-dom' import EnvironmentService from 'services/environment.service' -import configureStore from 'store' +import configureStore from 'store/store' import cozyBar from 'utils/cozyBar' import logApp from 'utils/logger' import MatomoTracker from 'utils/matomoTracker' diff --git a/tests/__mocks__/store/store.ts b/tests/__mocks__/store/store.ts index 7f39d022fcfe7a4d5f8832fff69e3066a9264a47..edcf8340dbf730b315fc53f4494cfaed9d850e79 100644 --- a/tests/__mocks__/store/store.ts +++ b/tests/__mocks__/store/store.ts @@ -1,6 +1,6 @@ import configureStore from 'redux-mock-store' import thunkMiddleware from 'redux-thunk' -import { AppActionsTypes, EcolyoState, MockEcolyoState } from 'store' +import { AppActionsTypes, EcolyoState, MockEcolyoState } from 'store/store' import mockClient from '../client' import { mockProfileEcogesture } from '../profileEcogesture.mock' import { mockAnalysisState } from './analysis.state.mock'