From 257f963bae31ebb834ef05f022b58d09f6006001 Mon Sep 17 00:00:00 2001 From: Anastasia Sergeeva Date: Mon, 24 Jul 2023 23:11:04 +0300 Subject: [PATCH 01/90] feat: add routine slider, fix events in main page, start to make recomposition --- src/assets/index.tsx | 10 +- .../Articles/Article/Article.tsx | 4 +- .../Articles/Article/article.module.css | 2 +- .../Articles/Articles.tsx | 4 +- .../Articles/articles.module.css | 4 +- .../BurnoutLevel/BurnoutLevel.module.css | 3 +- .../BurnoutLevel/BurnoutLevel.tsx | 4 +- .../BurnoutTestBanner.module.css | 2 +- .../centerScreenMain.module.css | 19 --- .../CenterScreenMain/centerScreenMain.tsx | 25 ---- .../{RightScreenMain => }/Events/Events.tsx | 9 +- .../Events/events.module.css | 2 +- src/components/EventsMain/EventsMain.tsx | 7 +- .../EventsMainCard/EventsMainCard.tsx | 10 +- .../EventsMainCard/eventsMainCard.module.css | 8 +- .../MoodButton/MoodButton.module.css | 14 +- .../MoodButton/MoodButton.tsx | 8 +- .../MoodGraph/MoodGraph.module.css | 3 +- .../MoodGraph/MoodGraph.tsx | 8 +- src/components/Myteam/Myteam.tsx | 2 +- .../psychologistInfo.module.css | 2 +- .../RightScreenMain/RightScreenMain.tsx | 43 ------ .../rightScreenMain.module.css | 6 - .../RoutineSlider/RoutineSlider.helpers.ts | 13 ++ .../RoutineSlider/RoutineSlider.tsx | 128 ++++++++++++++++++ .../assets/routine-slider-btn.svg | 4 + .../ButtonsList/ButtonsList.module.scss | 8 ++ .../components/ButtonsList/ButtonsList.tsx | 23 ++++ .../RoutineSection/RoutineSection.module.scss | 46 +++++++ .../RoutineSection/RoutineSection.tsx | 38 ++++++ .../RoutineSlider/routineslider.module.scss | 21 +++ src/pages/main/Main.tsx | 66 ++++++++- src/pages/main/main.module.css | 41 +++++- src/pages/profile/Profile.tsx | 4 +- src/shared/api/Api.ts | 8 ++ 35 files changed, 442 insertions(+), 157 deletions(-) rename src/components/{RightScreenMain => }/Articles/Article/Article.tsx (89%) rename src/components/{RightScreenMain => }/Articles/Article/article.module.css (98%) rename src/components/{RightScreenMain => }/Articles/Articles.tsx (89%) rename src/components/{RightScreenMain => }/Articles/articles.module.css (77%) rename src/components/{CenterScreenMain => }/BurnoutLevel/BurnoutLevel.module.css (94%) rename src/components/{CenterScreenMain => }/BurnoutLevel/BurnoutLevel.tsx (95%) delete mode 100644 src/components/CenterScreenMain/centerScreenMain.module.css delete mode 100644 src/components/CenterScreenMain/centerScreenMain.tsx rename src/components/{RightScreenMain => }/Events/Events.tsx (69%) rename src/components/{RightScreenMain => }/Events/events.module.css (96%) rename src/components/{CenterScreenMain => }/MoodButton/MoodButton.module.css (67%) rename src/components/{CenterScreenMain => }/MoodButton/MoodButton.tsx (93%) rename src/components/{CenterScreenMain => }/MoodGraph/MoodGraph.module.css (96%) rename src/components/{CenterScreenMain => }/MoodGraph/MoodGraph.tsx (97%) delete mode 100644 src/components/RightScreenMain/RightScreenMain.tsx delete mode 100644 src/components/RightScreenMain/rightScreenMain.module.css create mode 100644 src/components/RoutineSlider/RoutineSlider.helpers.ts create mode 100644 src/components/RoutineSlider/RoutineSlider.tsx create mode 100644 src/components/RoutineSlider/assets/routine-slider-btn.svg create mode 100644 src/components/RoutineSlider/components/ButtonsList/ButtonsList.module.scss create mode 100644 src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx create mode 100644 src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss create mode 100644 src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx create mode 100644 src/components/RoutineSlider/routineslider.module.scss diff --git a/src/assets/index.tsx b/src/assets/index.tsx index d44c99b..3af2c56 100644 --- a/src/assets/index.tsx +++ b/src/assets/index.tsx @@ -138,7 +138,7 @@ const simpleSmileIcon = ( @@ -165,7 +165,7 @@ const slightlySmileIcon = ( @@ -192,7 +192,7 @@ const expressionlessIcon = ( @@ -219,7 +219,7 @@ const confusedIcon = ( @@ -246,7 +246,7 @@ const worriedIcon = ( diff --git a/src/components/RightScreenMain/Articles/Article/Article.tsx b/src/components/Articles/Article/Article.tsx similarity index 89% rename from src/components/RightScreenMain/Articles/Article/Article.tsx rename to src/components/Articles/Article/Article.tsx index 5c29bd2..efdfcae 100644 --- a/src/components/RightScreenMain/Articles/Article/Article.tsx +++ b/src/components/Articles/Article/Article.tsx @@ -1,8 +1,8 @@ import styles from "./article.module.css"; -import {ArticleInterface} from "@/types"; +import {ArticleInterface} from "@/types.ts"; import React from "react"; import {useNavigate} from "react-router-dom"; -import play from "../../../../../public/play.svg"; +import play from "../../../../public/play.svg"; interface ArticleProps { article: ArticleInterface; diff --git a/src/components/RightScreenMain/Articles/Article/article.module.css b/src/components/Articles/Article/article.module.css similarity index 98% rename from src/components/RightScreenMain/Articles/Article/article.module.css rename to src/components/Articles/Article/article.module.css index d30d9cc..e7f6dd1 100644 --- a/src/components/RightScreenMain/Articles/Article/article.module.css +++ b/src/components/Articles/Article/article.module.css @@ -3,7 +3,7 @@ display: flex; /* width: 47%; */ - max-width: 156px; + width: 156px; height: 210px; flex-direction: column; align-items: flex-start; diff --git a/src/components/RightScreenMain/Articles/Articles.tsx b/src/components/Articles/Articles.tsx similarity index 89% rename from src/components/RightScreenMain/Articles/Articles.tsx rename to src/components/Articles/Articles.tsx index f3cc868..bed16e9 100644 --- a/src/components/RightScreenMain/Articles/Articles.tsx +++ b/src/components/Articles/Articles.tsx @@ -1,7 +1,7 @@ import {FC} from "react"; import styles from "./articles.module.css"; -import {Article} from "./Article/Article"; -import {ArticleInterface} from "@/types"; +import {Article} from "./Article/Article.tsx"; +import {ArticleInterface} from "@/types.ts"; import vector from "@/assets/Vector.svg" interface ArticlesListProps { diff --git a/src/components/RightScreenMain/Articles/articles.module.css b/src/components/Articles/articles.module.css similarity index 77% rename from src/components/RightScreenMain/Articles/articles.module.css rename to src/components/Articles/articles.module.css index 9354799..11046f6 100644 --- a/src/components/RightScreenMain/Articles/articles.module.css +++ b/src/components/Articles/articles.module.css @@ -6,8 +6,8 @@ /* flex-wrap: wrap; */ align-items: center; margin: 16px 0 0; - gap: 12px; - grid-template-columns: 1fr 1fr; + gap: 17.33px; + grid-template-columns: repeat(4, 1fr); } .title { diff --git a/src/components/CenterScreenMain/BurnoutLevel/BurnoutLevel.module.css b/src/components/BurnoutLevel/BurnoutLevel.module.css similarity index 94% rename from src/components/CenterScreenMain/BurnoutLevel/BurnoutLevel.module.css rename to src/components/BurnoutLevel/BurnoutLevel.module.css index bc133db..46bcc3f 100644 --- a/src/components/CenterScreenMain/BurnoutLevel/BurnoutLevel.module.css +++ b/src/components/BurnoutLevel/BurnoutLevel.module.css @@ -1,10 +1,9 @@ .container { position: relative; - max-width: 676px; + width: 676px; height: 188px; padding: 16px 20px; border-radius: 20px; - margin-top: 32px; background-color: white; /* background-image: url("./burnoutLevel-TO_BE_DELETED.png"); diff --git a/src/components/CenterScreenMain/BurnoutLevel/BurnoutLevel.tsx b/src/components/BurnoutLevel/BurnoutLevel.tsx similarity index 95% rename from src/components/CenterScreenMain/BurnoutLevel/BurnoutLevel.tsx rename to src/components/BurnoutLevel/BurnoutLevel.tsx index 2d3e71b..feab7a6 100644 --- a/src/components/CenterScreenMain/BurnoutLevel/BurnoutLevel.tsx +++ b/src/components/BurnoutLevel/BurnoutLevel.tsx @@ -1,8 +1,8 @@ import styles from "./BurnoutLevel.module.css"; import { ResponsiveBar } from "@nivo/bar"; import { useState, useEffect } from "react"; -import { useAppSelector } from "@/store/hooks"; -import { selectBurnoutLevel } from "@/store/reducers/conditionsBurnout/conditionsBurnoutReducer"; +import { useAppSelector } from "@/store/hooks.ts"; +import { selectBurnoutLevel } from "@/store/reducers/conditionsBurnout/conditionsBurnoutReducer.ts"; import { DataBurnOutInterface, UserBurnoutLevel } from "@/types.ts"; import { useLocation } from "react-router"; diff --git a/src/components/BurnoutTestBanner/BurnoutTestBanner.module.css b/src/components/BurnoutTestBanner/BurnoutTestBanner.module.css index 9ab6a16..82cf8af 100644 --- a/src/components/BurnoutTestBanner/BurnoutTestBanner.module.css +++ b/src/components/BurnoutTestBanner/BurnoutTestBanner.module.css @@ -1,6 +1,6 @@ .container { display: flex; - max-width: 676px; + width: 676px; height: 148px; padding: 16px 16px 16px 20px; border-radius: 20px; diff --git a/src/components/CenterScreenMain/centerScreenMain.module.css b/src/components/CenterScreenMain/centerScreenMain.module.css deleted file mode 100644 index cfcc672..0000000 --- a/src/components/CenterScreenMain/centerScreenMain.module.css +++ /dev/null @@ -1,19 +0,0 @@ -.container { - /* test */ -} - -.mood-tracker { - margin: 32px 0 0; -} - -.mood-tracker-heading { - margin: 0; - color: var(--color-black); - font: var(--font-h2); -} - -.mood-buttons { - display: flex; - justify-content: space-between; - margin: 24px 0 0; -} diff --git a/src/components/CenterScreenMain/centerScreenMain.tsx b/src/components/CenterScreenMain/centerScreenMain.tsx deleted file mode 100644 index 238aac4..0000000 --- a/src/components/CenterScreenMain/centerScreenMain.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import styles from "./centerScreenMain.module.css"; -import { BurnoutTestBanner } from "../BurnoutTestBanner/BurnoutTestBanner"; -import { MoodButton } from "./MoodButton/MoodButton"; -import { MoodGraph } from "./MoodGraph/MoodGraph"; -import { BurnoutLevel } from "./BurnoutLevel/BurnoutLevel"; - -export const CenterScreenMain = () => { - return ( -
- -
-

Оцените свое настроение

-
- - - - - -
- - -
-
- ); -}; diff --git a/src/components/RightScreenMain/Events/Events.tsx b/src/components/Events/Events.tsx similarity index 69% rename from src/components/RightScreenMain/Events/Events.tsx rename to src/components/Events/Events.tsx index fd33cbb..2f4398b 100644 --- a/src/components/RightScreenMain/Events/Events.tsx +++ b/src/components/Events/Events.tsx @@ -9,7 +9,7 @@ export const EventsMain = () => {

Тимбилдинг

- +
  • @@ -19,6 +19,13 @@ export const EventsMain = () => {
  • +
  • + +
    +

    Тимбилдинг

    + +
    +
  • ); diff --git a/src/components/RightScreenMain/Events/events.module.css b/src/components/Events/events.module.css similarity index 96% rename from src/components/RightScreenMain/Events/events.module.css rename to src/components/Events/events.module.css index 733551d..aeed159 100644 --- a/src/components/RightScreenMain/Events/events.module.css +++ b/src/components/Events/events.module.css @@ -1,5 +1,5 @@ .events { - max-width: 324px; + width: 324px; } .title { diff --git a/src/components/EventsMain/EventsMain.tsx b/src/components/EventsMain/EventsMain.tsx index 5df1b28..6b698d2 100644 --- a/src/components/EventsMain/EventsMain.tsx +++ b/src/components/EventsMain/EventsMain.tsx @@ -1,5 +1,5 @@ import styles from "./eventsMain.module.css"; -import { useState, useEffect } from "react"; +import React, { useState, useEffect } from "react"; import { EventInterface } from "@/types"; import { EventsMainCard } from "./EventsMainCard/EventsMainCard"; @@ -14,10 +14,7 @@ export const EventsMain: React.FC = ({events}) => { setEventsSort(events.slice(0,2)) },[events]); - // useEffect(()=>{ - // console.log(events); - // console.log(eventsSort); - // },[eventsSort]); + console.log(eventsSort); return (
    diff --git a/src/components/EventsMain/EventsMainCard/EventsMainCard.tsx b/src/components/EventsMain/EventsMainCard/EventsMainCard.tsx index 246a062..de074da 100644 --- a/src/components/EventsMain/EventsMainCard/EventsMainCard.tsx +++ b/src/components/EventsMain/EventsMainCard/EventsMainCard.tsx @@ -14,6 +14,8 @@ export const EventsMainCard: React.FC = ({item}) => { const hoursEnd = dataEnd.getHours() < 10 ? `0${dataEnd.getHours()}` : `${dataEnd.getHours()}`; const minutesEnd = dataEnd.getMinutes() < 10 ? `0${dataEnd.getMinutes()}` : `${dataEnd.getMinutes()}`; + console.log() + return (
  • @@ -21,18 +23,12 @@ export const EventsMainCard: React.FC = ({item}) => {

    {monthNames[dataStart.getMonth()]}

    -

    Тимбилдинг

    +

    {item.name}

    {`${hoursStart}:${minutesStart}`}— {`${hoursEnd}:${minutesEnd}`}

    - - {/* -
    -

    Тимбилдинг

    - -
    */}
  • ); } diff --git a/src/components/EventsMain/EventsMainCard/eventsMainCard.module.css b/src/components/EventsMain/EventsMainCard/eventsMainCard.module.css index d667af1..e2035dc 100644 --- a/src/components/EventsMain/EventsMainCard/eventsMainCard.module.css +++ b/src/components/EventsMain/EventsMainCard/eventsMainCard.module.css @@ -1,6 +1,6 @@ .point { display: flex; - width: 100%; + width: 324px; justify-content: space-between; padding: 12px 16px; border-radius: 20px; @@ -14,10 +14,11 @@ flex-direction: column; } -.rightBlock { +.right-block { display:flex; flex-direction: column; justify-content: center; + align-items: flex-end; gap: 8px; } @@ -40,7 +41,8 @@ .typeActivity { margin: 0; color: var(--color-accent-purple); - font: var(--font-body) + font: var(--font-body); + text-align: right; } .time { diff --git a/src/components/CenterScreenMain/MoodButton/MoodButton.module.css b/src/components/MoodButton/MoodButton.module.css similarity index 67% rename from src/components/CenterScreenMain/MoodButton/MoodButton.module.css rename to src/components/MoodButton/MoodButton.module.css index 7777e1c..ccd17b5 100644 --- a/src/components/CenterScreenMain/MoodButton/MoodButton.module.css +++ b/src/components/MoodButton/MoodButton.module.css @@ -1,11 +1,13 @@ .container { display: flex; - width: 122px; + width: 192.4px; height: 58px; align-items: center; justify-content: center; + padding: 0; border: none; border-radius: 0 0 12px 12px; + background-color: var(--color-background-white); filter: drop-shadow(0 0 2px rgb(0 0 0 / 6%)) drop-shadow(0 4px 2px rgb(0 0 0 / 3%)); font: var(--font-button); @@ -23,21 +25,21 @@ } .mood-button-red { - border-top: 6px solid #fa3d33; + border-top: 4px solid #fa3d33; } .mood-button-orange { - border-top: 6px solid #ff6941; + border-top: 4px solid #ff6941; } .mood-button-yellow { - border-top: 6px solid #feab23; + border-top: 4px solid #feab23; } .mood-button-green { - border-top: 6px solid #99ca65; + border-top: 4px solid #99ca65; } .mood-button-supergreen { - border-top: 6px solid #00b750; + border-top: 4px solid #00b750; } diff --git a/src/components/CenterScreenMain/MoodButton/MoodButton.tsx b/src/components/MoodButton/MoodButton.tsx similarity index 93% rename from src/components/CenterScreenMain/MoodButton/MoodButton.tsx rename to src/components/MoodButton/MoodButton.tsx index fa77e29..17da451 100644 --- a/src/components/CenterScreenMain/MoodButton/MoodButton.tsx +++ b/src/components/MoodButton/MoodButton.tsx @@ -1,9 +1,9 @@ import styles from "./MoodButton.module.css"; import cn from "classnames"; -import { useAppDispatch, useAppSelector } from "@/store/hooks"; -import { setSuccessMessage } from "@/store/reducers/alertSuccess/alertSuccessReducer"; -import { setErrorMessage } from "@/store/reducers/alertError/alertErrorReducer"; -import { sendButtonCondition, selectButtonConditions } from "@/store/reducers/conditionsBurnout/conditionsBurnoutReducer"; +import { useAppDispatch, useAppSelector } from "@/store/hooks.ts"; +import { setSuccessMessage } from "@/store/reducers/alertSuccess/alertSuccessReducer.ts"; +import { setErrorMessage } from "@/store/reducers/alertError/alertErrorReducer.ts"; +import { sendButtonCondition, selectButtonConditions } from "@/store/reducers/conditionsBurnout/conditionsBurnoutReducer.ts"; type Moods = "bad" | "so-so" | "normal" | "good" | "perfect"; interface MoodsProps { diff --git a/src/components/CenterScreenMain/MoodGraph/MoodGraph.module.css b/src/components/MoodGraph/MoodGraph.module.css similarity index 96% rename from src/components/CenterScreenMain/MoodGraph/MoodGraph.module.css rename to src/components/MoodGraph/MoodGraph.module.css index ee9457d..0fabf18 100644 --- a/src/components/CenterScreenMain/MoodGraph/MoodGraph.module.css +++ b/src/components/MoodGraph/MoodGraph.module.css @@ -1,10 +1,9 @@ .container { position: relative; - max-width: 676px; + width: 676px; height: 328px; padding: 16px 20px; border-radius: 20px; - margin-top: 32px; background-color: white; } diff --git a/src/components/CenterScreenMain/MoodGraph/MoodGraph.tsx b/src/components/MoodGraph/MoodGraph.tsx similarity index 97% rename from src/components/CenterScreenMain/MoodGraph/MoodGraph.tsx rename to src/components/MoodGraph/MoodGraph.tsx index 789ecb0..8f81483 100644 --- a/src/components/CenterScreenMain/MoodGraph/MoodGraph.tsx +++ b/src/components/MoodGraph/MoodGraph.tsx @@ -1,7 +1,7 @@ import { ResponsiveLine } from "@nivo/line"; import { useState, useEffect } from "react"; -import { selectConditions, selectButtonConditions } from "@/store/reducers/conditionsBurnout/conditionsBurnoutReducer"; -import { useAppSelector } from "@/store/hooks"; +import { selectConditions, selectButtonConditions } from "@/store/reducers/conditionsBurnout/conditionsBurnoutReducer.ts"; +import { useAppSelector } from "@/store/hooks.ts"; import { arrowLeft, arrowRight } from "@/assets"; import { @@ -159,13 +159,13 @@ export const MoodGraph = ({conditionsData}: Props) => { margin={{ top: 50, right: 0, bottom: 40, left: 33 }} // xScale={{ type: "point" }} curve="basis" - lineWidth={1} + lineWidth={1.5} enablePoints={false} enableGridX={false} enableGridY={false} enableArea={true} areaOpacity={0.1} - colors={{ scheme: 'purple_orange' }} + colors={'#8A32E0'} animate={true} defs={[ { diff --git a/src/components/Myteam/Myteam.tsx b/src/components/Myteam/Myteam.tsx index 4e462e1..8fae245 100644 --- a/src/components/Myteam/Myteam.tsx +++ b/src/components/Myteam/Myteam.tsx @@ -1,7 +1,7 @@ import styles from "./myteam.module.css"; import React, { useState, useEffect } from "react"; import { Navbar } from "@/components/Navbar/Navbar"; -import { Articles } from "../RightScreenMain/Articles/Articles"; +import { Articles } from "@/components/Articles/Articles"; import { Employees } from "../Employees/Employees"; import { ArticleInterface, EmployeeInterface } from "@/types"; import { Button } from "@/shared/ui/Button/Button"; diff --git a/src/components/PsychologistInfo/psychologistInfo.module.css b/src/components/PsychologistInfo/psychologistInfo.module.css index 34d3ac0..120d01e 100644 --- a/src/components/PsychologistInfo/psychologistInfo.module.css +++ b/src/components/PsychologistInfo/psychologistInfo.module.css @@ -1,6 +1,6 @@ .psychologist-info { display: flex; - max-width: 324px; + width: 324px; height: 148px; flex-direction: column; padding: 12px 20px 16px; diff --git a/src/components/RightScreenMain/RightScreenMain.tsx b/src/components/RightScreenMain/RightScreenMain.tsx deleted file mode 100644 index 2bb232c..0000000 --- a/src/components/RightScreenMain/RightScreenMain.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import styles from "./rightScreenMain.module.css"; -import { EventInterface } from "@/types"; -import {PsychologistInfo} from "../PsychologistInfo/PsychologistInfo"; -import { Articles } from "./Articles/Articles"; -import { EventsMain } from "../EventsMain/EventsMain"; -import {ArticleInterface} from "@/types"; - -interface Props { - events: EventInterface[]; -} -export const RightScreenMain: React.FC = ({events}) => { - const articles: ArticleInterface[] = [ - { - type: "видео", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - { - type: "статья", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - { - type: "видео", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - ]; - - return ( -
    - - - -
    - ); -}; diff --git a/src/components/RightScreenMain/rightScreenMain.module.css b/src/components/RightScreenMain/rightScreenMain.module.css deleted file mode 100644 index 1387e8c..0000000 --- a/src/components/RightScreenMain/rightScreenMain.module.css +++ /dev/null @@ -1,6 +0,0 @@ -.container { - display: flex; - max-width: 324px; - flex-flow: column wrap; - gap: 32px; -} diff --git a/src/components/RoutineSlider/RoutineSlider.helpers.ts b/src/components/RoutineSlider/RoutineSlider.helpers.ts new file mode 100644 index 0000000..31d93bb --- /dev/null +++ b/src/components/RoutineSlider/RoutineSlider.helpers.ts @@ -0,0 +1,13 @@ +export const getPercentage = (containerWidth: number, distanceMoved: number) => { + return (distanceMoved / containerWidth) * 100; +}; + +export const limitNumberWithinRange = ( + value: number, + min: number, + max: number +): number => { + return Math.min(Math.max(value, min), max); +}; + +export const nearestN = (N: number, number: number) => Math.ceil(number / N) * N; diff --git a/src/components/RoutineSlider/RoutineSlider.tsx b/src/components/RoutineSlider/RoutineSlider.tsx new file mode 100644 index 0000000..65715ab --- /dev/null +++ b/src/components/RoutineSlider/RoutineSlider.tsx @@ -0,0 +1,128 @@ +import { useEffect, useRef, useState } from 'react'; +import { useRequest } from "@/shared/hooks/useRequest.tsx"; +import { getActivityTypes } from "@/shared/api/Api.ts"; +import { RoutineSection } from "@/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx"; +import { getPercentage, limitNumberWithinRange, nearestN } from "@/components/RoutineSlider/RoutineSlider.helpers.ts"; +import classes from './routineslider.module.scss'; +import {ButtonsList} from "@/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx"; + +interface TagsInterface { + id: number; + name: string; + description: string; + key: number; + color: string; +} + +export const RoutineSlider = () => { + const [data] = useRequest(getActivityTypes); + const [widths, setWidths] = useState([]); + const RoutineSliderRef = useRef(null); + const [tags, setTags] = useState([]); + + useEffect(() => { + if (data) { + setWidths(new Array(data.length).fill(100 / data.length)); + setTags(data); + } + }, [data]); + + const handleCancelButton = () => { + setTags(data) + setWidths(new Array(data.length).fill(100 / data.length)) + } + + return ( +
    +

    Чем был наполнен ваш день сегодня?

    +
    + {tags.map((tag, index) => ( + { + e.preventDefault(); + document.body.style.cursor = "ew-resize"; + + const startDragX = e.pageX; + const sliderWidth = RoutineSliderRef.current?.offsetWidth || 0; + + if (!startDragX || sliderWidth === 0) return; + + const resize = (e: any) => { + e.preventDefault(); + const endDragX = e.type === 'touchmove' ? e.touches[0].pageX : e.pageX; + const distanceMoved = endDragX - startDragX; + const maxPercent = widths[index] + widths[index + 1]; + + const percentageMoved = nearestN(1, getPercentage(sliderWidth, distanceMoved)) + // const percentageMoved = getPercentage(sliderWidth, distanceMoved); + + const _widths = widths.slice(); + + const prevPercentage = _widths[index]; + + const newPercentage = prevPercentage + percentageMoved; + _widths[index] = limitNumberWithinRange( + newPercentage, + 0, + maxPercent + ); + + const nextSectionIndex = index + 1; + + const nextSectionNewPercentage = + _widths[nextSectionIndex] - percentageMoved; + _widths[nextSectionIndex] = limitNumberWithinRange( + nextSectionNewPercentage, + 0, + maxPercent + ); + + if (tags.length > 2) { + if (_widths[index] === 0) { + _widths[nextSectionIndex] = maxPercent; + _widths.splice(index, 1); + setTags(tags.filter((_, i) => i !== index)); + removeEventListener(); + } + if (_widths[nextSectionIndex] === 0) { + _widths[index] = maxPercent; + _widths.splice(nextSectionIndex, 1); + setTags(tags.filter((_, i) => i !== nextSectionIndex)); + removeEventListener(); + } + } + + setWidths(_widths); + }; + + window.addEventListener("pointermove", resize); + window.addEventListener("touchmove", resize); + + const removeEventListener = () => { + window.removeEventListener("pointermove", resize); + window.removeEventListener("touchmove", resize); + }; + + const handleEventUp = (e: Event) => { + e.preventDefault(); + document.body.style.cursor = "initial"; + removeEventListener(); + }; + + window.addEventListener("touchend", handleEventUp); + window.addEventListener("pointerup", handleEventUp); + }} + color={tag.color} + /> + ))} +
    + +
    + ); +}; diff --git a/src/components/RoutineSlider/assets/routine-slider-btn.svg b/src/components/RoutineSlider/assets/routine-slider-btn.svg new file mode 100644 index 0000000..5ccb563 --- /dev/null +++ b/src/components/RoutineSlider/assets/routine-slider-btn.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/RoutineSlider/components/ButtonsList/ButtonsList.module.scss b/src/components/RoutineSlider/components/ButtonsList/ButtonsList.module.scss new file mode 100644 index 0000000..ab19429 --- /dev/null +++ b/src/components/RoutineSlider/components/ButtonsList/ButtonsList.module.scss @@ -0,0 +1,8 @@ +@import "@/shared/styles/mixins.scss"; + +.buttons-list { + margin: 24px 0 0 38px; + display: flex; + align-items: center; + gap: 58px; +} diff --git a/src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx b/src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx new file mode 100644 index 0000000..436bc3e --- /dev/null +++ b/src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx @@ -0,0 +1,23 @@ +import {Button} from "@/shared/ui/Button/Button.tsx"; +import styles from './ButtonsList.module.scss'; +import {ReactElement} from "react"; + +interface Props { + handleCancelButton: () => void; +} +export const ButtonsList = ({handleCancelButton}: Props): ReactElement => { + return ( +
    +
    + ); +}; diff --git a/src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss new file mode 100644 index 0000000..cc3c867 --- /dev/null +++ b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss @@ -0,0 +1,46 @@ + +.tag:last-of-type>.slider-button { + display:none !important; +} + +.tag { + text-align: center; + position: relative; + box-sizing: border-box; + padding: 10px 0 15px; + border-right: 4px solid white; + &:last-of-type { + border-right: none; + } + &-text { + color: white; + user-select: none; + display: block; + overflow: hidden; + &-name { + font: var(--font-button); + } + &-percentage { + font: var(--font-caption); + } + } +} + +.slider-button { + width: 2em; + height: 2em; + background-color: white; + position: absolute; + border-radius: 50%; + right: calc(-1.1em); + top: 0; + display: flex; + justify-content: center; + align-items: center; + bottom: 0; + margin: auto; + z-index: 10; + cursor: ew-resize; + user-select: none; +} + diff --git a/src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx new file mode 100644 index 0000000..3094480 --- /dev/null +++ b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx @@ -0,0 +1,38 @@ +import classes from './RoutineSection.module.scss'; +import BtnBackground from '../../assets/routine-slider-btn.svg'; +import React from "react"; + +interface RoutineSectionProps { + name: string; + color: string; + width: number; + onSliderSelect: (e: React.MouseEvent) => void; +} + +export const RoutineSection = ({ + name, + color, + width, + onSliderSelect + }: RoutineSectionProps) => { + return ( +
    + {name} + {width + "%"} + +
    + +
    +
    + ); +}; + diff --git a/src/components/RoutineSlider/routineslider.module.scss b/src/components/RoutineSlider/routineslider.module.scss new file mode 100644 index 0000000..08b669a --- /dev/null +++ b/src/components/RoutineSlider/routineslider.module.scss @@ -0,0 +1,21 @@ +@import "@/shared/styles/mixins.scss"; + +.container { + background-color: var(--color-background-white); + border-radius: 20px; + padding: 12px 20px 16px; + margin-bottom: 27px; +} + +.title { + font: var(--font-h2); + color: var(--color-black); + margin: 0 0 24px; +} + +.routine-slider { + width: 100%; + display: flex; + border-radius: 20px; + overflow: hidden; +} diff --git a/src/pages/main/Main.tsx b/src/pages/main/Main.tsx index 9d1d9b7..3012e3c 100644 --- a/src/pages/main/Main.tsx +++ b/src/pages/main/Main.tsx @@ -1,10 +1,16 @@ import styles from "./main.module.css"; -import { EventInterface } from "@/types"; +import {ArticleInterface, EventInterface} from "@/types"; import { useOnlineCheck } from "@/shared/hooks/useOnlineCheck"; -import { CenterScreenMain } from "@/components/CenterScreenMain/centerScreenMain"; -import { RightScreenMain } from "@/components/RightScreenMain/RightScreenMain"; import { BadInternetConnection } from "@/components/BadInternetConnection/BadInternetConnection"; import { Navbar } from "@/components/Navbar/Navbar"; +import {RoutineSlider} from "@/components/RoutineSlider/RoutineSlider.tsx"; +import {MoodButton} from "@/components/MoodButton/MoodButton.tsx"; +import {BurnoutTestBanner} from "@/components/BurnoutTestBanner/BurnoutTestBanner.tsx"; +import {MoodGraph} from "@/components/MoodGraph/MoodGraph.tsx"; +import {BurnoutLevel} from "@/components/BurnoutLevel/BurnoutLevel.tsx"; +import {PsychologistInfo} from "@/components/PsychologistInfo/PsychologistInfo.tsx"; +import {Articles} from "@/components/Articles/Articles.tsx"; +import {EventsMain} from "@/components/EventsMain/EventsMain.tsx"; interface Props { events: EventInterface[]; @@ -12,15 +18,63 @@ interface Props { export const Main: React.FC = ({events}) => { const isOnline = useOnlineCheck(); + const articles: ArticleInterface[] = [ + { + type: "видео", + title: "Как понять, что у вас профессиональное выгорание", + length: "5 минут", + banner: "/image.png", + }, + { + type: "статья", + title: "Как понять, что у вас профессиональное выгорание", + length: "5 минут", + banner: "/image.png", + }, + { + type: "видео", + title: "Как понять, что у вас профессиональное выгорание", + length: "5 минут", + banner: "/image.png", + }, + ]; + return (
    {isOnline ?
    - {/*
    */}
    - - +
    + + +
    +
    +

    Оцените свое настроение сегодня

    +
    + + + + + +
    +
    + +
    + +
    здесь будет круговая диаграмма
    +
    +
    + +
    здесь будет кнопка для скачивания аналитики
    +
    +
    + + +
    : } diff --git a/src/pages/main/main.module.css b/src/pages/main/main.module.css index 1d186df..7898463 100644 --- a/src/pages/main/main.module.css +++ b/src/pages/main/main.module.css @@ -3,16 +3,49 @@ } .main { - display: flex; + width: 1029px; box-sizing: border-box; + padding: 40px 0 46px; +} - /* padding: 40px 132px 46px 52px; */ - padding: 40px 10px 46px; +.section { + display: flex; gap: 28px; + margin-bottom: 32px; +} + +.mood-tracker { + margin: 0 0 32px; +} + +.mood-tracker-heading { + margin: 0; + color: var(--color-black); + font: var(--font-h2); +} + +.mood-buttons { + display: flex; + justify-content: space-between; + margin: 24px 0 0; +} + +.pie-chart { + width: 324px; + height: 328px; + border-radius: 20px; + background-color: white; +} + +.analytics { + width: 324px; + height: 188px; + border-radius: 20px; + background-color: white; } @media screen and (width > 1440px) { .main { - justify-content: center; + margin: 0 auto; } } diff --git a/src/pages/profile/Profile.tsx b/src/pages/profile/Profile.tsx index 1ddf98d..188e851 100644 --- a/src/pages/profile/Profile.tsx +++ b/src/pages/profile/Profile.tsx @@ -23,8 +23,8 @@ import { UserConditionRecieved, } from "@/types"; import * as Api from "@/shared/api/Api"; -import { MoodGraph } from "@/components/CenterScreenMain/MoodGraph/MoodGraph"; -import { BurnoutLevel } from "@/components/CenterScreenMain/BurnoutLevel/BurnoutLevel"; +import { MoodGraph } from "@/components/MoodGraph/MoodGraph"; +import { BurnoutLevel } from "@/components/BurnoutLevel/BurnoutLevel"; import { BalanceWheelResult } from "@/pages/balancewheel/components/BalanceWheelResult/BalanceWheelResult"; interface Props { diff --git a/src/shared/api/Api.ts b/src/shared/api/Api.ts index 7779e2e..7245ef6 100644 --- a/src/shared/api/Api.ts +++ b/src/shared/api/Api.ts @@ -350,3 +350,11 @@ export const fetchData = async () => { } }; +export const getActivityTypes = () => { + return axios.get(`${BASE_URL_REQUEST}/metrics/activity_types`, { + headers: { + authorization: `Bearer ${localStorage.getItem("jwt")}`, + }, + }); +}; + From 217e370350073da376022281b63f2b6a6f43920f Mon Sep 17 00:00:00 2001 From: Anastasia Sergeeva Date: Wed, 26 Jul 2023 10:18:01 +0300 Subject: [PATCH 02/90] feat: make pie chart --- package-lock.json | 59 +++++++++ package.json | 1 + src/components/App/App.tsx | 1 + src/components/EventsMain/EventsMain.tsx | 2 - src/components/PieChart/PieChart.module.scss | 4 + src/components/PieChart/PieChart.tsx | 81 +++++++++++++ .../RoutineSlider/RoutineSlider.tsx | 59 +++++---- .../components/ButtonsList/ButtonsList.tsx | 8 +- .../RoutineSection/RoutineSection.module.scss | 4 + .../RoutineSection/RoutineSection.tsx | 2 + .../RoutineSlider/routineslider.module.scss | 1 - src/pages/main/Main.tsx | 113 +++++++++++------- .../{main.module.css => main.module.scss} | 15 ++- src/shared/api/Api.ts | 30 ++++- src/shared/ui/Button/button.module.scss | 10 +- src/types.ts | 13 ++ 16 files changed, 324 insertions(+), 79 deletions(-) create mode 100644 src/components/PieChart/PieChart.module.scss create mode 100644 src/components/PieChart/PieChart.tsx rename src/pages/main/{main.module.css => main.module.scss} (75%) diff --git a/package-lock.json b/package-lock.json index 11ab89f..718f077 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@nivo/bar": "^0.83.0", "@nivo/core": "^0.83.0", "@nivo/line": "^0.83.0", + "@nivo/pie": "^0.83.0", "@nivo/radar": "^0.83.0", "@reduxjs/toolkit": "^1.9.5", "axios": "^1.4.0", @@ -3727,6 +3728,21 @@ "react": ">= 16.14.0 < 19.0.0" } }, + "node_modules/@nivo/arcs": { + "version": "0.83.0", + "resolved": "https://registry.npmjs.org/@nivo/arcs/-/arcs-0.83.0.tgz", + "integrity": "sha512-UcbNbtp28lbI5V/Sm6TIgYzZmtuhSxW3eTma+YBsgXi1AN/THSwEg0gSV8owyDT/8kaL+jcBQ6c54gzSLClhkw==", + "dependencies": { + "@nivo/colors": "0.83.0", + "@nivo/core": "0.83.0", + "@react-spring/web": "9.4.5 || ^9.7.2", + "@types/d3-shape": "^2.0.0", + "d3-shape": "^1.3.5" + }, + "peerDependencies": { + "react": ">= 16.14.0 < 19.0.0" + } + }, "node_modules/@nivo/axes": { "version": "0.83.0", "resolved": "https://registry.npmjs.org/@nivo/axes/-/axes-0.83.0.tgz", @@ -3853,6 +3869,23 @@ "react": ">= 16.14.0 < 19.0.0" } }, + "node_modules/@nivo/pie": { + "version": "0.83.0", + "resolved": "https://registry.npmjs.org/@nivo/pie/-/pie-0.83.0.tgz", + "integrity": "sha512-98j/h4T/QmQ10gFh1cMh6uLfcGurFcYZN97Lu3ig3D9bbsLuLgpUED/d5O+8w7qLJtnlg3zptqy+N9UgRAqbOg==", + "dependencies": { + "@nivo/arcs": "0.83.0", + "@nivo/colors": "0.83.0", + "@nivo/core": "0.83.0", + "@nivo/legends": "0.83.0", + "@nivo/tooltip": "0.83.0", + "@types/d3-shape": "^2.0.0", + "d3-shape": "^1.3.5" + }, + "peerDependencies": { + "react": ">= 16.14.0 < 19.0.0" + } + }, "node_modules/@nivo/radar": { "version": "0.83.0", "resolved": "https://registry.npmjs.org/@nivo/radar/-/radar-0.83.0.tgz", @@ -22515,6 +22548,18 @@ "prop-types": "^15.7.2" } }, + "@nivo/arcs": { + "version": "0.83.0", + "resolved": "https://registry.npmjs.org/@nivo/arcs/-/arcs-0.83.0.tgz", + "integrity": "sha512-UcbNbtp28lbI5V/Sm6TIgYzZmtuhSxW3eTma+YBsgXi1AN/THSwEg0gSV8owyDT/8kaL+jcBQ6c54gzSLClhkw==", + "requires": { + "@nivo/colors": "0.83.0", + "@nivo/core": "0.83.0", + "@react-spring/web": "9.4.5 || ^9.7.2", + "@types/d3-shape": "^2.0.0", + "d3-shape": "^1.3.5" + } + }, "@nivo/axes": { "version": "0.83.0", "resolved": "https://registry.npmjs.org/@nivo/axes/-/axes-0.83.0.tgz", @@ -22618,6 +22663,20 @@ "prop-types": "^15.7.2" } }, + "@nivo/pie": { + "version": "0.83.0", + "resolved": "https://registry.npmjs.org/@nivo/pie/-/pie-0.83.0.tgz", + "integrity": "sha512-98j/h4T/QmQ10gFh1cMh6uLfcGurFcYZN97Lu3ig3D9bbsLuLgpUED/d5O+8w7qLJtnlg3zptqy+N9UgRAqbOg==", + "requires": { + "@nivo/arcs": "0.83.0", + "@nivo/colors": "0.83.0", + "@nivo/core": "0.83.0", + "@nivo/legends": "0.83.0", + "@nivo/tooltip": "0.83.0", + "@types/d3-shape": "^2.0.0", + "d3-shape": "^1.3.5" + } + }, "@nivo/radar": { "version": "0.83.0", "resolved": "https://registry.npmjs.org/@nivo/radar/-/radar-0.83.0.tgz", diff --git a/package.json b/package.json index 4ec24d4..03e6898 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@nivo/bar": "^0.83.0", "@nivo/core": "^0.83.0", "@nivo/line": "^0.83.0", + "@nivo/pie": "^0.83.0", "@nivo/radar": "^0.83.0", "@reduxjs/toolkit": "^1.9.5", "axios": "^1.4.0", diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx index 2a78cdb..da40694 100644 --- a/src/components/App/App.tsx +++ b/src/components/App/App.tsx @@ -38,6 +38,7 @@ export const App = () => { const [events, setEvents] = useState([]); const currentUserInfo = useAppSelector(selectUserInfo); + const buttonCondition = useAppSelector(selectButtonConditions); const role = useAppSelector((state) => state.currentUserSlice.currentUser.role); diff --git a/src/components/EventsMain/EventsMain.tsx b/src/components/EventsMain/EventsMain.tsx index 6b698d2..d028db3 100644 --- a/src/components/EventsMain/EventsMain.tsx +++ b/src/components/EventsMain/EventsMain.tsx @@ -14,8 +14,6 @@ export const EventsMain: React.FC = ({events}) => { setEventsSort(events.slice(0,2)) },[events]); - console.log(eventsSort); - return (

    Предстоящие мероприятия

    diff --git a/src/components/PieChart/PieChart.module.scss b/src/components/PieChart/PieChart.module.scss new file mode 100644 index 0000000..55df15b --- /dev/null +++ b/src/components/PieChart/PieChart.module.scss @@ -0,0 +1,4 @@ +.container { + width: 324px; + height: 280px; +} diff --git a/src/components/PieChart/PieChart.tsx b/src/components/PieChart/PieChart.tsx new file mode 100644 index 0000000..af124e5 --- /dev/null +++ b/src/components/PieChart/PieChart.tsx @@ -0,0 +1,81 @@ +import {ResponsivePie} from "@nivo/pie"; +import styles from './PieChart.module.scss'; +import {TagsInterface} from "@/types.ts"; +import {ReactElement, useEffect, useState} from 'react'; +import {useRequest} from "@/shared/hooks/useRequest.tsx"; +import {getActivities} from "@/shared/api/Api.ts"; + +interface Props { + data: TagsInterface[]; + id: string | number; + widths: any; +} + +interface PieChartDataInterface { + id: string; + label: string; + value: number; +} + +interface PieDataProps { + data: PieChartDataInterface[]; + colors: string[]; +} + +const MyResponsivePie = ({ data, colors }: PieDataProps): ReactElement => ( + `${value}%`} + legends={[ + { + anchor: 'bottom', + direction: 'column', + justify: false, + translateX: -86, + translateY: 70, + itemsSpacing: 0, + itemWidth: 100, + itemHeight: 18, + itemTextColor: '#000', + itemDirection: 'left-to-right', + itemOpacity: 1, + symbolSize: 12, + symbolShape: 'circle', + } + ]} + /> +); + +export const PieChart = ({data, id, widths}: Props): ReactElement => { + const [activities] = useRequest(() => getActivities(id)); + const [pieChartData, setPieChartData] = useState([]); + const [colors, setColors] = useState([]); + + useEffect(() => { + const colorsArr: string[] = []; + if (activities && activities.results.length > 0 && data) { + setPieChartData(data.map((item: TagsInterface, index: number) => ({ + id: item.name, + label: item.name, + value: Number(widths[index]), + })) + ); + + data.forEach((item) => { + colorsArr.push(item.color); + }) + setColors(colorsArr); + } + }, [activities, data, widths]); + + return ( +
    + {pieChartData.length !== 0 && colors.length !== 0 && } +
    + ); +}; diff --git a/src/components/RoutineSlider/RoutineSlider.tsx b/src/components/RoutineSlider/RoutineSlider.tsx index 65715ab..04100e6 100644 --- a/src/components/RoutineSlider/RoutineSlider.tsx +++ b/src/components/RoutineSlider/RoutineSlider.tsx @@ -1,35 +1,49 @@ -import { useEffect, useRef, useState } from 'react'; -import { useRequest } from "@/shared/hooks/useRequest.tsx"; -import { getActivityTypes } from "@/shared/api/Api.ts"; +import {ReactElement, useEffect, useRef, useState} from 'react'; import { RoutineSection } from "@/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx"; import { getPercentage, limitNumberWithinRange, nearestN } from "@/components/RoutineSlider/RoutineSlider.helpers.ts"; import classes from './routineslider.module.scss'; import {ButtonsList} from "@/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx"; - -interface TagsInterface { - id: number; - name: string; - description: string; - key: number; - color: string; +import * as Api from "@/shared/api/Api.ts"; +import {TagsInterface} from "@/types.ts"; + +interface Props { + data: TagsInterface[]; + handleTags: (data: TagsInterface[]) => void; + handleWidths: (data: number[]) => void; + tags: TagsInterface[]; + widths: number[]; } -export const RoutineSlider = () => { - const [data] = useRequest(getActivityTypes); - const [widths, setWidths] = useState([]); +export const RoutineSlider = ({data, handleTags, handleWidths, widths, tags}: Props): ReactElement => { const RoutineSliderRef = useRef(null); - const [tags, setTags] = useState([]); + const [isButtonDisabled, setIsButtonDisabled] = useState(true); useEffect(() => { if (data) { - setWidths(new Array(data.length).fill(100 / data.length)); - setTags(data); + handleWidths(new Array(data.length).fill(100 / data.length)); + handleTags(data); } }, [data]); const handleCancelButton = () => { - setTags(data) - setWidths(new Array(data.length).fill(100 / data.length)) + handleTags(data) + handleWidths(new Array(data.length).fill(100 / data.length)) + } + + async function handleSendActivities() { + const activities = tags.map((item, index) => ({ + type: item.id, + percentage: widths[index] + })); + const emptyActivities = data.filter(item => !tags.includes(item)).map((item) => ({ + type: item.id, + percentage: 0 + })); + try { + await Api.sendActivities(activities.concat(emptyActivities)); + } catch (err: any) { + console.log(err); + } } return ( @@ -87,18 +101,19 @@ export const RoutineSlider = () => { if (_widths[index] === 0) { _widths[nextSectionIndex] = maxPercent; _widths.splice(index, 1); - setTags(tags.filter((_, i) => i !== index)); + handleTags(tags.filter((_, i) => i !== index)); removeEventListener(); } if (_widths[nextSectionIndex] === 0) { _widths[index] = maxPercent; _widths.splice(nextSectionIndex, 1); - setTags(tags.filter((_, i) => i !== nextSectionIndex)); + handleTags(tags.filter((_, i) => i !== nextSectionIndex)); removeEventListener(); } } - setWidths(_widths); + handleWidths(_widths); + setIsButtonDisabled(false); }; window.addEventListener("pointermove", resize); @@ -122,7 +137,7 @@ export const RoutineSlider = () => { /> ))}
    - +
    ); }; diff --git a/src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx b/src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx index 436bc3e..af135f1 100644 --- a/src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx +++ b/src/components/RoutineSlider/components/ButtonsList/ButtonsList.tsx @@ -4,19 +4,25 @@ import {ReactElement} from "react"; interface Props { handleCancelButton: () => void; + handleSendActivities: () => void; + disabled: boolean; } -export const ButtonsList = ({handleCancelButton}: Props): ReactElement => { +export const ButtonsList = ({handleCancelButton, handleSendActivities, disabled}: Props): ReactElement => { + return (
    ); diff --git a/src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss index cc3c867..90b66f5 100644 --- a/src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss +++ b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.module.scss @@ -9,7 +9,11 @@ box-sizing: border-box; padding: 10px 0 15px; border-right: 4px solid white; + &:first-of-type { + border-radius: 20px 0 0 20px; + } &:last-of-type { + border-radius: 0 20px 20px 0; border-right: none; } &-text { diff --git a/src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx index 3094480..a74ddac 100644 --- a/src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx +++ b/src/components/RoutineSlider/components/RoutineSection/RoutineSection.tsx @@ -15,6 +15,8 @@ export const RoutineSection = ({ width, onSliderSelect }: RoutineSectionProps) => { + + return (
    = ({events}) => { +export const Main = ({events}: Props): ReactElement | null => { const isOnline = useOnlineCheck(); + const [activitiesData] = useRequest(getActivityTypes); + const currentUser = useAppSelector(selectUserInfo); + const [tagsOfPieChart, setTagsOfPieChart] = useState([]); + const [widthsOfPieChart, setWidthsOfPieChart] = useState([]); const articles: ArticleInterface[] = [ { @@ -39,45 +49,60 @@ export const Main: React.FC = ({events}) => { }, ]; - return ( -
    - - {isOnline ? -
    -
    -
    - - -
    -
    -

    Оцените свое настроение сегодня

    -
    - - - - - -
    -
    - -
    - -
    здесь будет круговая диаграмма
    -
    -
    - -
    здесь будет кнопка для скачивания аналитики
    -
    -
    - - -
    -
    -
    - : } -
    - ) + const handleTagsOfPieChart = (data: TagsInterface[]) => { + setTagsOfPieChart(data); + } + + const handleWidthsOfPieChart = (data: number[]) => { + setWidthsOfPieChart(data) + } + + if(activitiesData) { + return ( +
    + + {isOnline ? +
    +
    +
    + + +
    +
    +

    Оцените свое настроение сегодня

    +
    + + + + + +
    +
    + +
    + +
    +

    Деятельность

    + +
    +
    +
    + +
    здесь будет кнопка для скачивания аналитики
    +
    +
    + + +
    +
    +
    + : } +
    + ) + } else { + return null; + } }; diff --git a/src/pages/main/main.module.css b/src/pages/main/main.module.scss similarity index 75% rename from src/pages/main/main.module.css rename to src/pages/main/main.module.scss index 7898463..b321d27 100644 --- a/src/pages/main/main.module.css +++ b/src/pages/main/main.module.scss @@ -31,10 +31,17 @@ } .pie-chart { - width: 324px; - height: 328px; - border-radius: 20px; - background-color: white; + &-container { + width: 324px; + height: 328px; + border-radius: 20px; + background-color: white; + padding: 16px 20px; + } + &-title { + margin: 0 0 25px 0; + font: var(--font-h3); + } } .analytics { diff --git a/src/shared/api/Api.ts b/src/shared/api/Api.ts index 7245ef6..65cfb94 100644 --- a/src/shared/api/Api.ts +++ b/src/shared/api/Api.ts @@ -1,5 +1,12 @@ import axios from "axios"; -import {EventInterface, SubmitArguments, UserConditionForSend, UserInfo, WheelResults} from "@/types"; +import { + ActivityInterface, + EventInterface, + SubmitArguments, + UserConditionForSend, + UserInfo, + WheelResults +} from "@/types"; import {BASE_URL_REQUEST, BASE_URL_WSS} from "../constants"; // const BASE_URL = "https://em-dev.usolcev.com/api/v1"; @@ -358,3 +365,24 @@ export const getActivityTypes = () => { }); }; +export const getActivities = (id: string | number) => { + return axios.get(`${BASE_URL_REQUEST}/metrics/activities/?employee=${id}`, { + headers: { + authorization: `Bearer ${localStorage.getItem("jwt")}`, + }, + }); +}; + +export const sendActivities = (activities: ActivityInterface[]) => { + return axios.post( + `${BASE_URL_REQUEST}/metrics/activities`, { + activity_rates: activities + }, + { + headers: { + authorization: `Bearer ${localStorage.getItem("jwt")}`, + }, + } + ); +}; + diff --git a/src/shared/ui/Button/button.module.scss b/src/shared/ui/Button/button.module.scss index 964446d..f3e4e3f 100644 --- a/src/shared/ui/Button/button.module.scss +++ b/src/shared/ui/Button/button.module.scss @@ -51,6 +51,11 @@ border-color: var(--color-accent-secondary); color: var(--color-accent-secondary); } + &:disabled { + border-color: var(--color-accent-purple); + color: var(--color-accent-purple); + } + } &-empty { @@ -72,6 +77,7 @@ &:disabled { cursor: auto; opacity: 0.64; + color: var(--color-accent-purple); } } @@ -87,8 +93,4 @@ .disabled { cursor: auto; opacity: 0.64; - - &:hover { - background-color: var(--color-accent-purple) - } } diff --git a/src/types.ts b/src/types.ts index 0803ea2..7e30470 100644 --- a/src/types.ts +++ b/src/types.ts @@ -350,3 +350,16 @@ export interface DataBurnOutInterface { degress: number, } + +export interface ActivityInterface { + type: number; + percentage: number; +} + +export interface TagsInterface { + id: number; + name: string; + description: string; + key: number; + color: string; +} From 4f89475a9e4f2fffb56d722e2b54e6b0ecb85d93 Mon Sep 17 00:00:00 2001 From: Kirill Kurentsov Date: Wed, 26 Jul 2023 21:34:24 +0300 Subject: [PATCH 03/90] fix: landing page v3 with widescreen support and FAQ --- src/assets/audience_chef.jpg | Bin 0 -> 25229 bytes src/assets/audience_chef.png | Bin 0 -> 34133 bytes src/assets/audience_employee.png | Bin 0 -> 36995 bytes src/assets/audience_hr.jpg | Bin 0 -> 26441 bytes src/assets/audience_hr.png | Bin 0 -> 34045 bytes src/assets/hero_screenshot.png | Bin 0 -> 83413 bytes src/assets/hero_wheel.png | Bin 0 -> 25882 bytes src/assets/logo_MoodBeat_bl.svg | 1 + src/index.css | 1 + src/pages/landing/LandingPage.module.scss | 143 +++++---- src/pages/landing/LandingPage.tsx | 375 ++++++++++++---------- 11 files changed, 287 insertions(+), 233 deletions(-) create mode 100644 src/assets/audience_chef.jpg create mode 100644 src/assets/audience_chef.png create mode 100644 src/assets/audience_employee.png create mode 100644 src/assets/audience_hr.jpg create mode 100644 src/assets/audience_hr.png create mode 100644 src/assets/hero_screenshot.png create mode 100644 src/assets/hero_wheel.png create mode 100644 src/assets/logo_MoodBeat_bl.svg diff --git a/src/assets/audience_chef.jpg b/src/assets/audience_chef.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cf382bd468925418e83e52bff691a616366272e9 GIT binary patch literal 25229 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
    + Date: Fri, 28 Jul 2023 23:05:09 +0300 Subject: [PATCH 20/90] fix_bug_build --- src/components/Myteam/Myteam.tsx | 66 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/components/Myteam/Myteam.tsx b/src/components/Myteam/Myteam.tsx index 2548b24..baf2952 100644 --- a/src/components/Myteam/Myteam.tsx +++ b/src/components/Myteam/Myteam.tsx @@ -1,7 +1,7 @@ import styles from "./myteam.module.css"; import React, { useState, useEffect } from "react"; import { Navbar } from "@/components/Navbar/Navbar"; -import { Articles } from "@/components/Articles/Articles"; +// import { Articles } from "@/components/Articles/Articles"; import { Employees } from "../Employees/Employees"; import { ArticleInterface, EmployeeInterface } from "@/types"; import { Button } from "@/shared/ui/Button/Button"; @@ -24,38 +24,38 @@ export const Myteam: React.FC = ({ employees, takeNewEmployeesList }) => { - const articles: ArticleInterface[] = [ - { - type: "видео", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - { - type: "видео", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - { - type: "видео", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - { - type: "видео", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - { - type: "видео", - title: "Как понять, что у вас профессиональное выгорание", - length: "5 минут", - banner: "/image.png", - }, - ]; + // const articles: ArticleInterface[] = [ + // { + // type: "видео", + // title: "Как понять, что у вас профессиональное выгорание", + // length: "5 минут", + // banner: "/image.png", + // }, + // { + // type: "видео", + // title: "Как понять, что у вас профессиональное выгорание", + // length: "5 минут", + // banner: "/image.png", + // }, + // { + // type: "видео", + // title: "Как понять, что у вас профессиональное выгорание", + // length: "5 минут", + // banner: "/image.png", + // }, + // { + // type: "видео", + // title: "Как понять, что у вас профессиональное выгорание", + // length: "5 минут", + // banner: "/image.png", + // }, + // { + // type: "видео", + // title: "Как понять, что у вас профессиональное выгорание", + // length: "5 минут", + // banner: "/image.png", + // }, + // ]; const isOnline = useOnlineCheck(); const navigate = useNavigate(); From cff4cc055cb3222427ea473a3fcc754cfca0a762 Mon Sep 17 00:00:00 2001 From: Alix2019 Date: Fri, 28 Jul 2023 23:09:28 +0300 Subject: [PATCH 21/90] fix_bug_build --- src/components/Myteam/Myteam.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/Myteam/Myteam.tsx b/src/components/Myteam/Myteam.tsx index baf2952..e07df84 100644 --- a/src/components/Myteam/Myteam.tsx +++ b/src/components/Myteam/Myteam.tsx @@ -3,7 +3,10 @@ import React, { useState, useEffect } from "react"; import { Navbar } from "@/components/Navbar/Navbar"; // import { Articles } from "@/components/Articles/Articles"; import { Employees } from "../Employees/Employees"; -import { ArticleInterface, EmployeeInterface } from "@/types"; +import { + // ArticleInterface, + EmployeeInterface +} from "@/types"; import { Button } from "@/shared/ui/Button/Button"; import { PopupWithBackground } from "@/shared/ui/PopupWithBackground/PopupWithBackground"; import { BadInternetConnection } from "../BadInternetConnection/BadInternetConnection"; From eb8b88de98632b343012d9af9012bbb4e477d307 Mon Sep 17 00:00:00 2001 From: Kirill Kurentsov Date: Sat, 29 Jul 2023 09:58:56 +0300 Subject: [PATCH 22/90] fix: refactor NotificationPopup to remove endless refresh state loop --- .../NotificationPopup/NotificationPopup.tsx | 29 ++++++++----------- src/index.css | 1 + .../components/Interests/Interests.tsx | 4 ++- .../components/PeriodPicker.module.scss | 4 +-- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/components/NotificationPopup/NotificationPopup.tsx b/src/components/NotificationPopup/NotificationPopup.tsx index d61aab1..25282cb 100644 --- a/src/components/NotificationPopup/NotificationPopup.tsx +++ b/src/components/NotificationPopup/NotificationPopup.tsx @@ -1,5 +1,5 @@ import styles from "./NotificationPopup.module.css"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useState, useCallback } from "react"; import SettingsIcon from "./settings_20.svg"; import NotificationIcon from "./notification_28.svg"; import { useNavigate } from "react-router-dom"; @@ -21,7 +21,6 @@ export const NotificationPopup: React.FC = ({ events, }) => { const notifications = useAppSelector(selectNotifications); - const [displayedDate, setDisplayedDate] = useState({ date: new Date() }); const [displayedDateText, setDisplayedDateText] = useState(""); const navigate = useNavigate(); const ref = useRef(null); @@ -38,7 +37,7 @@ export const NotificationPopup: React.FC = ({ useEscapeKey(closeNotificationPopup); useOutsideClick(closeNotificationPopup, ref); - useEffect(() => { + const handleNotificationChange = useCallback(() => { if ( notifications && notifications.filter((x) => x.incident_type === "Событие").length > 0 @@ -55,32 +54,28 @@ export const NotificationPopup: React.FC = ({ }); // Определяем дату ближайшего непросмотренного мероприятия + let tempDate = new Date(0); eventsToCheck.map((x, i) => { - if (i === 0) setDisplayedDate({ date: x.start_time }); - if (x.start_time < displayedDate.date) - setDisplayedDate({ date: x.start_time }); + if (i === 0) tempDate = x.start_time; + if (x.start_time < tempDate) tempDate = x.start_time; }); - if (typeof displayedDate.date === "string") { + if (typeof tempDate === "string") { setDisplayedDateText( - new Date(displayedDate.date).toLocaleDateString("ru-RU", { + new Date(tempDate).toLocaleDateString("ru-RU", { day: "numeric", month: "long", hour: "2-digit", minute: "2-digit", }) ); - console.log( - `${new Date(displayedDate.date).toLocaleDateString("ru-RU", { - day: "numeric", - month: "long", - hour: "2-digit", - minute: "2-digit", - })}` - ); } } - }, [events, notifications, displayedDate.date]); + }, [events, notifications]); + + useEffect(() => { + handleNotificationChange(); + }, [handleNotificationChange]); return (