From cde8c845e9288f49a9608d9c79960aedc9554198 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Fri, 16 Sep 2022 15:50:24 +0300 Subject: [PATCH 1/2] TCA-440 - add slider on homepage with user's latest progress --- .../in-progress/InProgress.module.scss | 8 +- .../progress-block/ProgressBlock.module.scss | 6 +- .../cards-slider/CardsSlider.module.scss | 63 +++++++++++ .../cards-slider/CardsSlider.tsx | 49 +++++++++ .../progress-block/cards-slider/index.ts | 1 + .../progress-action/ProgressAction.tsx | 103 ++++++++---------- 6 files changed, 166 insertions(+), 64 deletions(-) create mode 100644 src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.module.scss create mode 100644 src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx create mode 100644 src-ts/tools/learn/welcome/progress-block/cards-slider/index.ts diff --git a/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss b/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss index 1b525b6fd..152d7f6fb 100644 --- a/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss +++ b/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.module.scss @@ -8,10 +8,6 @@ display: flex; - &.large { - padding: $space-xxxxl; - } - @include ltelg { &, &.large { padding: $space-lg; @@ -119,8 +115,8 @@ .started-date { font-weight: bold; - + @include ltemd { order: -1; } -} \ No newline at end of file +} diff --git a/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss b/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss index 167346070..354f50713 100644 --- a/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss +++ b/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss @@ -4,14 +4,14 @@ .wrap { background: $black-5; border-radius: $space-sm; - padding: $space-xxl; + padding: $space-xxl $space-xxl $space-lg; color: $black-100; display: flex; flex-direction: column; - gap: $space-lg; + gap: $space-xxl; width: 100%; - + @include ltemd { padding: $space-lg; } diff --git a/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.module.scss b/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.module.scss new file mode 100644 index 000000000..f54fe4bcb --- /dev/null +++ b/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.module.scss @@ -0,0 +1,63 @@ +@import '../../../../../lib/styles/includes'; + +.slides-wrap { + display: block; + position: relative; + z-index: 1; + overflow: hidden; +} + +.slide { + position: absolute; + top: 0; + left: 0; + width: 100%; + + opacity: 0; + visibility: hidden; + transition: 0.2s ease; + &:global(:not(.active)) { + pointer-events: none; + } + + + &:global(.is-prev) { + transform: translateX(-100%); + } + + &:global(.is-next) { + transform: translateX(100%); + } + + &:global(.active) { + position: relative; + opacity: 1; + transform: translateX(0); + visibility: visible; + } +} + +.nav-wrap { + display: flex; + align-items: center; + justify-content: center; + margin-top: $space-xxl; + + gap: calc($space-xs + $border-xs); +} + +.nav-dot { + display: block; + width: $space-md; + height: $space-md; + background: $black-40; + border-radius: 50%; + cursor: pointer; + + &:global(.active) { + width: calc($space-lg + $border); + height: calc($space-lg + $border); + border: $border solid $turq-100; + background: $tc-white; + } +} diff --git a/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx b/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx new file mode 100644 index 000000000..e41f99aab --- /dev/null +++ b/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx @@ -0,0 +1,49 @@ +import classNames from 'classnames' +import { fill } from 'lodash' +import { Children, Dispatch, FC, ReactNode, SetStateAction, useState } from 'react' + +import styles from './CardsSlider.module.scss' + +interface CardsSliderProps { + children: Array +} + +const CardsSlider: FC = (props: CardsSliderProps) => { + const [activeSlide, setActiveSlide]: [number, Dispatch>] = useState(2) + + const wrapSlides: (children: Array) => Array = (children: Array) => { + return Children.map(children, (child, index) => ( +
index && 'is-prev', + activeSlide < index && 'is-next', + ) + } + > + {child} +
+ )) as Array + } + + return ( +
+
+ {wrapSlides(props.children)} +
+
+ {fill(Array(props.children.length), '').map((_, i) => ( + setActiveSlide(i)} + /> + ))} +
+
+ ) +} + +export default CardsSlider diff --git a/src-ts/tools/learn/welcome/progress-block/cards-slider/index.ts b/src-ts/tools/learn/welcome/progress-block/cards-slider/index.ts new file mode 100644 index 000000000..f2113ef20 --- /dev/null +++ b/src-ts/tools/learn/welcome/progress-block/cards-slider/index.ts @@ -0,0 +1 @@ +export { default as CardsSlider } from './CardsSlider' diff --git a/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.tsx b/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.tsx index 3eb8997ec..9de579e3b 100644 --- a/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.tsx +++ b/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.tsx @@ -1,15 +1,18 @@ +import { orderBy } from 'lodash' import { FC, ReactNode, useMemo } from 'react' import { Button } from '../../../../../lib' import { LearnCertification, - LearningHat, + LearnUserCertificationProgress, MyCourseCompletedCard, MyCourseInProgressCard, UserCertificationCompleted, UserCertificationInProgress, + UserCertificationProgressStatus, } from '../../../learn-lib' import { LEARN_PATHS } from '../../../learn.routes' +import { CardsSlider } from '../cards-slider' import styles from './ProgressAction.module.scss' @@ -19,6 +22,12 @@ interface ProgressActionProps { userInProgressCertifications: ReadonlyArray } +function isCompleted(cert: LearnUserCertificationProgress): boolean { + return cert.status === UserCertificationProgressStatus.completed +} + +const USER_PROGRESS_MAX_SLIDES_COUNT: number = 8 + const ProgressAction: FC = (props: ProgressActionProps) => { const { @@ -45,72 +54,56 @@ const ProgressAction: FC = (props: ProgressActionProps) => }, {} as unknown as { [key: string]: LearnCertification }) ), [allCertifications]) - // we only want to display the last course that was acted upon - const mostRecentIsCompleted: boolean = myCompletedCertifications?.[0]?.updatedAt > (myInProgressCertifications?.[0]?.updatedAt || 0) - - function renderInProgress(): JSX.Element { - - // if the most recently acted upon course is completed and not in progress, - // or there are no courses in progress, don't show this block - if (mostRecentIsCompleted || !myInProgressCertifications.length) { - return <> - } - - const courseToDisplay: UserCertificationInProgress = myInProgressCertifications[0] + const recentlyUpdatedCertifications: Array = orderBy([ + ...myCompletedCertifications, + ...myInProgressCertifications, + ], 'updatedAt', 'desc').slice(0, USER_PROGRESS_MAX_SLIDES_COUNT) + function renderInProgress(courseToDisplay: UserCertificationInProgress): JSX.Element { return ( - <> -
-

