diff --git a/src/components/Options/AnalysisOptions.tsx b/src/components/Options/AnalysisOptions.tsx deleted file mode 100644 index 00c627f4af26c44836f1a1fdfa523136a6b722ea..0000000000000000000000000000000000000000 --- a/src/components/Options/AnalysisOptions.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React from 'react' -import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { useSelector, useDispatch } from 'react-redux' -import { AppStore } from 'store' -import { updateProfile } from 'store/profile/profile.actions' -import './analysisOptions.scss' - -const AnalysisOptions: React.FC = () => { - const { t } = useI18n() - const dispatch = useDispatch() - const profile = useSelector((state: AppStore) => state.ecolyo.profile) - - const updateProfileReport = async (value: boolean) => { - dispatch(updateProfile({ sendReportNotification: value })) - } - - const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { - e.target.value === 'true' - ? updateProfileReport(true) - : updateProfileReport(false) - } - - return ( - <div className="analysis-option-root"> - <div className="analysis-option-content"> - <div className="head text-14-normal-uppercase"> - {t('PROFILE.ANALYSIS.TITLE')} - </div> - <form action="" className="radios"> - <div className="input"> - <input - id="monthly" - name="report" - type="radio" - value="true" - onChange={handleChange} - checked={ - profile && profile.sendReportNotification === true - ? true - : false - } - ></input> - <label htmlFor="monthly"> {t('PROFILE.ANALYSIS.MONTHLY')}</label> - </div> - <div className="input"> - <input - id="never" - name="report" - type="radio" - value="false" - onChange={handleChange} - checked={ - profile && profile.sendReportNotification === false - ? true - : false - } - ></input> - <label htmlFor="never"> {t('PROFILE.ANALYSIS.NEVER')}</label> - </div> - </form> - </div> - </div> - ) -} - -export default AnalysisOptions diff --git a/src/components/Options/OptionsView.tsx b/src/components/Options/OptionsView.tsx index bceb2723f671bf2b8579b96a0339346ae6c53efb..e58f22d61b9a40c3bd04638138f120eeb62afe80 100644 --- a/src/components/Options/OptionsView.tsx +++ b/src/components/Options/OptionsView.tsx @@ -3,7 +3,7 @@ import CozyBar from 'components/Header/CozyBar' import Header from 'components/Header/Header' import Content from 'components/Content/Content' import KonnectorViewerList from 'components/Konnector/KonnectorViewerList' -import AnalysisOptions from 'components/Options/AnalysisOptions' +import ReportOptions from 'components/Options/ReportOptions' import FAQLink from 'components/FAQ/FAQLink' import LegalNoticeLink from 'components/LegalNotice/LegalNoticeLink' import Version from 'components/Version/Version' @@ -29,7 +29,7 @@ const OptionsView: React.FC = () => { ></Header> <Content height={headerHeight}> <KonnectorViewerList isParam={true} /> - <AnalysisOptions /> + <ReportOptions /> <ProfileTypeOptions /> <FAQLink /> <LegalNoticeLink /> diff --git a/src/components/Options/AnalysisOptions.spec.tsx b/src/components/Options/ReportOptions.spec.tsx similarity index 61% rename from src/components/Options/AnalysisOptions.spec.tsx rename to src/components/Options/ReportOptions.spec.tsx index 8ff833ad6dcba46257a30454f993cf1337430941..e5bdbfe4a1f6bfa17471bacd44ec3768e53313de 100644 --- a/src/components/Options/AnalysisOptions.spec.tsx +++ b/src/components/Options/ReportOptions.spec.tsx @@ -1,7 +1,7 @@ import React from 'react' import { mount } from 'enzyme' import { Provider } from 'react-redux' -import AnlysisOptions from 'components/Options/AnalysisOptions' +import ReportOptions from 'components/Options/ReportOptions' import { createMockStore, mockInitialEcolyoState, @@ -18,6 +18,15 @@ jest.mock('cozy-ui/transpiled/react/I18n', () => { } }) +const mockUpdateProfile = jest.fn() +jest.mock('services/profile.service', () => { + return jest.fn(() => { + return { + updateProfile: mockUpdateProfile, + } + }) +}) + const updateProfileSpy = jest.spyOn(profileActions, 'updateProfile') describe('ReportOptions component', () => { @@ -28,44 +37,34 @@ describe('ReportOptions component', () => { updateProfileSpy.mockClear() }) - it('should be rendered with 2 inputs', () => { + it('should be rendered with sendReportNotification to false', () => { const wrapper = mount( <Provider store={store}> - <AnlysisOptions /> + <ReportOptions /> </Provider> ) - expect(wrapper.find('input')).toHaveLength(2) + expect(wrapper.find('input')).toHaveLength(1) + expect( + wrapper + .find('#switch-report') + .first() + .props().checked + ).toBeFalsy() }) it('should update the profile with sendReportNotification to true', () => { const wrapper = mount( <Provider store={store}> - <AnlysisOptions /> + <ReportOptions /> </Provider> ) wrapper - .find('#monthly') + .find('#switch-report') .first() - .simulate('change', { target: { value: 'true' } }) + .simulate('change', { target: { checked: 'true' } }) expect(updateProfileSpy).toBeCalledTimes(1) expect(updateProfileSpy).toHaveBeenCalledWith({ sendReportNotification: true, }) }) - - it('should update the profile with sendReportNotification to false', () => { - const wrapper = mount( - <Provider store={store}> - <AnlysisOptions /> - </Provider> - ) - wrapper - .find('#monthly') - .first() - .simulate('change', { target: { value: 'false' } }) - expect(updateProfileSpy).toBeCalledTimes(1) - expect(updateProfileSpy).toHaveBeenCalledWith({ - sendReportNotification: false, - }) - }) }) diff --git a/src/components/Options/ReportOptions.tsx b/src/components/Options/ReportOptions.tsx new file mode 100644 index 0000000000000000000000000000000000000000..85abc687b7b4152ee7fdb88b4aac47cec3b6b7d3 --- /dev/null +++ b/src/components/Options/ReportOptions.tsx @@ -0,0 +1,47 @@ +import React from 'react' +import { useI18n } from 'cozy-ui/transpiled/react/I18n' +import { useSelector, useDispatch } from 'react-redux' +import { AppStore } from 'store' +import { updateProfile } from 'store/profile/profile.actions' +import './reportOptions.scss' + +const ReportOptions: React.FC = () => { + const { t } = useI18n() + const dispatch = useDispatch() + const profile = useSelector((state: AppStore) => state.ecolyo.profile) + + const updateProfileReport = async (value: boolean) => { + dispatch(updateProfile({ sendReportNotification: value })) + } + + const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { + e.target.checked ? updateProfileReport(true) : updateProfileReport(false) + } + + return ( + <div className="analysis-option-root"> + <div className="analysis-option-content"> + <div className="head text-16-normal-uppercase"> + {t('PROFILE.ANALYSIS.TITLE')} + </div> + <div className="switch-container"> + <label htmlFor="switch-report"> + <input + type="checkbox" + id="switch-report" + name="switch-report" + checked={profile.sendReportNotification} + onChange={handleChange} + /> + <span className="switch-slider"></span> + </label> + <div className="text-16-normal"> + {t('PROFILE.ANALYSIS.SWITCH_LABEL')} + </div> + </div> + </div> + </div> + ) +} + +export default ReportOptions diff --git a/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap b/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap index 5780afa6178e7653c6ac25911217d0e0b985d232..c4d3156eabfca8d61fd3efe22b9c7db2b2f459f4 100644 --- a/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap +++ b/src/components/Options/__snapshots__/OptionsView.spec.tsx.snap @@ -15,7 +15,7 @@ exports[`OptionsView component should be rendered correctly 1`] = ` <KonnectorViewerList isParam={true} /> - <AnalysisOptions /> + <ReportOptions /> <ProfileTypeOptions /> <FAQLink /> <LegalNoticeLink /> diff --git a/src/components/Options/analysisOptions.scss b/src/components/Options/analysisOptions.scss deleted file mode 100644 index 99adef540e6945713a8c4a10911208235da15cb0..0000000000000000000000000000000000000000 --- a/src/components/Options/analysisOptions.scss +++ /dev/null @@ -1,63 +0,0 @@ -@import 'src/styles/base/color'; -@import 'src/styles/base/breakpoint'; -.analysis-option-root { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 0 1.5rem; - .analysis-option-content { - width: 45.75rem; - @media #{$large-phone} { - width: 100%; - } - } - .head { - margin-top: 2rem; - color: $grey-bright; - } - .radios { - margin-top: 0.5rem; - .input { - padding: 0.5rem; - input[type='radio'] { - box-sizing: border-box; - -webkit-appearance: none; - outline: none; - border-radius: 50%; - position: relative; - top: 0.3rem; - width: 1.3rem; - height: 1.3rem; - border: 2px solid $soft-grey; - background: transparent; - &:after { - transition: all 300ms ease; - content: ''; - border-radius: 50%; - } - &:checked { - & ~ label { - color: $grey-bright; - } - &:after { - content: ''; - position: absolute; - top: -2px; - left: -2px; - box-sizing: border-box; - width: inherit; - height: inherit; - background-color: transparent; - border-radius: 50%; - border: 6px solid $gold-shadow; - } - } - } - } - label { - color: $soft-grey; - margin-left: 1rem; - } - } -} diff --git a/src/components/Options/reportOptions.scss b/src/components/Options/reportOptions.scss new file mode 100644 index 0000000000000000000000000000000000000000..ffc6594980f36674399c351d347c3062efaee851 --- /dev/null +++ b/src/components/Options/reportOptions.scss @@ -0,0 +1,67 @@ +@import 'src/styles/base/color'; +@import 'src/styles/base/breakpoint'; +.analysis-option-root { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 0 1.5rem; + .analysis-option-content { + width: 45.75rem; + @media #{$large-phone} { + width: 100%; + } + } + .head { + margin: 2rem 0 1rem; + color: $grey-bright; + } + .switch-container { + display: flex; + align-items: center; + color: $grey-bright; + label { + position: relative; + display: inline-block; + width: 34px; + height: 14px; + margin-right: 1rem; + } + input { + opacity: 0; + width: 0; + height: 0; + &:checked + .switch-slider { + background-color: $gold-shadow; + } + &:focus + .switch-slider { + box-shadow: 0 0 1px $gold-shadow; + } + &:checked + .switch-slider:before { + transform: translateX(19px); + } + } + .switch-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: $grey-dark; + transition: 0.4s; + border-radius: 34px; + &::before { + position: absolute; + content: ''; + height: 20px; + width: 20px; + left: -3px; + bottom: -3px; + border-radius: 50%; + background-color: $grey-bright; + transition: 0.4s; + } + } + } +} diff --git a/src/locales/fr.json b/src/locales/fr.json index 88a31debeb81cabbf9add61b5cada8deddf606e3..46515581c570f754fa07573c477e03ec17976577 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -125,10 +125,8 @@ }, "PROFILE": { "ANALYSIS": { - "TITLE": "Être notifié de l'arrivée de l'analyse mensuel", - "WEEKLY": "Hebdomadaire", - "MONTHLY": "Mensuel", - "NEVER": "Jamais" + "TITLE": "Notification par mail", + "SWITCH_LABEL": "Être prévenu de la parution de mon bilan mensuel" } }, "KONNECTORCONFIG": { diff --git a/src/services/mail.service.spec.ts b/src/services/mail.service.spec.ts index 34150672274a13a74bb505ea3d2f4ead1652b79f..448226be623b3a0bf4f4cdab14a7e4d19a1ae4f8 100644 --- a/src/services/mail.service.spec.ts +++ b/src/services/mail.service.spec.ts @@ -92,7 +92,7 @@ describe('Mail service', () => { }) describe('CreateBodyMonthlyReport service', () => { - it('should return body mail with the right values when url is different from bilan', () => { + it('should return body mail with the right values when url is different from analysis', () => { const result: string = mailService.CreateBodyMonthlyReport( 'user', 'https://user-ecolyo.test.com' @@ -100,7 +100,7 @@ describe('Mail service', () => { expect(result).toEqual(expect.stringContaining('Bonjour user')) expect(result).toEqual( expect.stringContaining( - '<a class="btnEcolyo" href="https://user-ecolyo.test.com/#/bilan">' + '<a class="btnEcolyo" href="https://user-ecolyo.test.com/#/analysis">' ) ) expect(result).toEqual( @@ -110,15 +110,15 @@ describe('Mail service', () => { ) }) - it('should return body mail with the right values when url is equals to bilan', () => { + it('should return body mail with the right values when url is equals to analysis', () => { const result: string = mailService.CreateBodyMonthlyReport( 'user', - 'https://user-ecolyo.test.com/#/bilan' + 'https://user-ecolyo.test.com/#/analysis' ) expect(result).toEqual(expect.stringContaining('Bonjour user')) expect(result).toEqual( expect.stringContaining( - '<a class="btnEcolyo" href="https://user-ecolyo.test.com/#/bilan">' + '<a class="btnEcolyo" href="https://user-ecolyo.test.com/#/analysis">' ) ) expect(result).toEqual( diff --git a/src/services/mail.service.ts b/src/services/mail.service.ts index 1eb375c4a2239f309ef093b210db0cbeff787b6f..7488881d9e955f9f98e8b04a209c1acd940d84e4 100644 --- a/src/services/mail.service.ts +++ b/src/services/mail.service.ts @@ -412,17 +412,17 @@ export default class MailService { } public CreateBodyMonthlyReport(username: string, clientUrl: string) { let unsubscibeUrl = clientUrl - if (!clientUrl.includes('bilan')) { + if (!clientUrl.includes('analysis')) { unsubscibeUrl = clientUrl + '/#/options' - clientUrl = clientUrl + '/#/bilan' + clientUrl = clientUrl + '/#/analysis' } else { - unsubscibeUrl = clientUrl.replace('bilan', 'options') + unsubscibeUrl = clientUrl.replace('analysis', 'options') } return ` <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> - <title>Votre bilan hebdomadaire</title> + <title>Votre bilan mensuel</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <style type="text/css"> @@ -583,7 +583,7 @@ export default class MailService { <tbody> <tr> <td class="title"> - <h2>Bilan Mensuel</h2> + <h2>Du nouveau dans votre espace Ecolyo !</h2> </td> </tr> </tbody> @@ -643,7 +643,10 @@ export default class MailService { style="color:#FFFFFF; font-size:16px;" > <p> - votre bilan mensuel est disponible sur votre espace Ecolyo. + Le bilan de vos consommations du mois dernier est prêt ! + </p> + <p> + Retrouvez-le dans le menu Analyse du service. </p> </div> </td>