diff --git a/jest.config.js b/jest.config.js index 08353ff8..b8c6371f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,7 +2,7 @@ process.env.TZ = 'UTC' module.exports = { testURL: 'http://localhost/', - moduleFileExtensions: ['js', 'jsx', 'json', 'styl'], + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'styl'], setupFiles: ['/test/jestLib/setup.js'], setupFilesAfterEnv: ['/test/jestLib/setupAfterEnv.js'], moduleDirectories: ['src', 'node_modules'], diff --git a/package.json b/package.json index 20f05498..c5e7ccb0 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "scripts": { "analyze": "COZY_SCRIPTS_ANALYZER=true yarn build", "lint": "yarn lint:js && yarn lint:styles", - "lint:js": "cs lint '{src,test}/**/*.{js,jsx}'", + "lint:js": "cs lint '{src,test}/**/*.{js,jsx,ts,tsx}'", "lint:styles": "stylint src/styles --config ./.stylintrc", "prebuild": "yarn lint", "build": "yarn build:browser", diff --git a/src/components/AppProviders.jsx b/src/components/AppProviders.jsx index 9287ea1d..4945ed2c 100644 --- a/src/components/AppProviders.jsx +++ b/src/components/AppProviders.jsx @@ -13,7 +13,6 @@ import { BreakpointsProvider } from 'cozy-ui/transpiled/react/hooks/useBreakpoin import { GEOJSON_DOCTYPE, SETTINGS_DOCTYPE } from 'src/doctypes' import AccountProvider from 'src/components/Providers/AccountProvider' import SelectDatesProvider from 'src/components/Providers/SelectDatesProvider' -import BikeGoalDateProvider from 'src/components/Providers/BikeGoalDateProvider' /* With MUI V4, it is possible to generate deterministic class names. @@ -35,13 +34,11 @@ const AppProviders = ({ client, lang, polyglot, children }) => { - - - - {children} - - - + + + {children} + + diff --git a/src/components/AppRouter.jsx b/src/components/AppRouter.jsx index 6dfac1bb..4d528e07 100644 --- a/src/components/AppRouter.jsx +++ b/src/components/AppRouter.jsx @@ -83,27 +83,30 @@ const AppRouter = () => { } /> } /> } /> )} - - {/* // redirection */} - } - /> - {flag('coachco2.bikegoal.enabled') && ( + {/* redirection */} } + path="analysis" + element={} /> - )} - } /> - } /> + {flag('coachco2.bikegoal.enabled') && ( + + } + /> + )} + } /> + } /> + {/* redirection - end */} + ) diff --git a/src/components/EditDialogs/RecurrenceEditDialog/RecurrenceEditDialogTitle.jsx b/src/components/EditDialogs/RecurrenceEditDialog/RecurrenceEditDialogTitle.jsx index eb6cf603..da6d9907 100644 --- a/src/components/EditDialogs/RecurrenceEditDialog/RecurrenceEditDialogTitle.jsx +++ b/src/components/EditDialogs/RecurrenceEditDialog/RecurrenceEditDialogTitle.jsx @@ -63,7 +63,7 @@ const RecurrenceEditDialogTitle = () => { return (
{t('recurring.title')} - + diff --git a/src/components/Goals/BikeGoal/BikeGoalAchievement.jsx b/src/components/Goals/BikeGoal/BikeGoalAchievement.jsx index bdeedadc..61cf72e7 100644 --- a/src/components/Goals/BikeGoal/BikeGoalAchievement.jsx +++ b/src/components/Goals/BikeGoal/BikeGoalAchievement.jsx @@ -1,5 +1,5 @@ import React from 'react' -import { useNavigate, useParams } from 'react-router-dom' +import { useNavigate } from 'react-router-dom' import PropTypes from 'prop-types' import { useI18n } from 'cozy-ui/transpiled/react/I18n' @@ -19,11 +19,10 @@ import { const BikeGoalAchievement = ({ className, timeseries }) => { const { t } = useI18n() const { isMobile } = useBreakpoints() - const { year } = useParams() const navigate = useNavigate() const handleClickAchievement = () => { - navigate(`certificate/generate/${year}`) + navigate('certificate/generate') } return ( diff --git a/src/components/Goals/BikeGoal/BikeGoalAlertSuccess.jsx b/src/components/Goals/BikeGoal/BikeGoalAlertSuccess.jsx index 7490062c..89d285d4 100644 --- a/src/components/Goals/BikeGoal/BikeGoalAlertSuccess.jsx +++ b/src/components/Goals/BikeGoal/BikeGoalAlertSuccess.jsx @@ -6,18 +6,17 @@ import Alert from 'cozy-ui/transpiled/react/Alert' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { getBountyAmount } from 'src/components/Goals/BikeGoal/helpers' -import { useBikeGoalDateContext } from 'src/components/Providers/BikeGoalDateProvider' import useSettings from 'src/hooks/useSettings' const BikeGoalAlertSuccess = () => { const { t } = useI18n() const navigate = useNavigate() - const { date } = useBikeGoalDateContext() const { save: setShowAlertSuccess } = useSettings('bikeGoal.showAlertSuccess') const handleConfirm = () => { setShowAlertSuccess(false) - navigate(`certificate/generate/${date.getFullYear()}`) + const currentYear = new Date().getFullYear().toString() + navigate(`/bikegoal/${currentYear}/trips/certificate/generate`) } return ( diff --git a/src/components/Goals/BikeGoal/BikeGoalDialogMobile.jsx b/src/components/Goals/BikeGoal/BikeGoalDialogMobile.jsx index 0f0a682c..0199db14 100644 --- a/src/components/Goals/BikeGoal/BikeGoalDialogMobile.jsx +++ b/src/components/Goals/BikeGoal/BikeGoalDialogMobile.jsx @@ -1,6 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { useNavigate } from 'react-router-dom' +import { useNavigate, useParams } from 'react-router-dom' import { IllustrationDialog } from 'cozy-ui/transpiled/react/CozyDialogs' @@ -8,14 +8,18 @@ import BikeGoalList from 'src/components/Goals/BikeGoal/BikeGoalList' import BikeGoalAchievement from 'src/components/Goals/BikeGoal/BikeGoalAchievement' import BikeGoalChart from 'src/components/Goals/BikeGoal/BikeGoalChart' import BikeGoalActions from 'src/components/Goals/BikeGoal/BikeGoalActions' +import { filterTimeseriesByYear } from 'src/lib/timeseries' const BikeGoalDialogMobile = ({ timeseries, timeseriesQueryLeft }) => { const navigate = useNavigate() + const { year } = useParams() + + const timeseriesByYear = filterTimeseriesByYear(timeseries, year) return ( navigate('/')} + onBack={() => navigate('/trips')} disableGutters content={ <> @@ -24,15 +28,15 @@ const BikeGoalDialogMobile = ({ timeseries, timeseriesQueryLeft }) => { display="flex" paddingTop="1.5rem" marginTop="3rem" - timeseries={timeseries} + timeseries={timeseriesByYear} /> diff --git a/src/components/Goals/BikeGoal/BikeGoalSummary.jsx b/src/components/Goals/BikeGoal/BikeGoalSummary.jsx index 4e20fe1b..f4cee4ab 100644 --- a/src/components/Goals/BikeGoal/BikeGoalSummary.jsx +++ b/src/components/Goals/BikeGoal/BikeGoalSummary.jsx @@ -1,5 +1,6 @@ import React from 'react' +import { isQueryLoading, useQueryAll } from 'cozy-client' import Typography from 'cozy-ui/transpiled/react/Typography' import Paper from 'cozy-ui/transpiled/react/Paper' import { useI18n } from 'cozy-ui/transpiled/react/I18n' @@ -11,24 +12,41 @@ import { isGoalCompleted, countDaysOrDaysToReach } from 'src/components/Goals/BikeGoal/helpers' -import { useTemporaryQueryForBikeGoal } from 'src/components/Goals/useTemporaryQueryForBikeGoal' +import { buildBikeCommuteTimeseriesQueryByAccountId } from 'src/queries/queries' +import { useAccountContext } from 'src/components/Providers/AccountProvider' +import { filterTimeseriesByYear } from 'src/lib/timeseries' const BikeGoalSummary = () => { const { t } = useI18n() + const { account, isAccountLoading } = useAccountContext() - // TODO: uncomment this when the request return something - // const timeseriesQuery = - // buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId( - // { - // date: new Date(), - // accountId: account?._id - // }, - // Boolean(account) - // ) + const timeseriesQuery = buildBikeCommuteTimeseriesQueryByAccountId( + { accountId: account?._id }, + Boolean(account) + ) + const { data: timeseries, ...timeseriesQueryLeft } = useQueryAll( + timeseriesQuery.definition, + timeseriesQuery.options + ) + + const isLoadingTimeseriesQuery = + isQueryLoading(timeseriesQueryLeft) || timeseriesQueryLeft.hasMore + + const isLoading = isAccountLoading || isLoadingTimeseriesQuery + + if (isLoading) { + return ( + + + + ) + } - // TODO: remove this hooks when the above request will work - const { timeseries, isLoadingTimeseriesQuery } = - useTemporaryQueryForBikeGoal() + const currentYear = new Date().getFullYear().toString() + const timeseriesByYear = filterTimeseriesByYear(timeseries, currentYear) return ( <> @@ -36,33 +54,27 @@ const BikeGoalSummary = () => { elevation={2} className="u-flex u-flex-items-center u-mh-1-s u-mh-2 u-mb-1 u-flex-items-start" > - {isLoadingTimeseriesQuery ? ( - - ) : ( - <> - -
- {t('bikeGoal.title')} - - {t('bikeGoal.goal_progression', { - days: countDaysOrDaysToReach(timeseries), - daysToReach: getDaysToReach() - })} - -
- - )} + +
+ {t('bikeGoal.title')} + + {t('bikeGoal.goal_progression', { + days: countDaysOrDaysToReach(timeseriesByYear), + daysToReach: getDaysToReach() + })} + +
) diff --git a/src/components/Goals/BikeGoal/BikeGoalViewDesktop.jsx b/src/components/Goals/BikeGoal/BikeGoalViewDesktop.jsx index b23da134..812410c8 100644 --- a/src/components/Goals/BikeGoal/BikeGoalViewDesktop.jsx +++ b/src/components/Goals/BikeGoal/BikeGoalViewDesktop.jsx @@ -1,6 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { useNavigate } from 'react-router-dom' +import { useNavigate, useParams } from 'react-router-dom' import { useI18n } from 'cozy-ui/transpiled/react/I18n' @@ -9,17 +9,21 @@ import BikeGoalList from 'src/components/Goals/BikeGoal/BikeGoalList' import BikeGoalAchievement from 'src/components/Goals/BikeGoal/BikeGoalAchievement' import BikeGoalChart from 'src/components/Goals/BikeGoal/BikeGoalChart' import BikeGoalActions from 'src/components/Goals/BikeGoal/BikeGoalActions' +import { filterTimeseriesByYear } from 'src/lib/timeseries' const BikeGoalViewDesktop = ({ timeseries, timeseriesQueryLeft }) => { const { t } = useI18n() const navigate = useNavigate() + const { year } = useParams() + + const timeseriesByYear = filterTimeseriesByYear(timeseries, year) return ( <> } - onBack={() => navigate('/')} + subtitle={} + onBack={() => navigate('/trips')} /> { position="absolute" top="2rem" right="2rem" - timeseries={timeseries} + timeseries={timeseriesByYear} /> diff --git a/src/components/Goals/BikeGoal/Certificate/CertificateGenerationContent.jsx b/src/components/Goals/BikeGoal/Certificate/CertificateGenerationContent.jsx index 03da6da3..78203020 100644 --- a/src/components/Goals/BikeGoal/Certificate/CertificateGenerationContent.jsx +++ b/src/components/Goals/BikeGoal/Certificate/CertificateGenerationContent.jsx @@ -1,4 +1,5 @@ import React from 'react' +import { useParams } from 'react-router-dom' import Typography from 'cozy-ui/transpiled/react/Typography' import { useI18n } from 'cozy-ui/transpiled/react/I18n' @@ -14,14 +15,13 @@ import FileTypePdfIcon from 'cozy-ui/transpiled/react/Icons/FileTypePdf' import BikeGoalChart from 'src/components/Goals/BikeGoal/BikeGoalChart' import { getBountyAmount } from 'src/components/Goals/BikeGoal/helpers' -import { useBikeGoalDateContext } from 'src/components/Providers/BikeGoalDateProvider' import styles from 'src/components/Goals/BikeGoal/Certificate/CertificateGeneration.styl' const CertificateGenerationContent = () => { const { t } = useI18n() const { isMobile } = useBreakpoints() - const { date } = useBikeGoalDateContext() + const { year } = useParams() return (
@@ -32,7 +32,7 @@ const CertificateGenerationContent = () => { {t('bikeGoal.certificateGeneration.content', { bountyAmount: getBountyAmount(), - year: date.getFullYear() + year })} diff --git a/src/components/Goals/BikeGoal/DateSelector/ActionButton.jsx b/src/components/Goals/BikeGoal/DateSelector/ActionButton.jsx index 29bc7637..525535d3 100644 --- a/src/components/Goals/BikeGoal/DateSelector/ActionButton.jsx +++ b/src/components/Goals/BikeGoal/DateSelector/ActionButton.jsx @@ -31,7 +31,7 @@ const ActionButton = forwardRef(({ label, onClick }, ref) => { ActionButton.displayName = 'ActionButton' ActionButton.propTypes = { - label: PropTypes.number, + label: PropTypes.string, onClick: PropTypes.func } diff --git a/src/components/Goals/BikeGoal/DateSelector/BikeGoalDateSelector.jsx b/src/components/Goals/BikeGoal/DateSelector/BikeGoalDateSelector.jsx index 0abd80c0..7b21646c 100644 --- a/src/components/Goals/BikeGoal/DateSelector/BikeGoalDateSelector.jsx +++ b/src/components/Goals/BikeGoal/DateSelector/BikeGoalDateSelector.jsx @@ -1,38 +1,25 @@ import React, { useRef, useState, useMemo } from 'react' import PropTypes from 'prop-types' -import differenceInCalendarYears from 'date-fns/differenceInCalendarYears' -import subYears from 'date-fns/subYears' +import { useNavigate, useParams } from 'react-router-dom' import ActionMenu, { ActionMenuItem } from 'cozy-ui/transpiled/react/ActionMenu' -import { getEarliestTimeserie } from 'src/lib/timeseries' -import { useBikeGoalDateContext } from 'src/components/Providers/BikeGoalDateProvider' import ActionButton from 'src/components/Goals/BikeGoal/DateSelector/ActionButton' +import { makeMenuDates } from 'src/components/Goals/BikeGoal/DateSelector/helpers' const BikeGoalDateSelector = ({ timeseries }) => { - const { date, setDate } = useBikeGoalDateContext() + const { year } = useParams() + const navigate = useNavigate() const actionMenuAnchorRef = useRef() const [showMenu, setShowMenu] = useState(false) - const earliestDate = useMemo( - () => new Date(getEarliestTimeserie(timeseries).startDate), - [timeseries] - ) - const latestDate = useMemo(() => new Date(), []) - const numberOfYears = differenceInCalendarYears(latestDate, earliestDate) - const menuDates = useMemo( - () => - Array.from({ length: numberOfYears + 1 }, (_, index) => { - return subYears(latestDate, index) - }), - [latestDate, numberOfYears] - ) + const menuDates = useMemo(() => makeMenuDates(timeseries), [timeseries]) return ( <> setShowMenu(v => !v)} /> {showMenu && ( @@ -43,8 +30,11 @@ const BikeGoalDateSelector = ({ timeseries }) => { popperOptions={{ placement: 'bottom-end' }} > {menuDates.map((menuDate, index) => ( - setDate(menuDate)}> - {menuDate.getFullYear()} + navigate(`/bikegoal/${menuDate}/trips`)} + > + {menuDate} ))} diff --git a/src/components/Goals/BikeGoal/DateSelector/helpers.spec.js b/src/components/Goals/BikeGoal/DateSelector/helpers.spec.js new file mode 100644 index 00000000..3137feb1 --- /dev/null +++ b/src/components/Goals/BikeGoal/DateSelector/helpers.spec.js @@ -0,0 +1,15 @@ +import { makeMenuDates } from './helpers' + +describe('makeMenuDates', () => { + it('should return an array of years', () => { + const timeseries = [ + { startDate: '2022-01-01T00:00:00', endDate: '2022-01-01T00:00:00' }, + { startDate: '2020-01-01T00:00:00', endDate: '2020-01-01T00:00:00' }, + { startDate: '2021-01-01T00:00:00', endDate: '2021-01-01T00:00:00' } + ] + + const res = makeMenuDates(timeseries) + + expect(res).toStrictEqual(['2022', '2021', '2020']) + }) +}) diff --git a/src/components/Goals/BikeGoal/DateSelector/helpers.ts b/src/components/Goals/BikeGoal/DateSelector/helpers.ts new file mode 100644 index 00000000..649305ab --- /dev/null +++ b/src/components/Goals/BikeGoal/DateSelector/helpers.ts @@ -0,0 +1,27 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ + +// TODO: remove eslint-disable by convert 'src/lib/timeseries' in TS +// or at least getEarliestTimeserie + +import type { TimeSeries } from 'cozy-client/types/models/timeseries' + +import differenceInCalendarYears from 'date-fns/differenceInCalendarYears' +import subYears from 'date-fns/subYears' + +import { getEarliestTimeserie } from 'src/lib/timeseries' + +export const makeMenuDates = (timeseries: Array): Array => { + const latestDate = new Date() + if (!timeseries || timeseries.length === 0) { + return [latestDate.getFullYear().toString()] + } + + const earliestDate = new Date(getEarliestTimeserie(timeseries).startDate) + const numberOfYears = differenceInCalendarYears(latestDate, earliestDate) + + return Array.from({ length: numberOfYears + 1 }, (_, index) => { + return subYears(latestDate, index).getFullYear().toString() + }) +} diff --git a/src/components/Goals/BikeGoal/OptionSelector/DeactivationModal.jsx b/src/components/Goals/BikeGoal/OptionSelector/DeactivationModal.jsx index 319c9ccd..fa7f8ddf 100644 --- a/src/components/Goals/BikeGoal/OptionSelector/DeactivationModal.jsx +++ b/src/components/Goals/BikeGoal/OptionSelector/DeactivationModal.jsx @@ -17,7 +17,7 @@ const DeactivationModal = ({ open, onClose }) => { const handleDeactivation = () => { setIsBusy(true) save(false) - navigate('/') + navigate('/trips') } return ( diff --git a/src/components/Goals/BikeGoal/helpers.js b/src/components/Goals/BikeGoal/helpers.js index 178361b5..a586c156 100644 --- a/src/components/Goals/BikeGoal/helpers.js +++ b/src/components/Goals/BikeGoal/helpers.js @@ -18,10 +18,14 @@ export const getBountyAmount = () => { } export const isGoalCompleted = timeseries => { + if (!timeseries || timeseries.length === 0) return false + return countDays(timeseries) >= getDaysToReach() } export const countDaysOrDaysToReach = timeseries => { + if (!timeseries || timeseries.length === 0) return 0 + const days = countDays(timeseries) const daysToReach = getDaysToReach() diff --git a/src/components/Goals/useTemporaryQueryForBikeGoal.jsx b/src/components/Goals/useTemporaryQueryForBikeGoal.jsx deleted file mode 100644 index 8e02fd33..00000000 --- a/src/components/Goals/useTemporaryQueryForBikeGoal.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import { hasQueryBeenLoaded, isQueryLoading, useQuery } from 'cozy-client' - -import { buildAggregatedTimeseriesQueryByAccountId } from 'src/queries/queries' -import { useAccountContext } from 'src/components/Providers/AccountProvider' - -export const useTemporaryQueryForBikeGoal = () => { - const { account, isAccountLoading } = useAccountContext() - - const timeseriesQuery = buildAggregatedTimeseriesQueryByAccountId({ - accountId: account?._id, - limitBy: 50 - }) - - const { data: timeseries, ...timeseriesQueryLeft } = useQuery( - timeseriesQuery.definition, - timeseriesQuery.options - ) - - const isLoadingTimeseriesQuery = - isQueryLoading(timeseriesQueryLeft) && - !hasQueryBeenLoaded(timeseriesQueryLeft) - - const isLoadingOrEmpty = - isAccountLoading || - !account || - isLoadingTimeseriesQuery || - timeseries.length === 0 - - return { - isLoadingTimeseriesQuery, - timeseriesQueryLeft, - isLoadingOrEmpty, - timeseries - } -} diff --git a/src/components/Providers/BikeGoalDateProvider.jsx b/src/components/Providers/BikeGoalDateProvider.jsx deleted file mode 100644 index 9a7a704b..00000000 --- a/src/components/Providers/BikeGoalDateProvider.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { createContext, useState, useContext, useMemo } from 'react' - -export const BikeGoalDateContext = createContext() - -export const useBikeGoalDateContext = () => { - const context = useContext(BikeGoalDateContext) - - if (!context) { - throw new Error( - 'useBikeGoalDateContext must be used within a BikeGoalDateProvider' - ) - } - return context -} - -export const BikeGoalDateProvider = ({ children }) => { - const [date, setDate] = useState(() => new Date()) - - const value = useMemo( - () => ({ - date, - setDate - }), - [date] - ) - - return ( - - {children} - - ) -} - -export default BikeGoalDateProvider diff --git a/src/components/Views/BikeGoal.jsx b/src/components/Views/BikeGoal.jsx index b17ba003..4854f07b 100644 --- a/src/components/Views/BikeGoal.jsx +++ b/src/components/Views/BikeGoal.jsx @@ -1,35 +1,35 @@ import React from 'react' +import { isQueryLoading, useQueryAll } from 'cozy-client' import useBreakpoints from 'cozy-ui/transpiled/react/hooks/useBreakpoints' import { useAccountContext } from 'src/components/Providers/AccountProvider' import SpinnerOrEmptyContent from 'src/components/SpinnerOrEmptyContent' import BikeGoalDialogMobile from 'src/components/Goals/BikeGoal/BikeGoalDialogMobile' import BikeGoalViewDesktop from 'src/components/Goals/BikeGoal/BikeGoalViewDesktop' -import { useTemporaryQueryForBikeGoal } from 'src/components/Goals/useTemporaryQueryForBikeGoal' +import { buildBikeCommuteTimeseriesQueryByAccountId } from 'src/queries/queries' const Bikegoal = () => { const { account, isAccountLoading } = useAccountContext() const { isMobile } = useBreakpoints() - // TODO: uncomment this when the request return something - // - // const { date } = useBikeGoalDateContext() - // const timeseriesQuery = - // buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId( - // { - // date, - // accountId: account?._id - // }, - // Boolean(account) - // ) - - // TODO: remove this hooks when the above request will work - const { - timeseries, - timeseriesQueryLeft, - isLoadingTimeseriesQuery, - isLoadingOrEmpty - } = useTemporaryQueryForBikeGoal() + + const timeseriesQuery = buildBikeCommuteTimeseriesQueryByAccountId( + { accountId: account?._id }, + Boolean(account) + ) + const { data: timeseries, ...timeseriesQueryLeft } = useQueryAll( + timeseriesQuery.definition, + timeseriesQuery.options + ) + + const isLoadingTimeseriesQuery = + isQueryLoading(timeseriesQueryLeft) || timeseriesQueryLeft.hasMore + + const isLoadingOrEmpty = + isAccountLoading || + !account || + isLoadingTimeseriesQuery || + timeseries.length === 0 if (isLoadingOrEmpty) { return ( diff --git a/src/components/Views/BikeGoalEdit.jsx b/src/components/Views/BikeGoalEdit.jsx index 0223e3bb..9846b42a 100644 --- a/src/components/Views/BikeGoalEdit.jsx +++ b/src/components/Views/BikeGoalEdit.jsx @@ -16,8 +16,7 @@ const BikeGoalEdit = () => { disableGutters title={t('bikeGoal.edit.title')} content={} - onBack={() => navigate('..')} - onClose={() => navigate('/')} + onClose={() => navigate('..')} /> ) } diff --git a/src/lib/timeseries.js b/src/lib/timeseries.js index 4f21c7a3..09af7521 100644 --- a/src/lib/timeseries.js +++ b/src/lib/timeseries.js @@ -492,3 +492,9 @@ export const getEarliestTimeserie = timeseries => { return prev.startDate < current.startDate ? prev : current }) } + +export const filterTimeseriesByYear = (timeseries, year) => { + return timeseries.filter( + timeserie => new Date(timeserie.startDate).getFullYear().toString() === year + ) +} diff --git a/src/lib/timeseries.spec.js b/src/lib/timeseries.spec.js index 693b64cb..4d84f1a7 100644 --- a/src/lib/timeseries.spec.js +++ b/src/lib/timeseries.spec.js @@ -45,7 +45,8 @@ import { setManualPurpose, computeFirstAndLastDay, countDays, - getEarliestTimeserie + getEarliestTimeserie, + filterTimeseriesByYear } from 'src/lib/timeseries' describe('transformSerieToTrip', () => { @@ -816,3 +817,22 @@ describe('getEarliestTimeserie', () => { }) }) }) + +describe('filterTimeseriesByYear', () => { + it('should return only timeseries that match the year', () => { + const timeseries = [ + { startDate: '2022-01-01T00:00:00', endDate: '2022-01-01T00:00:00' }, + { startDate: '2020-01-01T00:00:00', endDate: '2020-01-01T00:00:00' }, + { startDate: '2021-01-01T00:00:00', endDate: '2021-01-01T00:00:00' } + ] + + const res = filterTimeseriesByYear(timeseries, '2021') + + expect(res).toStrictEqual([ + { + startDate: '2021-01-01T00:00:00', + endDate: '2021-01-01T00:00:00' + } + ]) + }) +}) diff --git a/src/locales/fr.json b/src/locales/fr.json index 004daf8d..0ed1a42e 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -210,9 +210,9 @@ }, "settings": { "participation": "Participer à l'objectif “Aller au travail à vélo”", - "showAlerter": "Afficher l'alerter de l'objectif vélo", - "hideOnboarding": "Masquer l'embarquement d'objectif vélo", - "showAlerterSuccess": "Afficher l'alerte de succès de l'objectif vélo" + "showAlerter": "Objectif vélo : afficher l'alerter", + "hideOnboarding": "Objectif vélo : Masquer l'onboarding", + "showAlerterSuccess": "Objectif vélo : Afficher l'alerte de succès" }, "onboarding": { "title": "Forfait \"mobilités durables\"", diff --git a/src/queries/queries.js b/src/queries/queries.js index 53a6492b..60913bd3 100644 --- a/src/queries/queries.js +++ b/src/queries/queries.js @@ -1,8 +1,6 @@ import endOfMonth from 'date-fns/endOfMonth' import startOfMonth from 'date-fns/startOfMonth' import subYears from 'date-fns/subYears' -import startOfYear from 'date-fns/startOfYear' -import endOfYear from 'date-fns/endOfYear' import CozyClient, { Q } from 'cozy-client' @@ -11,7 +9,7 @@ import { ACCOUNTS_DOCTYPE, SETTINGS_DOCTYPE } from 'src/doctypes' -import { TRIPS_DISTANCE_SIMILARITY_RATIO } from 'src/constants' +import { TRIPS_DISTANCE_SIMILARITY_RATIO, BICYCLING_MODE } from 'src/constants' const older30s = 30 * 1000 const neverReload = 100000 * 1000 @@ -176,31 +174,22 @@ export const buildOneYearOldTimeseriesWithAggregationByAccountId = } } -export const buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId = ( - { date, accountId }, +export const buildBikeCommuteTimeseriesQueryByAccountId = ( + { accountId }, enabled ) => { - const startYearDate = startOfYear(date) - const endYearDate = endOfYear(date) - return { definition: Q('io.cozy.timeseries.geojson') .where({ 'cozyMetadata.sourceAccount': accountId, - startDate: { - $gte: startYearDate.toISOString(), - $lte: endYearDate.toISOString() - }, + startDate: { $gt: null }, 'aggregation.purpose': 'COMMUTE', - 'aggregation.modes': { - $elemMatch: { - $eq: 'BIKE' - } - } + 'aggregation.modes': { $elemMatch: { $eq: BICYCLING_MODE } } }) .select([ 'startDate', 'endDate', + 'aggregation', 'aggregation.modes', 'aggregation.purpose', 'cozyMetadata.sourceAccount' @@ -211,15 +200,10 @@ export const buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId = ( 'aggregation.purpose', 'aggregation.modes' ]) - .sortBy([ - { 'cozyMetadata.sourceAccount': 'desc' }, - { startDate: 'desc' }, - { 'aggregation.purpose': 'desc' }, - { 'aggregation.modes': 'desc' } - ]) - .limitBy(50), + .sortBy([{ 'cozyMetadata.sourceAccount': 'desc' }, { startDate: 'desc' }]) + .limitBy(1000), options: { - as: `${GEOJSON_DOCTYPE}/sourceAccount/${accountId}/OneYearBikeCommute/year/${startYearDate.getFullYear()}`, + as: `${GEOJSON_DOCTYPE}/sourceAccount/${accountId}/BikeCommute/`, fetchPolicy: CozyClient.fetchPolicies.olderThan(neverReload), enabled } diff --git a/src/queries/queries.spec.js b/src/queries/queries.spec.js index f519ab58..06852d54 100644 --- a/src/queries/queries.spec.js +++ b/src/queries/queries.spec.js @@ -4,7 +4,7 @@ import { buildTimeseriesQueryByDateAndAccountId, buildOneYearOldTimeseriesWithAggregationByAccountId, builTimeserieQueryByAccountIdAndStartPlaceAndEndPlaceAndStartDateAndDistance, - buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId + buildBikeCommuteTimeseriesQueryByAccountId } from './queries' describe('buildTimeseriesQueryByDateAndAccountId', () => { @@ -122,21 +122,10 @@ describe('builTimeserieQueryByAccountIdAndStartPlaceAndEndPlaceAndStartDateAndDi }) }) -describe('buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId', () => { - beforeEach(() => { - MockDate.set('2020-01-01') - }) - - afterEach(() => { - MockDate.reset() - }) - +describe('buildBikeCommuteTimeseriesQueryByAccountId', () => { it('should use a well formated selector', () => { - const query = buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId( - { - date: new Date(), - accountId: 'accountId' - }, + const query = buildBikeCommuteTimeseriesQueryByAccountId( + { accountId: 'accountId' }, false ) @@ -145,15 +134,12 @@ describe('buildOneYearBikeCommuteTimeseriesQueryByDateAndAccountId', () => { selector: { 'aggregation.modes': { $elemMatch: { - $eq: 'BIKE' + $eq: 'BICYCLING' } }, 'aggregation.purpose': 'COMMUTE', 'cozyMetadata.sourceAccount': 'accountId', - startDate: { - $gte: '2020-01-01T00:00:00.000Z', - $lte: '2020-12-31T23:59:59.999Z' - } + startDate: { $gt: null } } } })