Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/factory/llle_project/ecolyo
1 result
Show changes
Commits on Source (6)
Showing
with 254 additions and 184 deletions
module.exports = {
plugins: [
'@typescript-eslint',
'react',
'react-hooks',
'jest',
'jsx-a11y',
'@eslint-react/eslint-plugin',
],
extends: [
'eslint:recommended',
'plugin:react/recommended', // Uses the recommended rules from @eslint-plugin-react
......@@ -15,6 +23,8 @@ module.exports = {
'plugin:@typescript-eslint/recommended',
// Stylistic rule configurations, for consistent and predictable syntax usage
'plugin:@typescript-eslint/stylistic-type-checked',
// Eslint React plugin
'plugin:@eslint-react/recommended-legacy',
],
files: ['**/*.{ts,tsx}'],
parserOptions: {
......@@ -61,6 +71,13 @@ module.exports = {
// Note: you must disable the base rule as it can report incorrect errors
'require-await': 'off',
'@typescript-eslint/require-await': 'error',
// disable recommandations
'@eslint-react/hooks-extra/no-redundant-custom-hook': 0, // great rule but should not be run in tests files
'@eslint-react/hooks-extra/no-direct-set-state-in-use-effect': 0, // to enable in another MR will have a lot of impact
'@eslint-react/dom/no-dangerously-set-innerhtml': 0, // used for for injecting html tags
'@eslint-react/no-array-index-key': 0,
'@eslint-react/no-unused-class-component-members': 0, // disabled for ".d.ts" files
},
},
{
......@@ -71,7 +88,6 @@ module.exports = {
},
},
],
plugins: ['@typescript-eslint', 'react', 'react-hooks', 'jest', 'jsx-a11y'],
parser: '@typescript-eslint/parser', // Specifies the ESLint parser
parserOptions: {
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
......
......@@ -46,6 +46,7 @@ const ChallengeCard = ({
return (
<button
type="button"
aria-label={t('challenge.card.goto')}
onClick={() => moveToSlide(index)}
className={indexSlider === index ? 'slide active' : 'slide inactive'}
......
......@@ -6,6 +6,7 @@ exports[`ChallengeCard component should be rendered correctly 1`] = `
aria-label="challenge.card.goto"
class="slide active"
style="min-width: 200px; max-width: 200px; min-height: 400px; background: none; padding: 0px;"
type="button"
>
<div
class="cardContent cardDone"
......
......@@ -68,7 +68,7 @@ describe('ExpiredConsentModal component', () => {
await act(async () => {
await userEvent.click(screen.getByText('consent_outdated.yes'))
})
expect(mockAppDispatch).toHaveBeenCalledTimes(2)
expect(mockAppDispatch).toHaveBeenCalledTimes(1)
expect(mockedNavigate).toHaveBeenCalledTimes(1)
})
it('should click on close modal', async () => {
......
......@@ -7,14 +7,10 @@ import StyledIcon from 'components/CommonKit/Icon/StyledIcon'
import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
import { FluidType } from 'enums'
import { AccountSgeData } from 'models'
import React, { useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import {
setShouldRefreshConsent,
updateSgeStore,
} from 'store/global/global.slice'
import { useAppDispatch, useAppSelector } from 'store/hooks'
import { setShouldRefreshConsent } from 'store/global/global.slice'
import { useAppDispatch } from 'store/hooks'
import { getFluidName } from 'utils/utils'
import './expiredConsentModal.scss'
......@@ -34,26 +30,8 @@ const ExpiredConsentModal = ({
const { t } = useI18n()
const navigate = useNavigate()
const dispatch = useAppDispatch()
const { fluidStatus } = useAppSelector(state => state.ecolyo.global)
const launchUpdateConsent = useCallback(() => {
if (fluidType === FluidType.ELECTRICITY) {
const accountData = fluidStatus[FluidType.ELECTRICITY].connection.account
?.auth as AccountSgeData
// store the previous account data since the onDelete will remove account from DB
dispatch(
updateSgeStore({
currentStep: 0,
firstName: accountData.firstname,
lastName: accountData.lastname,
pdl: parseInt(accountData.pointId),
address: accountData.address,
zipCode: parseInt(accountData.postalCode),
city: accountData.city,
dataConsent: true,
pdlConfirm: true,
shouldLaunchAccount: true,
})
)
dispatch(setShouldRefreshConsent(true))
toggleModal()
navigate(`/consumption/${FluidType[fluidType].toLocaleLowerCase()}`)
......@@ -62,7 +40,7 @@ const ExpiredConsentModal = ({
toggleModal()
navigate(`/connect/${FluidType[fluidType].toLocaleLowerCase()}`)
}
}, [dispatch, fluidStatus, fluidType, navigate, toggleModal])
}, [dispatch, fluidType, navigate, toggleModal])
return (
<Dialog
......
......@@ -5,12 +5,15 @@ import CozyBar from 'components/Header/CozyBar'
import Header from 'components/Header/Header'
import useKonnectorAuth from 'components/Hooks/useKonnectorAuth'
import useUserInstanceSettings from 'components/Hooks/useUserInstanceSettings'
import { useClient } from 'cozy-client'
import { FORM_DOCTYPE } from 'doctypes'
import { FluidType } from 'enums'
import { AccountGRDFData } from 'models'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useAppSelector } from 'store/hooks'
import '../connection.scss'
import { createInitialGrdfState, useFormData } from '../useForm'
import StepConsent from './StepConsent'
import { StepIdentity } from './StepIdentity'
......@@ -18,11 +21,14 @@ export enum GrdfStep {
Identity,
Consent,
}
/**
* http://ecolyo.cozy.tools:8080/#/connect/gas
*/
export const GrdfConnectView = () => {
const client = useClient()
const navigate = useNavigate()
const { formData } = useFormData()
const { instanceSettings } = useUserInstanceSettings()
const { fluidStatus } = useAppSelector(state => state.ecolyo.global)
const currentFluidStatus = fluidStatus[FluidType.GAS]
......@@ -30,13 +36,9 @@ export const GrdfConnectView = () => {
const [launchConnection, setLaunchConnection] = useState(false)
const [currentStep, setCurrentStep] = useState<GrdfStep>(GrdfStep.Identity)
const [formData, setFormData] = useState<AccountGRDFData>({
lastname: '',
firstname: '',
email: '',
postalCode: '',
pce: '',
})
const [grdfState, setGrdfState] = useState<AccountGRDFData>(
createInitialGrdfState()
)
const [formConsent, setFormConsent] = useState({
dataConsent: false,
pceConfirm: false,
......@@ -48,23 +50,27 @@ export const GrdfConnectView = () => {
}
const [connect, update] = useKonnectorAuth(FluidType.GAS, {
grdfAuthData: formData,
grdfAuthData: grdfState,
})
useEffect(() => {
setFormData(prev => ({ ...prev, email: instanceSettings.email ?? '' }))
}, [instanceSettings])
setGrdfState(prev => ({
...prev,
...createInitialGrdfState(formData),
email: instanceSettings.email ?? '',
}))
}, [instanceSettings, formData])
useEffect(() => {
async function launchConnect() {
if (launchConnection) {
setLaunchConnection(false)
if (!account) {
await connect()
} else {
await update()
}
setLaunchConnection(false)
navigate('/consumption/gas')
}
}
......@@ -74,11 +80,11 @@ export const GrdfConnectView = () => {
const isNextValid = useCallback(() => {
if (currentStep === GrdfStep.Identity) {
return (
formData.firstname !== '' &&
formData.lastname !== '' &&
formData.postalCode !== '' &&
formData.email.includes('@') &&
formData.pce.length === 14
grdfState.firstname !== '' &&
grdfState.lastname !== '' &&
grdfState.postalCode !== '' &&
grdfState.email.includes('@') &&
grdfState.pce.length === 14
)
} else if (currentStep === GrdfStep.Consent) {
return formConsent.dataConsent && formConsent.pceConfirm
......@@ -88,23 +94,40 @@ export const GrdfConnectView = () => {
currentStep,
formConsent.dataConsent,
formConsent.pceConfirm,
formData.email,
formData.firstname,
formData.lastname,
formData.pce,
formData.postalCode,
grdfState.email,
grdfState.firstname,
grdfState.lastname,
grdfState.pce,
grdfState.postalCode,
])
const handleNext = useCallback(() => {
if (!isNextValid()) return
if (currentStep < GrdfStep.Consent) {
setCurrentStep(prev => prev + 1)
client.save({
...formData,
_type: FORM_DOCTYPE,
firstName: grdfState.firstname,
lastName: grdfState.lastname,
pce: grdfState.pce,
zipCode: grdfState.postalCode,
})
}
if (currentStep === GrdfStep.Consent) {
setLaunchConnection(true)
}
focusMainContent()
}, [currentStep, isNextValid])
}, [
client,
currentStep,
formData,
grdfState.firstname,
grdfState.lastname,
grdfState.pce,
grdfState.postalCode,
isNextValid,
])
const handlePrev = () => {
setCurrentStep(prev => prev - 1)
......@@ -113,7 +136,7 @@ export const GrdfConnectView = () => {
const renderStep = (step: GrdfStep) => {
if (step === GrdfStep.Identity) {
return <StepIdentity formData={formData} setFormData={setFormData} />
return <StepIdentity formData={grdfState} setFormData={setGrdfState} />
} else {
return (
<StepConsent
......
import { render, screen } from '@testing-library/react'
import { SgeStore } from 'models'
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter } from 'react-router-dom'
......@@ -18,6 +19,23 @@ jest.mock('components/Hooks/useKonnectorAuth', () =>
jest.fn(() => [mockConnect, mockUpdate])
)
// mock sge state with shouldLaunchAccount set to true
jest.mock('components/Connection/useForm', () => ({
useFormData: jest.fn().mockReturnValue({ formData: {} }),
createInitialSgeState: jest.fn<SgeStore, []>().mockReturnValue({
address: '',
lastName: '',
firstName: '',
pdl: 0,
zipCode: 0,
city: '',
currentStep: 0,
dataConsent: false,
shouldLaunchAccount: true,
pdlConfirm: false,
}),
}))
describe('SgeConnectView component', () => {
beforeEach(() => {
jest.clearAllMocks()
......@@ -57,16 +75,6 @@ describe('SgeConnectView component', () => {
describe('should test methods from useKonnectorAuth hook', () => {
it('should launch account and trigger creation process', () => {
const store = createMockEcolyoStore({
global: {
...mockGlobalState,
sgeConnect: {
...mockGlobalState.sgeConnect,
shouldLaunchAccount: true,
},
},
})
render(
<Provider store={store}>
<SgeConnectView />
......@@ -79,10 +87,6 @@ describe('SgeConnectView component', () => {
global: {
...mockGlobalState,
fluidStatus: [SgeStatusWithAccount],
sgeConnect: {
...mockGlobalState.sgeConnect,
shouldLaunchAccount: true,
},
},
})
render(
......
......@@ -4,16 +4,16 @@ import Content from 'components/Content/Content'
import CozyBar from 'components/Header/CozyBar'
import Header from 'components/Header/Header'
import useKonnectorAuth from 'components/Hooks/useKonnectorAuth'
import { useClient } from 'cozy-client'
import { FORM_DOCTYPE } from 'doctypes'
import { FluidType, SgeStep } from 'enums'
import { SgeStore } from 'models'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
setShouldRefreshConsent,
updateSgeStore,
} from 'store/global/global.slice'
import { setShouldRefreshConsent } from 'store/global/global.slice'
import { useAppDispatch, useAppSelector } from 'store/hooks'
import '../connection.scss'
import { createInitialSgeState, useFormData } from '../useForm'
import StepAddress from './StepAddress'
import StepConsent from './StepConsent'
import StepIdentityAndPdl from './StepIdentityAndPdl'
......@@ -32,11 +32,12 @@ export type SGEKeysForm =
* http://ecolyo.cozy.tools:8080/#/connect/electricity
*/
const SgeConnectView = () => {
const client = useClient()
const navigate = useNavigate()
const dispatch = useAppDispatch()
const { sgeConnect } = useAppSelector(state => state.ecolyo.global)
const { formData } = useFormData()
const [isLoading, setIsLoading] = useState(false)
const [currentSgeState, setCurrentSgeState] = useState<SgeStore>(sgeConnect)
const [sgeState, setSgeState] = useState<SgeStore>(createInitialSgeState())
const [currentStep, setCurrentStep] = useState<SgeStep>(
SgeStep.IdentityAndPDL
)
......@@ -50,13 +51,25 @@ const SgeConnectView = () => {
}
const [connect, update] = useKonnectorAuth(FluidType.ELECTRICITY, {
sgeAuthData: sgeConnect,
sgeAuthData: sgeState,
})
useEffect(
function applyFormData() {
if (formData) {
setSgeState(prevState => ({
...prevState,
...createInitialSgeState(formData),
}))
}
},
[formData]
)
useEffect(() => {
async function launchConnect() {
if (sgeConnect.shouldLaunchAccount) {
dispatch(updateSgeStore({ ...sgeConnect, shouldLaunchAccount: false }))
if (sgeState.shouldLaunchAccount) {
setSgeState({ ...sgeState, shouldLaunchAccount: false })
dispatch(setShouldRefreshConsent(false))
if (!account) {
await connect()
......@@ -67,66 +80,74 @@ const SgeConnectView = () => {
}
}
launchConnect()
}, [account, connect, dispatch, navigate, sgeConnect, update])
}, [account, connect, sgeState, dispatch, navigate, update])
const isNextValid = useCallback(() => {
switch (currentStep) {
case SgeStep.IdentityAndPDL:
return (
currentSgeState.firstName !== '' &&
currentSgeState.lastName !== '' &&
currentSgeState.pdl !== null &&
currentSgeState.pdl.toString().length === 14
sgeState.firstName !== '' &&
sgeState.lastName !== '' &&
sgeState.pdl !== null &&
sgeState.pdl.toString().length === 14
)
case SgeStep.Address:
return (
currentSgeState.address !== '' &&
currentSgeState.city !== '' &&
currentSgeState.zipCode !== null &&
currentSgeState.zipCode.toString().length === 5
sgeState.address !== '' &&
sgeState.city !== '' &&
sgeState.zipCode !== null &&
sgeState.zipCode.toString().length === 5
)
case SgeStep.Consent:
return currentSgeState.dataConsent && currentSgeState.pdlConfirm
return sgeState.dataConsent && sgeState.pdlConfirm
default:
return false
}
}, [
currentSgeState.address,
currentSgeState.city,
currentSgeState.dataConsent,
currentSgeState.firstName,
currentSgeState.lastName,
currentSgeState.pdl,
currentSgeState.pdlConfirm,
currentSgeState.zipCode,
sgeState.address,
sgeState.city,
sgeState.dataConsent,
sgeState.firstName,
sgeState.lastName,
sgeState.pdl,
sgeState.pdlConfirm,
sgeState.zipCode,
currentStep,
])
const handleNext = useCallback(() => {
if (currentStep < SgeStep.Consent) {
setCurrentStep(prev => prev + 1)
dispatch(updateSgeStore(currentSgeState))
client.save({
...formData,
_type: FORM_DOCTYPE,
firstName: sgeState.firstName,
lastName: sgeState.lastName,
pdl: sgeState.pdl,
address: sgeState.address,
city: sgeState.city,
zipCode: sgeState.zipCode,
})
}
if (currentStep === SgeStep.Consent && !isLoading) {
setIsLoading(true)
const updatedState = {
...currentSgeState,
city: currentSgeState.city.trim(),
...sgeState,
city: sgeState.city.trim(),
shouldLaunchAccount: true,
}
setCurrentSgeState(updatedState)
dispatch(updateSgeStore(updatedState))
setSgeState(updatedState)
}
focusMainContent()
}, [currentStep, isLoading, dispatch, currentSgeState])
}, [currentStep, isLoading, client, formData, sgeState])
const handlePrev = useCallback(() => {
if (currentStep !== SgeStep.IdentityAndPDL) {
setCurrentStep(prev => prev - 1)
}
dispatch(updateSgeStore(currentSgeState))
focusMainContent()
}, [currentSgeState, currentStep, dispatch])
}, [currentStep])
const onChange = useCallback(
(
......@@ -137,25 +158,23 @@ const SgeConnectView = () => {
if (maxLength && value.toString().length > maxLength) return
const updatedState = {
...currentSgeState,
...sgeState,
[key]: value,
}
setCurrentSgeState(updatedState)
setSgeState(updatedState)
},
[currentSgeState]
[sgeState]
)
const renderStep = (step: SgeStep) => {
switch (step) {
case SgeStep.Address:
return <StepAddress sgeState={currentSgeState} onChange={onChange} />
return <StepAddress sgeState={sgeState} onChange={onChange} />
case SgeStep.Consent:
return <StepConsent sgeState={currentSgeState} onChange={onChange} />
return <StepConsent sgeState={sgeState} onChange={onChange} />
case SgeStep.IdentityAndPDL:
default:
return (
<StepIdentityAndPdl sgeState={currentSgeState} onChange={onChange} />
)
return <StepIdentityAndPdl sgeState={sgeState} onChange={onChange} />
}
}
......
import { act, render, screen } from '@testing-library/react'
import { userEvent } from '@testing-library/user-event'
import React from 'react'
import { mockGlobalState } from 'tests/__mocks__/store'
import { mockSgeState } from 'tests/__mocks__/forms.mock'
import StepAddress from './StepAddress'
const mockHandleChange = jest.fn()
......@@ -9,10 +9,7 @@ const mockHandleChange = jest.fn()
describe('StepAddress component', () => {
it('should be rendered correctly', () => {
const { container } = render(
<StepAddress
sgeState={mockGlobalState.sgeConnect}
onChange={mockHandleChange}
/>
<StepAddress sgeState={mockSgeState} onChange={mockHandleChange} />
)
expect(container).toMatchSnapshot()
})
......@@ -20,10 +17,7 @@ describe('StepAddress component', () => {
describe('should change inputs', () => {
beforeEach(() => {
render(
<StepAddress
sgeState={mockGlobalState.sgeConnect}
onChange={mockHandleChange}
/>
<StepAddress sgeState={mockSgeState} onChange={mockHandleChange} />
)
})
it('should change address value', async () => {
......@@ -40,9 +34,9 @@ describe('StepAddress component', () => {
name: 'auth.enedissgegrandlyon.zipCode',
})
await act(async () => {
await userEvent.type(input, '0')
await userEvent.type(input, '1')
})
expect(mockHandleChange).toHaveBeenCalledWith('zipCode', '0', 5)
expect(mockHandleChange).toHaveBeenCalledWith('zipCode', '1', 5)
})
it('should change city value', async () => {
......@@ -58,7 +52,7 @@ describe('StepAddress component', () => {
it('should have an existing zipCode value', () => {
render(
<StepAddress
sgeState={{ ...mockGlobalState.sgeConnect, zipCode: 69200 }}
sgeState={{ ...mockSgeState, zipCode: 69200 }}
onChange={mockHandleChange}
/>
)
......
import { render, screen } from '@testing-library/react'
import { userEvent } from '@testing-library/user-event'
import React from 'react'
import { mockGlobalState } from 'tests/__mocks__/store'
import { mockSgeState } from 'tests/__mocks__/forms.mock'
import StepConsent from './StepConsent'
const mockHandleChange = jest.fn()
......@@ -9,21 +9,13 @@ const mockHandleChange = jest.fn()
describe('StepConsent component', () => {
it('should be rendered correctly', () => {
const { container } = render(
<StepConsent
sgeState={mockGlobalState.sgeConnect}
onChange={mockHandleChange}
/>
<StepConsent sgeState={mockSgeState} onChange={mockHandleChange} />
)
expect(container).toMatchSnapshot()
})
it('should change dataConsent and pdlConfirm value', async () => {
render(
<StepConsent
sgeState={mockGlobalState.sgeConnect}
onChange={mockHandleChange}
/>
)
render(<StepConsent sgeState={mockSgeState} onChange={mockHandleChange} />)
const consentCheckbox = screen.getByLabelText(
'auth.enedissgegrandlyon.consentCheck1'
)
......
import { act, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import React from 'react'
import { mockGlobalState } from 'tests/__mocks__/store'
import { mockSgeState } from 'tests/__mocks__/forms.mock'
import StepIdentityAndPdl from './StepIdentityAndPdl'
const mockHandleChange = jest.fn()
......@@ -9,20 +9,14 @@ const mockHandleChange = jest.fn()
describe('StepIdentityAndPdl component', () => {
it('should be rendered correctly', () => {
const { container } = render(
<StepIdentityAndPdl
sgeState={mockGlobalState.sgeConnect}
onChange={mockHandleChange}
/>
<StepIdentityAndPdl sgeState={mockSgeState} onChange={mockHandleChange} />
)
expect(container).toMatchSnapshot()
})
it('should be able to change fields', async () => {
render(
<StepIdentityAndPdl
sgeState={mockGlobalState.sgeConnect}
onChange={mockHandleChange}
/>
<StepIdentityAndPdl sgeState={mockSgeState} onChange={mockHandleChange} />
)
const firstNameInput = screen.getByRole('textbox', {
name: 'auth.enedissgegrandlyon.firstName',
......@@ -51,10 +45,7 @@ describe('StepIdentityAndPdl component', () => {
it('should open hint modal', async () => {
render(
<StepIdentityAndPdl
sgeState={mockGlobalState.sgeConnect}
onChange={mockHandleChange}
/>
<StepIdentityAndPdl sgeState={mockSgeState} onChange={mockHandleChange} />
)
await act(async () => {
await userEvent.click(
......@@ -68,7 +59,7 @@ describe('StepIdentityAndPdl component', () => {
render(
<StepIdentityAndPdl
sgeState={{
...mockGlobalState.sgeConnect,
...mockSgeState,
pdl: 11111111111111,
firstName: 'Zack',
lastName: 'Ichan',
......
......@@ -58,8 +58,8 @@ exports[`StepAddress component should be rendered correctly 1`] = `
class="MuiFormControl-root MuiTextField-root"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled Mui-required Mui-required"
data-shrink="true"
for="zipCode"
id="zipCode-label"
>
......@@ -81,14 +81,14 @@ exports[`StepAddress component should be rendered correctly 1`] = `
id="zipCode"
required=""
type="number"
value=""
value="0"
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-1 MuiOutlinedInput-notchedOutline"
>
<legend
class="PrivateNotchedOutline-legendLabelled-3"
class="PrivateNotchedOutline-legendLabelled-3 PrivateNotchedOutline-legendNotched-4"
>
<span>
auth.enedissgegrandlyon.zipCode
......
import { Q, QueryDefinition, useQuery } from 'cozy-client'
import { QueryOptions } from 'cozy-client/types/types'
import { FORM_DOCTYPE } from 'doctypes'
import { SgeStep } from 'enums'
import { AccountGRDFData, SgeStore } from 'models'
export type QueryParams = (arg?: any) => {
definition: QueryDefinition
options: QueryOptions
}
interface FormData {
firstName: string
lastName: string
pdl: string
pce: string
zipCode: string
city: string
address: string
}
const getFormData: QueryParams = () => ({
definition: Q(FORM_DOCTYPE),
options: { as: 'form' },
})
/** Returns the form data from the form doctype */
export const useFormData = () => {
const { definition, options } = getFormData()
// eslint-disable-next-line prefer-const
let { data, lastError, fetchStatus } = useQuery(definition, options)
if (data === null) {
data = []
}
const formData = data as [FormData]
return {
formData: formData[0],
isFetching: fetchStatus === 'loading',
lastError,
}
}
export const createInitialSgeState = (formData?: FormData): SgeStore => ({
address: formData?.address ?? '',
lastName: formData?.lastName ?? '',
firstName: formData?.firstName ?? '',
pdl: formData?.pdl ? parseInt(formData.pdl) : null,
zipCode: formData?.zipCode ? parseInt(formData.zipCode) : null,
city: formData?.city ?? '',
currentStep: SgeStep.Address,
dataConsent: false,
pdlConfirm: false,
shouldLaunchAccount: false,
})
export const createInitialGrdfState = (
formData?: FormData
): AccountGRDFData => ({
lastname: formData?.lastName ?? '',
firstname: formData?.firstName ?? '',
pce: formData?.pce ?? '',
postalCode: formData?.zipCode ?? '',
email: '',
})
......@@ -51,7 +51,7 @@ const EcogestureTabsView = () => {
const { profile, profileEcogesture, profileType } = useAppSelector(
state => state.ecolyo
)
const [tabValue, setTabValue] = useState<EcogestureTab>(
const [tabValue, setTabValue] = useState<EcogestureTab>(() =>
tab ? parseInt(tab) : EcogestureTab.OBJECTIVE
)
const [isLoading, setIsLoading] = useState<boolean>(true)
......
......@@ -6,7 +6,7 @@ import { useClient } from 'cozy-client'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
import { FluidType, KonnectorUpdate } from 'enums'
import { DateTime } from 'luxon'
import { AccountSgeData, FluidConnection, FluidStatus } from 'models'
import { FluidConnection, FluidStatus } from 'models'
import React, { useCallback, useEffect, useState } from 'react'
import AccountService from 'services/account.service'
import DateChartService from 'services/dateChart.service'
......@@ -14,7 +14,6 @@ import TriggerService from 'services/triggers.service'
import {
setShouldRefreshConsent,
updateFluidConnection,
updateSgeStore,
} from 'store/global/global.slice'
import { useAppDispatch, useAppSelector } from 'store/hooks'
import { getKonnectorUpdateError } from 'utils/utils'
......@@ -108,33 +107,11 @@ const ConnectionResult = ({
const handleRefreshConsent = useCallback(() => {
if (fluidType == FluidType.ELECTRICITY) {
const accountData = currentFluidStatus.connection.account
?.auth as AccountSgeData
// store the previous account data since the onDelete will remove account from DB
dispatch(
updateSgeStore({
currentStep: 0,
firstName: accountData.firstname,
lastName: accountData.lastname,
pdl: parseInt(accountData.pointId),
address: accountData.address,
zipCode: parseInt(accountData.postalCode),
city: accountData.city,
dataConsent: true,
pdlConfirm: true,
shouldLaunchAccount: true,
})
)
dispatch(setShouldRefreshConsent(true))
} else {
deleteAccountsAndTriggers()
}
}, [
fluidType,
currentFluidStatus.connection.account?.auth,
dispatch,
deleteAccountsAndTriggers,
])
}, [fluidType, dispatch, deleteAccountsAndTriggers])
useEffect(() => {
if (currentFluidStatus.connection.triggerState?.last_success) {
......
......@@ -65,11 +65,11 @@ const ExportLoadingModal = ({
fluidType: FluidType
): Promise<ExportDataRow> => {
const dataRow: ExportDataRow = {}
const fluidName = getFluidName(fluidType)
const FLUIDNAME = getFluidName(fluidType).toUpperCase()
dataRow[t('export.month')] = formatTwoDigits(dataload.date.month)
dataRow[t('export.year')] = dataload.date.year
dataRow[
`${t('export.consumption')} (${t('FLUID.' + fluidName + '.UNIT')})`
`${t('export.consumption')} (${t('FLUID.' + FLUIDNAME + '.UNIT')})`
] = dataload.value
if (fluidType === FluidType.ELECTRICITY) {
const emas = new EnedisMonthlyAnalysisDataService(client)
......@@ -137,6 +137,7 @@ const ExportLoadingModal = ({
useEffect(() => {
let subscribed = true
const date = new Date()
let timeout: ReturnType<typeof setTimeout>
const exportData = async (): Promise<void> => {
try {
......@@ -147,14 +148,15 @@ const ExportLoadingModal = ({
exportDataSheets.push(exportDataFluid)
}
}
await new Promise(r => setTimeout(r, 2000))
if (subscribed) {
exportToXlsx(
exportDataSheets,
'ecolyo_data_' + date.toLocaleDateString()
)
handleDone()
}
timeout = setTimeout(() => {
if (subscribed) {
exportToXlsx(
exportDataSheets,
'ecolyo_data_' + date.toLocaleDateString()
)
handleDone()
}
}, 2000)
} catch (e) {
Sentry.captureException(e)
handleDone(e)
......@@ -166,6 +168,7 @@ const ExportLoadingModal = ({
}
return () => {
subscribed = false
clearTimeout(timeout)
}
}, [getExportDataSheet, handleDone, open, selectedFluids])
......
......@@ -15,6 +15,7 @@ const MatomoOptOut = () => {
{t('matomo.matomo_title')}
</div>
<iframe
sandbox="allow-popups allow-scripts"
title="opt-out"
style={{ height: '250px' }}
className="matomo-content"
......
......@@ -15,6 +15,7 @@ exports[`MatomoOptOut component should be rendered correctly 1`] = `
</div>
<iframe
class="matomo-content"
sandbox="allow-popups allow-scripts"
src="http://localhost:9800/index.php?module=CoreAdminHome&action=optOut&language=fr&backgroundColor=121212&fontColor=e0e0e0&fontSize=&fontFamily=sans-serif"
style="height: 250px;"
title="opt-out"
......
......@@ -378,6 +378,7 @@ exports[`OptionsView component should be rendered correctly 1`] = `
</div>
<iframe
class="matomo-content"
sandbox="allow-popups allow-scripts"
src="http://localhost:9800/index.php?module=CoreAdminHome&action=optOut&language=fr&backgroundColor=121212&fontColor=e0e0e0&fontSize=&fontFamily=sans-serif"
style="height: 250px;"
title="opt-out"
......