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
Select Git revision

Target

Select target project
  • web-et-numerique/factory/llle_project/ecolyo
1 result
Select Git revision
Show changes
Commits on Source (6)
Showing
with 245 additions and 39 deletions
......@@ -51,6 +51,10 @@ module.exports = {
// a11y label fix, nesting is enough
'jsx-a11y/label-has-associated-control': 0,
// Note: you must disable the base rule as it can report incorrect errors
'require-await': 'off',
'@typescript-eslint/require-await': 'error',
},
},
{
......
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="11" height="11" rx="5.5" stroke="#1B1C22" />
<path d="M9.5 8.5L4 3" stroke="#1B1C22" stroke-linecap="round" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M4.29445 4.70867C4.2492 4.80317 4.20873 4.90039 4.17333 5H3.33333C3.15 5 3 5.15 3 5.33333C3 5.51667 3.15 5.66667 3.33333 5.66667H4.02C4.00667 5.77667 4 5.88667 4 6C4 6.11333 4.00667 6.22333 4.02 6.33333H3.33333C3.15 6.33333 3 6.48333 3 6.66667C3 6.85 3.15 7 3.33333 7H4.17333C4.58667 8.16333 5.69333 9 7 9C7.46345 9 7.90137 8.89571 8.29333 8.70755L7.65291 8.06712C7.44768 8.13205 7.22878 8.16667 7 8.16667C6.16333 8.16667 5.44 7.69333 5.08 7H6.58579L5.91912 6.33333H4.86C4.84333 6.22333 4.83333 6.11333 4.83333 6C4.83333 5.88667 4.84333 5.77667 4.86 5.66667H5.25245L4.29445 4.70867ZM6.34784 3.93363C6.5538 3.86847 6.77294 3.83333 7 3.83333C7.41667 3.83333 7.80667 3.95333 8.14 4.15667C8.30667 4.26 8.52333 4.24333 8.66333 4.10333C8.85667 3.91 8.81333 3.59333 8.58 3.45C8.12 3.16667 7.57667 3 7 3C6.53657 3 6.0983 3.10524 5.70719 3.29298L6.34784 3.93363Z"
fill="#1B1C22" />
</svg>
\ No newline at end of file
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="11" height="11" rx="5.5" stroke="currentColor" />
<path
d="M7 8.16667C6.16333 8.16667 5.44 7.69333 5.08 7H6.66667C6.85 7 7 6.85 7 6.66667C7 6.48333 6.85 6.33333 6.66667 6.33333H4.86C4.84333 6.22333 4.83333 6.11333 4.83333 6C4.83333 5.88667 4.84333 5.77667 4.86 5.66667H6.66667C6.85 5.66667 7 5.51667 7 5.33333C7 5.15 6.85 5 6.66667 5H5.08C5.44 4.30667 6.16667 3.83333 7 3.83333C7.41667 3.83333 7.80667 3.95333 8.14 4.15667C8.30667 4.26 8.52333 4.24333 8.66333 4.10333C8.85667 3.91 8.81333 3.59333 8.58 3.45C8.12 3.16667 7.57667 3 7 3C5.69333 3 4.58667 3.83667 4.17333 5H3.33333C3.15 5 3 5.15 3 5.33333C3 5.51667 3.15 5.66667 3.33333 5.66667H4.02C4.00667 5.77667 4 5.88667 4 6C4 6.11333 4.00667 6.22333 4.02 6.33333H3.33333C3.15 6.33333 3 6.48333 3 6.66667C3 6.85 3.15 7 3.33333 7H4.17333C4.58667 8.16333 5.69333 9 7 9C7.58 9 8.12 8.83667 8.58 8.55C8.81 8.40667 8.85333 8.08667 8.66 7.89333C8.52 7.75333 8.30333 7.73667 8.13667 7.84333C7.80667 8.05 7.42 8.16667 7 8.16667Z"
fill="currentColor" />
</svg>
\ No newline at end of file
......@@ -16,7 +16,7 @@ jest.mock('services/challenge.service', () => {
describe('ActionDone component', () => {
const store = createMockEcolyoStore()
it('should be rendered correctly', async () => {
it('should be rendered correctly', () => {
const { container } = render(
<Provider store={store}>
<ActionDone currentChallenge={userChallengeData[1]} />
......
......@@ -17,7 +17,7 @@ jest.mock('services/challenge.service', () => {
describe('ActionModal component', () => {
const store = createMockEcolyoStore()
it('should render correctly', async () => {
it('should render correctly', () => {
const { baseElement } = render(
<Provider store={store}>
<ActionModal
......
......@@ -26,7 +26,7 @@ jest.mock(
)
describe('ActionView component', () => {
it('should render match snapshot with "Unstarted" state', async () => {
it('should render match snapshot with "Unstarted" state', () => {
const store = createMockEcolyoStore({
challenge: {
...mockChallengeState,
......@@ -46,7 +46,7 @@ describe('ActionView component', () => {
)
expect(container).toMatchSnapshot()
})
it('should render match snapshot with "onGoing" state', async () => {
it('should render match snapshot with "onGoing" state', () => {
const store = createMockEcolyoStore({
challenge: {
...mockChallengeState,
......@@ -66,7 +66,7 @@ describe('ActionView component', () => {
)
expect(container).toMatchSnapshot()
})
it('should render match snapshot with "Notification" state', async () => {
it('should render match snapshot with "Notification" state', () => {
const store = createMockEcolyoStore({
challenge: {
...mockChallengeState,
......@@ -86,7 +86,7 @@ describe('ActionView component', () => {
)
expect(container).toMatchSnapshot()
})
it('should render match snapshot with default case', async () => {
it('should render match snapshot with default case', () => {
const store = createMockEcolyoStore({
challenge: {
...mockChallengeState,
......
......@@ -12,10 +12,11 @@ import Comparison from './Comparison/Comparison'
import ElecHalfHourMonthlyAnalysis from './ElecHalfHourMonthlyAnalysis/ElecHalfHourMonthlyAnalysis'
import IncompleteDataWarning from './IncompleteDataWarning/IncompleteDataWarning'
import MaxConsumptionCard from './MaxConsumptionCard/MaxConsumptionCard'
import './monthlyanalysis.scss'
import NewsletterReminder from './NewsletterReminder/NewsletterReminder'
import NoAnalysisModal from './NoKonnector/NoAnalysisModal'
import ProfileComparator from './ProfileComparator/ProfileComparator'
import TotalAnalysisChart from './TotalAnalysisChart/TotalAnalysisChart'
import './monthlyanalysis.scss'
interface MonthlyAnalysisProps {
saveLastScrollPosition: () => void
......@@ -28,8 +29,9 @@ const MonthlyAnalysis = ({
}: MonthlyAnalysisProps) => {
const client = useClient()
const {
analysis: { analysisMonth },
analysis: { analysisMonth, haveSeenNewsletterReminder },
global: { fluidStatus },
profile: { sendAnalysisNotification, isAnalysisReminderEnabled },
} = useAppSelector(state => state.ecolyo)
const consumptionService = useMemo(
......@@ -61,6 +63,11 @@ const MonthlyAnalysis = ({
percentageVariation: 0,
})
const displayNewsletterReminder =
!sendAnalysisNotification &&
isAnalysisReminderEnabled &&
!haveSeenNewsletterReminder
useEffect(() => {
let subscribed = true
......@@ -144,6 +151,12 @@ const MonthlyAnalysis = ({
{!isLoadingAnalysis && (
<Fade in={!isLoadingAnalysis}>
<div className="analysis-root">
{displayNewsletterReminder && (
<div className="analysis-content">
<NewsletterReminder />
</div>
)}
{incompleteDataFluids.length !== 0 && (
<div className="analysis-content">
<IncompleteDataWarning
......
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { render } from '@testing-library/react'
import React from 'react'
import { Provider } from 'react-redux'
import { createMockEcolyoStore } from 'tests/__mocks__/store'
import { WaterPricing } from './WaterPricing'
import NewsletterReminder from './NewsletterReminder'
const store = createMockEcolyoStore()
describe('NewsletterReminder', () => {
const store = createMockEcolyoStore()
describe('WaterPricing component', () => {
it('should be rendered correctly', () => {
it('renders component correctly and have correct snapshot', async () => {
const { container } = render(
<Provider store={store}>
<WaterPricing />
<NewsletterReminder />
</Provider>
)
expect(container).toMatchSnapshot()
})
it('should open modal when click on button', async () => {
render(
<Provider store={store}>
<WaterPricing />
</Provider>
)
userEvent.click(screen.getByRole('button'))
expect(await screen.findByRole('dialog')).toBeInTheDocument()
})
})
import { Button } from '@material-ui/core'
import CloseIcon from 'assets/icons/ico/close.svg'
import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
import React from 'react'
import { setHaveSeenNewsletterReminder } from 'store/analysis/analysis.slice'
import { useAppDispatch } from 'store/hooks'
import { updateProfile } from 'store/profile/profile.slice'
import './newsletterReminder.scss'
const NewsletterReminder = () => {
const { t } = useI18n()
const dispatch = useAppDispatch()
return (
<div className="newsletter-reminder">
<StyledIconButton
icon={CloseIcon}
sized={18}
onClick={() => dispatch(setHaveSeenNewsletterReminder(true))}
aria-label={t('analysis.newsletter_reminder.close')}
className="close-button"
/>
<div className="text-container">
<h2 className="title text-20-bold">
{t('analysis.newsletter_reminder.title')}
</h2>
<p className="text-18-normal">
{t('analysis.newsletter_reminder.text')}
</p>
</div>
<div className="buttons">
<Button
className="btnPrimary"
onClick={() =>
dispatch(updateProfile({ sendAnalysisNotification: true }))
}
>
{t('analysis.newsletter_reminder.button')}
</Button>
<Button
classes={{
root: 'btnText',
label: 'text-16-normal stop-show',
}}
size="small"
onClick={() =>
dispatch(updateProfile({ isAnalysisReminderEnabled: false }))
}
>
{t('analysis.newsletter_reminder.stop_showing')}
</Button>
</div>
</div>
)
}
export default NewsletterReminder
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NewsletterReminder renders component correctly and have correct snapshot 1`] = `
<div>
<div
class="newsletter-reminder"
>
<button
aria-label="analysis.newsletter_reminder.close"
class="MuiButtonBase-root MuiIconButton-root close-button"
tabindex="0"
type="button"
>
<span
class="MuiIconButton-label"
>
<svg
aria-hidden="true"
class="styles__icon___23x3R"
height="18"
width="18"
>
<use
xlink:href="#test-file-stub"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</button>
<div
class="text-container"
>
<h2
class="title text-20-bold"
>
analysis.newsletter_reminder.title
</h2>
<p
class="text-18-normal"
>
analysis.newsletter_reminder.text
</p>
</div>
<div
class="buttons"
>
<button
class="MuiButtonBase-root MuiButton-root MuiButton-text btnPrimary"
tabindex="0"
type="button"
>
<span
class="MuiButton-label"
>
analysis.newsletter_reminder.button
</span>
<span
class="MuiTouchRipple-root"
/>
</button>
<button
class="MuiButtonBase-root MuiButton-root btnText MuiButton-text MuiButton-textSizeSmall MuiButton-sizeSmall"
tabindex="0"
type="button"
>
<span
class="MuiButton-label text-16-normal stop-show"
>
analysis.newsletter_reminder.stop_showing
</span>
<span
class="MuiTouchRipple-root"
/>
</button>
</div>
</div>
</div>
`;
@import 'src/styles/base/color';
.newsletter-reminder {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
background: $grey-linear-gradient-background;
border: 1px solid $gold-shadow;
border-radius: 4px;
padding: 24px 16px 12px 16px;
gap: 16px;
.close-button {
position: absolute;
top: 0.5rem;
right: 0.5rem;
padding: 5px 5px;
}
.text-container {
h2 {
color: $gold-shadow;
margin: 0;
padding-inline: 1.5rem;
}
p {
color: $white;
margin: 0;
}
}
.buttons {
display: flex;
flex-direction: column;
gap: 12px;
button.btnPrimary {
max-width: 134px;
}
.stop-show {
color: $soft-grey;
}
}
}
......@@ -11,7 +11,7 @@ describe('AnalysisConsumptionRow component', () => {
const performanceValue = 25
describe('Multifluid row', () => {
it('should be rendered correctly for Multifluid and at least fluid connected', async () => {
it('should be rendered correctly for Multifluid and at least fluid connected', () => {
const { container } = render(
<ProfileComparatorRow
fluidType={FluidType.MULTIFLUID}
......@@ -34,7 +34,7 @@ describe('AnalysisConsumptionRow component', () => {
).toBeFalsy()
})
it('should be rendered correctly for Multifluid and at none fluid connected', async () => {
it('should be rendered correctly for Multifluid and at none fluid connected', () => {
const mockConnected = false
const { container } = render(
<ProfileComparatorRow
......@@ -62,7 +62,7 @@ describe('AnalysisConsumptionRow component', () => {
})
describe('Single fluid row', () => {
it('should be rendered correctly for singleFluid connected for average', async () => {
it('should be rendered correctly for singleFluid connected for average', () => {
const { container } = render(
<ProfileComparatorRow
fluidType={FluidType.ELECTRICITY}
......@@ -90,7 +90,7 @@ describe('AnalysisConsumptionRow component', () => {
).toBeFalsy()
})
it('should be rendered correctly for singleFluid not connected', async () => {
it('should be rendered correctly for singleFluid not connected', () => {
const mockConnected = false
const { container } = render(
<ProfileComparatorRow
......@@ -119,8 +119,8 @@ describe('AnalysisConsumptionRow component', () => {
).toBeTruthy()
})
it('should be rendered correctly for singleFluid with none performance value', async () => {
const mockPerformanceValue: number | null = null
it('should be rendered correctly for singleFluid with none performance value', () => {
const mockPerformanceValue = null
const { container } = render(
<ProfileComparatorRow
fluidType={FluidType.ELECTRICITY}
......@@ -146,7 +146,7 @@ describe('AnalysisConsumptionRow component', () => {
).toBeFalsy()
})
it('should be rendered correctly with unit', async () => {
it('should be rendered correctly with unit', () => {
const mockForecast: MonthlyForecast = {
...mockMonthlyForecastJanuaryTestProfile1,
fluidForecast: [
......
import EuroIcon from 'assets/icons/ico/euro-gold.svg'
import EuroIcon from 'assets/icons/ico/euro-icon.svg'
import classNames from 'classnames'
import StyledIcon from 'components/CommonKit/Icon/StyledIcon'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
......
......@@ -24,7 +24,7 @@ describe('ChallengeCardDone component', () => {
challenge: { currentChallenge: null },
},
})
it('should be rendered correctly', async () => {
it('should be rendered correctly', () => {
const { container } = render(
<Provider store={storeNoCurrentChallenge}>
<ChallengeCardDone userChallenge={userChallengeData[0]} />
......@@ -53,7 +53,7 @@ describe('ChallengeCardDone component', () => {
})
expect(mockUpdateUserChallenge).toHaveBeenCalledTimes(1)
})
it('should not reset challenge if another challenge is on going', async () => {
it('should not reset challenge if another challenge is on going', () => {
mockAppDispatch.mockImplementationOnce(() => mockDispatch)
const store = mockStore({
ecolyo: {
......@@ -72,7 +72,7 @@ describe('ChallengeCardDone component', () => {
expect(mockDispatch).toHaveBeenCalledTimes(0)
expect(mockUpdateUserChallenge).toHaveBeenCalledTimes(0)
})
it('should be primary button is challenge is lost', async () => {
it('should be primary button is challenge is lost', () => {
render(
<Provider store={storeNoCurrentChallenge}>
<ChallengeCardDone userChallenge={userChallengeData[1]} />
......@@ -83,7 +83,7 @@ describe('ChallengeCardDone component', () => {
})
expect(resetBtn).toHaveClass('btnPrimaryNegative')
})
it('should be secondary button is challenge is won', async () => {
it('should be secondary button is challenge is won', () => {
render(
<Provider store={storeNoCurrentChallenge}>
<ChallengeCardDone userChallenge={userChallengeData[0]} />
......
......@@ -32,7 +32,7 @@ const ChallengeCardDone = ({
const isSuccess = userChallenge.success === UserChallengeSuccess.WIN
const goDuel = async () => {
const goDuel = () => {
navigate('/challenges/duel?id=' + userChallenge.id)
}
......
......@@ -7,7 +7,7 @@ import ChallengeCardLast from './ChallengeCardLast'
declare let __SAU_IDEA_DIRECT_LINK__: string
describe('ChallengeCardLast component', () => {
it('should be rendered correctly', async () => {
it('should be rendered correctly', () => {
const { container } = render(<ChallengeCardLast />)
expect(container).toMatchSnapshot()
})
......
......@@ -101,7 +101,7 @@ const ChallengeCardOnGoing = ({
useEffect(() => {
let subscribed = true
async function importIcon() {
function importIcon() {
importIconById(userChallenge.id, 'challenge').then(icon => {
icon ? setChallengeIcon(icon) : setChallengeIcon(defaultChallengeIcon)
})
......@@ -114,7 +114,7 @@ const ChallengeCardOnGoing = ({
useEffect(() => {
let subscribed = true
async function setChallengeResult() {
function setChallengeResult() {
const isChallengeDone = challengeService.isChallengeDone(
userChallenge,
currentDataload
......
......@@ -73,7 +73,7 @@ describe('ChallengeCardUnlocked component', () => {
expect(mockStartUserChallenge).toHaveBeenCalledWith(userChallengeData[0])
})
it('should not be able to launch challenge if another one is active', async () => {
it('should not be able to launch challenge if another one is active', () => {
mockStartUserChallenge.mockResolvedValue(userChallengeData[0])
const store = createMockEcolyoStore({
global: mockGlobalState,
......
......@@ -17,7 +17,7 @@ export const GrdfWaitConsent = () => {
const authData = currentFluidStatus.connection.account
?.auth as AccountGRDFData
const updateKonnector = async () => {
const updateKonnector = () => {
const updatedConnection: FluidConnection = {
...currentFluidStatus.connection,
shouldLaunchKonnector: true,
......