In progress

- - {allMyLearningsLink} - -
- - + ) } - function renderCompleted(): JSX.Element { + function renderCompleted(certToDisplay: UserCertificationCompleted): JSX.Element { + return ( + + ) + } - // if the most recently acted upon course is in progress rather than completed, - // or there are no completed courses, don't show this block - if (!mostRecentIsCompleted || !myCompletedCertifications.length) { - return <> + function renderCertificateCards(): Array { + if (!recentlyUpdatedCertifications.length) { + return [] } - const certToDisplay: UserCertificationCompleted = myCompletedCertifications[0] - - return ( - <> -
-
- -

Congratulations!

-
- - {allMyLearningsLink} - -
- - - ) + return recentlyUpdatedCertifications.map((cert) => ( + isCompleted(cert) + ? renderCompleted(cert as UserCertificationCompleted) + : renderInProgress(cert as UserCertificationInProgress) + )) } return ( <> - {renderInProgress()} - {renderCompleted()} +
+

My progress

+ + {allMyLearningsLink} + +
+ + {renderCertificateCards()} + {allMyLearningsLink} From dbeb9ad6f5e8bd3e04bbbed17366b4c2bb305034 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Fri, 16 Sep 2022 16:31:05 +0300 Subject: [PATCH 2/2] update default active slider --- .../learn/welcome/progress-block/cards-slider/CardsSlider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx b/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx index e41f99aab..d8b4f8f29 100644 --- a/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx +++ b/src-ts/tools/learn/welcome/progress-block/cards-slider/CardsSlider.tsx @@ -9,7 +9,7 @@ interface CardsSliderProps { } const CardsSlider: FC = (props: CardsSliderProps) => { - const [activeSlide, setActiveSlide]: [number, Dispatch>] = useState(2) + const [activeSlide, setActiveSlide]: [number, Dispatch>] = useState(0) const wrapSlides: (children: Array) => Array = (children: Array) => { return Children.map(children, (child, index) => (