-
Bastien DUMONT authoredBastien DUMONT authored
ConsumptionView.tsx 9.60 KiB
import ExpiredConsentModal from 'components/Connection/ExpiredConsentModal/ExpiredConsentModal'
import Content from 'components/Content/Content'
import CustomPopupModal from 'components/CustomPopup/CustomPopupModal'
import DateNavigator from 'components/DateNavigator/DateNavigator'
import FluidChart from 'components/FluidChart/FluidChart'
import CozyBar from 'components/Header/CozyBar'
import Header from 'components/Header/Header'
import KonnectorViewerCard from 'components/Konnector/KonnectorViewerCard'
import KonnectorViewerList from 'components/Konnector/KonnectorViewerList'
import PartnerIssueModal from 'components/PartnerIssue/PartnerIssueModal'
import ReleaseNotesModal from 'components/ReleaseNotesModal/ReleaseNotesModal'
import { useClient } from 'cozy-client'
import { FluidType, TimeStep } from 'enums'
import { DateTime } from 'luxon'
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 {
setCurrentIndex,
setCurrentTimeStep,
setSelectedDate,
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 {
getKonnectorUpdateError,
getTodayDate,
isKonnectorActive,
} from 'utils/utils'
import ConsumptionDetails from './ConsumptionDetails/ConsumptionDetails'
import FluidButtons from './FluidButtons/FluidButtons'
const ConsumptionView = ({ fluidType }: { fluidType: FluidType }) => {
const navigate = useNavigate()
const client = useClient()
const dispatch = useAppDispatch()
const isMulti = fluidType === FluidType.MULTIFLUID
const {
chart: { currentTimeStep, showOfflineData, selectedDate, currentIndex },
global: { fluidStatus, releaseNotes },
modal: { partnersIssueModal, customPopupModal },
} = useAppSelector(state => state.ecolyo)
const dateChartService = new DateChartService()
const [openReleaseNoteModal, setOpenReleaseNoteModal] = useState<boolean>(
releaseNotes.show
)
const [headerHeight, setHeaderHeight] = useState<number>(0)
const [active, setActive] = useState<boolean>(false)
const [openExpiredConsentModal, setOpenExpiredConsentModal] =
useState<boolean>(true)
const [consentExpiredFluids, setConsentExpiredFluids] = useState<FluidType[]>(
[]
)
const updateKey =
fluidType !== FluidType.MULTIFLUID && fluidStatus[fluidType].lastDataDate
? `${fluidStatus[fluidType].lastDataDate!.toLocaleString()} + ${
fluidStatus[fluidType].status + fluidType
}`
: ''
const lastDataDateKey =
fluidType !== FluidType.MULTIFLUID && fluidStatus[fluidType].lastDataDate
? `${fluidStatus[fluidType].lastDataDate!.toLocaleString() + fluidType}`
: ''
const handleCloseReleaseNoteModal = useCallback(() => {
setOpenReleaseNoteModal(false)
dispatch(
showReleaseNotes({
show: false,
notes: releaseNotes.notes,
redirectLink: releaseNotes.redirectLink,
})
)
if (releaseNotes.redirectLink) {
navigate(releaseNotes.redirectLink)
}
}, [dispatch, navigate, releaseNotes.notes, releaseNotes.redirectLink])
const getPartnerKey = (fluidType: FluidType): 'enedis' | 'egl' | 'grdf' => {
switch (fluidType) {
case FluidType.ELECTRICITY:
return 'enedis'
case FluidType.WATER:
return 'egl'
case FluidType.GAS:
return 'grdf'
default:
throw new Error('unknown fluidtype')
}
}
const handleClosePartnerIssueModal = useCallback(
async (fluidType: FluidType) => {
const profileService = new ProfileService(client)
const profileValues = await profileService.getProfile()
if (profileValues) {
const updatedProfile = await profileService.updateProfile({
partnersIssueSeenDate: {
...profileValues.partnersIssueSeenDate,
[getPartnerKey(fluidType)]: getTodayDate(),
},
})
if (updatedProfile) {
dispatch(
openPartnersModal({
...partnersIssueModal,
[getPartnerKey(fluidType)]: false,
})
)
}
}
},
[client, dispatch, partnersIssueModal]
)
const handleCloseCustomPopupModal = async () => {
const profileService = new ProfileService(client)
const updatedProfile = await profileService.updateProfile({
customPopupDate: getTodayDate(),
})
if (updatedProfile) {
dispatch(
setCustomPopup({
...customPopupModal,
popupEnabled: false,
})
)
}
}
/** Handle time change */
useEffect(() => {
if (
fluidType !== FluidType.ELECTRICITY &&
currentTimeStep == TimeStep.HALF_AN_HOUR
) {
dispatch(setCurrentTimeStep(TimeStep.WEEK))
}
}, [dispatch, fluidType, currentTimeStep])
/**
* If fluid is not connected, display Connect components
* If fluid is connected, dispatch FluidChart
*/
useEffect(() => {
const isFluidConnected = isKonnectorActive(fluidStatus, fluidType)
dispatch(setShowOfflineData(isFluidConnected))
}, [dispatch, fluidStatus, fluidType])
useEffect(() => {
let subscribed = true
const expiredConsents: FluidType[] = []
// Check if some fluids have expired consent error
for (const fluid of fluidStatus) {
const error = fluid.connection.triggerState?.last_error
if (error && getKonnectorUpdateError(error) === 'error_update_oauth') {
expiredConsents.push(fluid.fluidType)
}
}
if (subscribed) setConsentExpiredFluids(expiredConsents)
return () => {
subscribed = false
}
}, [fluidStatus])
const disablePrev =
selectedDate <
DateTime.local(0, 1, 1).setZone('utc', {
keepLocalTime: true,
}) && !isKonnectorActive(fluidStatus, FluidType.MULTIFLUID)
const getIncrement = (next: boolean) =>
next
? dateChartService.defineIncrementForNextIndex(
currentTimeStep,
selectedDate,
currentIndex
)
: dateChartService.defineIncrementForPreviousIndex(
currentTimeStep,
selectedDate,
currentIndex
)
const handleClickMove = (next: boolean) => {
const increment = getIncrement(next)
const updatedDate = dateChartService.incrementDate(
currentTimeStep,
selectedDate,
increment
)
const updatedIndex = dateChartService.defineDateIndex(
currentTimeStep,
updatedDate
)
dispatch(setSelectedDate(updatedDate))
dispatch(setCurrentIndex(updatedIndex))
}
return (
<>
<CozyBar titleKey="common.title_consumption" />
<Header
setHeaderHeight={setHeaderHeight}
desktopTitleKey="common.title_consumption"
>
<DateNavigator
disableNext={isLastDateReached(selectedDate, currentTimeStep)}
disablePrev={disablePrev}
handleNextDate={() => handleClickMove(true)}
handlePrevDate={() => handleClickMove(false)}
navigatorDate={selectedDate}
timeStep={currentTimeStep}
/>
</Header>
<Content heightOffset={headerHeight}>
<FluidButtons activeFluid={fluidType} key={updateKey} />
{openReleaseNoteModal && (
<ReleaseNotesModal
open={openReleaseNoteModal}
handleCloseClick={handleCloseReleaseNoteModal}
/>
)}
{showOfflineData && (
<>
<FluidChart
fluidType={fluidType}
setActive={setActive}
key={lastDataDateKey}
/>
<ConsumptionDetails fluidType={fluidType} />
{!isMulti && (
<KonnectorViewerCard
fluidType={fluidType}
isDisconnected={false}
showOfflineData={true}
setActive={setActive}
active={active}
key={fluidType}
/>
)}
</>
)}
{!showOfflineData && (
<div className="konnector-section">
{isMulti ? (
<KonnectorViewerList />
) : (
<KonnectorViewerCard
fluidType={fluidType}
isDisconnected={true}
showOfflineData={false}
setActive={setActive}
active={active}
/>
)}
</div>
)}
</Content>
{/* Partner issue modals for individual fluids */}
{fluidStatus
.filter(fluid => fluid.maintenance)
.filter(fluid => fluid.fluidType === fluidType)
.map(issuedFluid => (
<PartnerIssueModal
key={issuedFluid.fluidType}
issuedFluid={issuedFluid.fluidType}
open={partnersIssueModal[getPartnerKey(issuedFluid.fluidType)]}
handleCloseClick={handleClosePartnerIssueModal}
/>
))}
<CustomPopupModal
customPopup={customPopupModal}
handleCloseClick={handleCloseCustomPopupModal}
/>
{Boolean(consentExpiredFluids.length) &&
consentExpiredFluids.map(fluid => {
return (
<ExpiredConsentModal
key={fluid}
open={openExpiredConsentModal}
handleCloseClick={() => setOpenExpiredConsentModal(false)}
fluidType={fluid}
toggleModal={() => setOpenExpiredConsentModal(prev => !prev)}
/>
)
})}
</>
)
}
export default ConsumptionView