From f66b1da0ec09ab6f5517eeb93db18a77d548b0e0 Mon Sep 17 00:00:00 2001 From: TaurusVB <114020229+TaurusVB@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:57:38 +0300 Subject: [PATCH] added dynamic changes to VideoCountExercises and BurnedCalories statisticts on Home, Sign In, Sign Up page --- .../ParamsBlockCard.jsx" | 4 +- src/components/headersComp/Logo/Logo.jsx | 9 +-- src/pages/Home/Home.jsx | 31 ++++++++++ src/pages/SignIn/SignIn.jsx | 23 +++++++- src/pages/SignUp/SignUp.jsx | 24 +++++++- src/redux/statistic/operations.js | 26 +++++++++ src/redux/statistic/selectors.js | 13 +++++ src/redux/statistic/slice.js | 56 +++++++++++++++++++ src/redux/store.js | 4 +- src/utils/formatNumberStatistics.js | 11 ++++ 10 files changed, 188 insertions(+), 13 deletions(-) create mode 100644 src/redux/statistic/operations.js create mode 100644 src/redux/statistic/selectors.js create mode 100644 src/redux/statistic/slice.js create mode 100644 src/utils/formatNumberStatistics.js diff --git "a/src/components/ParamsBlock\320\241ard/ParamsBlockCard.jsx" "b/src/components/ParamsBlock\320\241ard/ParamsBlockCard.jsx" index 93339258..91f6fcfe 100644 --- "a/src/components/ParamsBlock\320\241ard/ParamsBlockCard.jsx" +++ "b/src/components/ParamsBlock\320\241ard/ParamsBlockCard.jsx" @@ -25,7 +25,7 @@ const ParamsBlockCard = ({ data, measure, type, step, page }) => { - {data}+ + {data} Video tutorial @@ -51,7 +51,7 @@ const ParamsBlockCard = ({ data, measure, type, step, page }) => { }; ParamsBlockCard.propTypes = { - data: PropTypes.number, + data: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), type: PropTypes.string, measure: PropTypes.string, step: PropTypes.string, diff --git a/src/components/headersComp/Logo/Logo.jsx b/src/components/headersComp/Logo/Logo.jsx index 4fafbe8b..a38a1958 100644 --- a/src/components/headersComp/Logo/Logo.jsx +++ b/src/components/headersComp/Logo/Logo.jsx @@ -1,7 +1,8 @@ -import { Button, WrapLogo, Svg } from './Logo.styled'; +import { WrapLogo, Svg } from './Logo.styled'; import sprite from '../../../assets/sprite.svg'; import { UseAuth } from '../../../hooks/useAuth'; +import { NavLink } from 'react-router-dom'; export const Logo = () => { const { isLoggedIn } = UseAuth(); @@ -9,13 +10,13 @@ export const Logo = () => { return ( <> - {' '} - + ); diff --git a/src/pages/Home/Home.jsx b/src/pages/Home/Home.jsx index 2951bcb9..d554fcc7 100644 --- a/src/pages/Home/Home.jsx +++ b/src/pages/Home/Home.jsx @@ -1,8 +1,26 @@ +import { useEffect } from 'react'; import CustomNavLink from '../../components/CustomNavLink/CustomNavLink'; import MainTitle from '../../components/MainTitle/MainTitle'; +import ParamsBlockCard from '../../components/ParamsBlockСard/ParamsBlockCard'; import { LinkList, Wrapper, WrapperDesktop } from './Home.styled'; +import { useDispatch, useSelector } from 'react-redux'; +import { getVideoCountAndBurnedCaloriesStatistics } from '../../redux/statistic/operations'; +import { + getAllExercises, + getUsersBurnedCalories, +} from '../../redux/statistic/selectors'; +import formatNumber from '../../utils/formatNumberStatistics'; const Home = () => { + const dispatch = useDispatch(); + + const videoExercisesCount = useSelector(getAllExercises); + const allBurnedCalories = useSelector(getUsersBurnedCalories); + + useEffect(() => { + dispatch(getVideoCountAndBurnedCaloriesStatistics()); + }, [dispatch]); + return ( <> @@ -16,6 +34,19 @@ const Home = () => { + + + + ); diff --git a/src/pages/SignIn/SignIn.jsx b/src/pages/SignIn/SignIn.jsx index 24208364..5874c7b2 100644 --- a/src/pages/SignIn/SignIn.jsx +++ b/src/pages/SignIn/SignIn.jsx @@ -1,4 +1,4 @@ -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import Title from '../../components/Title/Title'; import SubTitle from '../../components/SubTitle/SubTitle'; import AuthForm from '../../components/AuthForm/AuthForm'; @@ -7,10 +7,23 @@ import { Wrapper, WrapperDesktop } from '../Home/Home.styled'; import ParamsBlockCard from '../../components/ParamsBlockСard'; import { logInUser } from '../../redux/auth/operation'; import { mg } from '../../utils'; +import { + getAllExercises, + getUsersBurnedCalories, +} from '../../redux/statistic/selectors'; +import { useEffect } from 'react'; +import { getVideoCountAndBurnedCaloriesStatistics } from '../../redux/statistic/operations'; const SignIn = () => { const dispatch = useDispatch(); + const videoExercisesCount = useSelector(getAllExercises); + const allBurnedCalories = useSelector(getUsersBurnedCalories); + + useEffect(() => { + dispatch(getVideoCountAndBurnedCaloriesStatistics()); + }, [dispatch]); + const logIn = (user, { resetForm }) => { dispatch(logInUser(user)); resetForm(); @@ -33,12 +46,16 @@ const SignIn = () => { linkText={'Sign Up'} /> - + diff --git a/src/pages/SignUp/SignUp.jsx b/src/pages/SignUp/SignUp.jsx index c417b1c3..1d8da957 100644 --- a/src/pages/SignUp/SignUp.jsx +++ b/src/pages/SignUp/SignUp.jsx @@ -1,15 +1,29 @@ import Title from '../../components/Title/Title'; import SubTitle from '../../components/SubTitle/SubTitle'; import AuthForm from '../../components/AuthForm'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { authUser } from '../../redux/auth/operation'; import BtnSubtitle from '../../components/BtnSubtitle/BtnSubtitle'; import { Wrapper, WrapperDesktop } from '../Home/Home.styled'; import ParamsBlockCard from '../../components/ParamsBlockСard/ParamsBlockCard'; import { mg } from '../../utils'; +import { + getAllExercises, + getUsersBurnedCalories, +} from '../../redux/statistic/selectors'; +import { useEffect } from 'react'; +import { getVideoCountAndBurnedCaloriesStatistics } from '../../redux/statistic/operations'; const SignUp = () => { const dispatch = useDispatch(); + + const videoExercisesCount = useSelector(getAllExercises); + const allBurnedCalories = useSelector(getUsersBurnedCalories); + + useEffect(() => { + dispatch(getVideoCountAndBurnedCaloriesStatistics()); + }, [dispatch]); + const handleSubmit = (user, { resetForm }) => { dispatch(authUser(user)); resetForm(); @@ -37,12 +51,16 @@ const SignUp = () => { linkText={'Sign In'} /> - + diff --git a/src/redux/statistic/operations.js b/src/redux/statistic/operations.js new file mode 100644 index 00000000..d4680a4d --- /dev/null +++ b/src/redux/statistic/operations.js @@ -0,0 +1,26 @@ +import { createAsyncThunk } from '@reduxjs/toolkit'; +import axios from 'axios'; +import { toast } from 'react-toastify'; + +axios.defaults.baseURL = 'https://power-pulse-rest-api.onrender.com'; + +export const getVideoCountAndBurnedCaloriesStatistics = createAsyncThunk( + 'getVideoCountAndBurnedCaloriesStatistics', + async (_, { rejectWithValue }) => { + try { + const { data } = await axios.get('/api/statistics'); + return data; + } catch (error) { + toast.error('Oops... Something went wrong! Try again!'); + return rejectWithValue('Oops... Something went wrong!'); + } + }, + { + condition: (_, { getState }) => { + const state = getState(); + if (state.statistics.allExercises > 1) { + return false; + } + }, + }, +); diff --git a/src/redux/statistic/selectors.js b/src/redux/statistic/selectors.js new file mode 100644 index 00000000..27fb4374 --- /dev/null +++ b/src/redux/statistic/selectors.js @@ -0,0 +1,13 @@ +export const getAllExercises = state => state.statistics.allExercises; + +export const getAllUsers = state => state.statistics.allUsers; + +export const getUsersBurnedCalories = state => state.statistics.usersBurnedCalories; + +export const getUsersTimeTraining = state => state.statistics.usersTimeTraining; + +export const getUsersTraining = state => state.statistics.usersTraining; + +export const isLoadingStatictics = state => state.statistics.isLoading; + +export const getErrorStatistics = state => state.statistics.error; diff --git a/src/redux/statistic/slice.js b/src/redux/statistic/slice.js new file mode 100644 index 00000000..17f46e8a --- /dev/null +++ b/src/redux/statistic/slice.js @@ -0,0 +1,56 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { getVideoCountAndBurnedCaloriesStatistics } from './operations'; +import formatNumber from '../../utils/formatNumberStatistics'; + +const contactsInitialValue = { + isLoading: false, + error: null, + allExercises: 0, + allUsers: 0, + usersBurnedCalories: 0, + usersTimeTraining: 0, + usersTraining: 0, +}; + +const handlePending = state => { + state.isLoading = true; + state.error = null; +}; + +const handleFullfield = state => { + state.isLoading = false; + state.error = null; +}; + +const handleRejected = (state, payload) => { + state.isLoading = false; + state.error = payload.error; +}; + +const getStatistics = createSlice({ + name: 'statistics', + initialState: contactsInitialValue, + extraReducers: builder => { + builder.addCase( + getVideoCountAndBurnedCaloriesStatistics.pending, + handlePending, + ); + builder.addCase( + getVideoCountAndBurnedCaloriesStatistics.fulfilled, + (state, { payload }) => { + handleFullfield(state, payload); + state.allExercises = payload.AllExercises; + state.allUsers = payload.AllUsers; + state.usersBurnedCalories = formatNumber(payload.usersBurnedCalories); + state.usersTimeTraining = payload.usersTimeTraining; + state.usersTraining = payload.usersTraining; + }, + ); + builder.addCase( + getVideoCountAndBurnedCaloriesStatistics.rejected, + handleRejected, + ); + }, +}); + +export const statisticsReducer = getStatistics.reducer; diff --git a/src/redux/store.js b/src/redux/store.js index 13611fe1..ee480e4f 100644 --- a/src/redux/store.js +++ b/src/redux/store.js @@ -15,7 +15,8 @@ import { authSlice } from './auth/slice'; import filterSlice from './exerciseFilters/slice'; import exercisesSlice from './exercises/slice'; import { diaryReducer } from './diary/slice'; -import productsSlice from './productsFilter/slice'; +import productsSlice from './productsFilter/slice'; +import { statisticsReducer } from './statistic/slice'; const persistConfig = { key: 'token', @@ -29,6 +30,7 @@ const rootReducer = combineReducers({ exercises: exercisesSlice, diary: diaryReducer, products: productsSlice, + statistics: statisticsReducer, }); export const store = configureStore({ diff --git a/src/utils/formatNumberStatistics.js b/src/utils/formatNumberStatistics.js new file mode 100644 index 00000000..5bfcdf83 --- /dev/null +++ b/src/utils/formatNumberStatistics.js @@ -0,0 +1,11 @@ +function formatNumber(number) { + if (number >= 1e6) { + return (number / 1e6).toFixed(1) + 'M'; + } else if (number >= 1e3) { + return (number / 1e3).toFixed(1) + 'K'; + } else { + return number.toString(); + } +} + +export default formatNumber;