diff --git a/src-ts/tools/learn/Learn.tsx b/src-ts/tools/learn/Learn.tsx
index aba5d5288..44b6a5825 100644
--- a/src-ts/tools/learn/Learn.tsx
+++ b/src-ts/tools/learn/Learn.tsx
@@ -2,7 +2,6 @@ import { FC, useContext } from 'react'
import { Outlet, Routes } from 'react-router-dom'
import {
- ContentLayout,
routeContext,
RouteContextData,
} from '../../lib'
diff --git a/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx b/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx
index da2f33abe..b30e16970 100755
--- a/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx
+++ b/src-ts/tools/learn/course-completed/CourseCompletedPage.tsx
@@ -11,16 +11,16 @@ import {
ProfileContextData
} from '../../../lib'
import {
- CertificationsProviderData,
+ AllCertificationsProviderData,
CollapsiblePane,
CourseOutline,
CoursesProviderData,
CourseTitle,
- MyCertificationProgressProviderData,
- MyCertificationProgressStatus,
- useCertificationsProvider,
- useCoursesProvider,
- useMyCertificationProgress
+ useAllCertifications,
+ useCourses,
+ UserCertificationProgressProviderData,
+ UserCertificationProgressStatus,
+ useUserCertificationProgress
} from '../learn-lib'
import { getCertificatePath, getCoursePath } from '../learn.routes'
@@ -39,12 +39,12 @@ const CourseCompletedPage: FC<{}> = () => {
const {
course: courseData,
ready: courseDataReady,
- }: CoursesProviderData = useCoursesProvider(providerParam, certificationParam)
+ }: CoursesProviderData = useCourses(providerParam, certificationParam)
const {
- certificateProgress: progress,
+ certificationProgress: progress,
ready: progressReady,
- }: MyCertificationProgressProviderData = useMyCertificationProgress(
+ }: UserCertificationProgressProviderData = useUserCertificationProgress(
profile?.userId,
routeParams.provider,
routeParams.certification
@@ -53,7 +53,7 @@ const CourseCompletedPage: FC<{}> = () => {
const {
certification,
ready: certifReady,
- }: CertificationsProviderData = useCertificationsProvider(providerParam, progress?.certificationId, {
+ }: AllCertificationsProviderData = useAllCertifications(providerParam, progress?.certificationId, {
enabled: progressReady && !!progress,
})
@@ -66,9 +66,9 @@ const CourseCompletedPage: FC<{}> = () => {
], [coursePath, courseData])
useEffect(() => {
- if (ready && progress?.status !== MyCertificationProgressStatus.completed) {
- navigate(coursePath)
- }
+ if (ready && progress?.status !== UserCertificationProgressStatus.completed) {
+ navigate(coursePath)
+ }
}, [
coursePath,
navigate,
diff --git a/src-ts/tools/learn/course-details/CourseDetailsPage.tsx b/src-ts/tools/learn/course-details/CourseDetailsPage.tsx
index 0dc41b16d..0cee9f3e8 100644
--- a/src-ts/tools/learn/course-details/CourseDetailsPage.tsx
+++ b/src-ts/tools/learn/course-details/CourseDetailsPage.tsx
@@ -13,12 +13,12 @@ import {
import {
CoursesProviderData,
CourseTitle,
- MyCertificationProgressProviderData,
- MyCertificationProgressStatus,
ResourceProviderData,
- useCoursesProvider,
- useMyCertificationProgress,
- useResourceProvider
+ useCourses,
+ UserCertificationProgressProviderData,
+ UserCertificationProgressStatus,
+ useResourceProvider,
+ useUserCertificationProgress
} from '../learn-lib'
import { CourseCurriculum } from './course-curriculum'
@@ -37,12 +37,12 @@ const CourseDetailsPage: FC<{}> = () => {
const {
course,
ready: courseReady,
- }: CoursesProviderData = useCoursesProvider(routeParams.provider ?? '', routeParams.certification)
+ }: CoursesProviderData = useCourses(routeParams.provider ?? '', routeParams.certification)
const {
- certificateProgress: progress,
+ certificationProgress: progress,
ready: progressReady,
- }: MyCertificationProgressProviderData = useMyCertificationProgress(
+ }: UserCertificationProgressProviderData = useUserCertificationProgress(
profile?.userId,
routeParams.provider,
routeParams.certification,
@@ -59,7 +59,7 @@ const CourseDetailsPage: FC<{}> = () => {
return
}
- return progress?.status === MyCertificationProgressStatus.completed ? (
+ return progress?.status === UserCertificationProgressStatus.completed ? (
<>
Suggested next steps
diff --git a/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.tsx b/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.tsx
index 415015ac9..df4e68edf 100644
--- a/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.tsx
+++ b/src-ts/tools/learn/course-details/course-curriculum/CourseCurriculum.tsx
@@ -9,13 +9,18 @@ import {
LearningHat,
LearnLesson,
LearnModule,
- LearnMyCertificationProgress,
- MyCertificationProgressStatus,
- startMyCertificationsProgressAsync,
- UpdateMyCertificateProgressActions,
- updateMyCertificationsProgressAsync
+ LearnUserCertificationProgress,
+ userCertificationProgressStartAsync,
+ UserCertificationProgressStatus,
+ userCertificationProgressUpdateAsync,
+ UserCertificationUpdateProgressActions
} from '../../learn-lib'
-import { authenticateAndStartCourseRoute, getCertificatePath, getFccLessonPath, LEARN_PATHS } from '../../learn.routes'
+import {
+ authenticateAndStartCourseRoute,
+ getCertificatePath,
+ getLessonPathFromCurrentLesson,
+ LEARN_PATHS,
+} from '../../learn.routes'
import styles from './CourseCurriculum.module.scss'
import { CurriculumSummary } from './curriculum-summary'
@@ -24,11 +29,12 @@ import { TcAcademyPolicyModal } from './tc-academy-policy-modal'
interface CourseCurriculumProps {
course: LearnCourse
profile?: UserProfile
- progress?: LearnMyCertificationProgress
+ progress?: LearnUserCertificationProgress
progressReady?: boolean
}
const CourseCurriculum: FC = (props: CourseCurriculumProps) => {
+
const navigate: NavigateFunction = useNavigate()
const [searchParams]: any = useSearchParams()
@@ -36,29 +42,35 @@ const CourseCurriculum: FC = (props: CourseCurriculumProp
const [isTcAcademyPolicyModal, setIsTcAcademyPolicyModal]: [boolean, Dispatch>] = useState(false)
- const status: string = props.progress?.status ?? 'init'
+ const status: string = props.progress?.status ?? UserCertificationProgressStatus.inititialized
const completedPercentage: number = (props.progress?.courseProgressPercentage ?? 0) / 100
- const inProgress: boolean = status === MyCertificationProgressStatus.inProgress || !!props.progress?.currentLesson
- const isCompleted: boolean = status === MyCertificationProgressStatus.completed
+ const inProgress: boolean = status === UserCertificationProgressStatus.inProgress || !!props.progress?.currentLesson
+ const isCompleted: boolean = status === UserCertificationProgressStatus.completed
/**
* Redirect user to the currentLesson if there's already some progress recorded
* otherwise redirect to first module > first lesson
*/
const handleStartCourse: () => void = useCallback(() => {
- const current: Array = (props.progress?.currentLesson ?? '').split('/')
+
const course: LearnCourse = props.course
const module: LearnModule = course.modules[0]
const lesson: LearnLesson = module.lessons[0]
- const lessonPath: string = getFccLessonPath(
+ const lessonPath: string = getLessonPathFromCurrentLesson(
course.provider,
course.certification,
- current[0] || module.meta.dashedName,
- current[1] || lesson.dashedName,
+ props.progress?.currentLesson,
+ module.meta.dashedName,
+ lesson.dashedName,
)
navigate(lessonPath)
- }, [props.course, props.progress, navigate])
+ }, [
+ getLessonPathFromCurrentLesson,
+ navigate,
+ props.course,
+ props.progress,
+ ])
/**
* Handle user click on start course/resume/login button
@@ -97,7 +109,7 @@ const CourseCurriculum: FC = (props: CourseCurriculumProp
}
if (!props.progress?.id) {
- await startMyCertificationsProgressAsync(
+ await userCertificationProgressStartAsync(
props.profile.userId,
props.course.certificationId,
props.course.id,
@@ -107,9 +119,9 @@ const CourseCurriculum: FC = (props: CourseCurriculumProp
}
)
} else {
- await updateMyCertificationsProgressAsync(
+ await userCertificationProgressUpdateAsync(
props.progress.id,
- UpdateMyCertificateProgressActions.acceptHonestyPolicy,
+ UserCertificationUpdateProgressActions.acceptHonestyPolicy,
{}
)
}
@@ -134,9 +146,9 @@ const CourseCurriculum: FC = (props: CourseCurriculumProp
* proceed as if the user just clicked "Start course" button
*/
useEffect(() => {
- if (props.progressReady && isLoggedIn && searchParams.get('start-course') !== null) {
- handleStartCourseClick()
- }
+ if (props.progressReady && isLoggedIn && searchParams.get('start-course') !== null) {
+ handleStartCourseClick()
+ }
}, [handleStartCourseClick, isLoggedIn, props.progressReady, searchParams])
return (
diff --git a/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx b/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx
index 351ab9d26..32d34bd0c 100644
--- a/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx
+++ b/src-ts/tools/learn/free-code-camp/FreeCodeCamp.tsx
@@ -1,4 +1,14 @@
-import { Dispatch, FC, SetStateAction, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useState } from 'react'
+import {
+ Dispatch,
+ FC,
+ SetStateAction,
+ useCallback,
+ useContext,
+ useEffect,
+ useLayoutEffect,
+ useMemo,
+ useState,
+} from 'react'
import { NavigateFunction, Params, useNavigate, useParams } from 'react-router-dom'
import {
@@ -15,16 +25,16 @@ import {
LearnLesson,
LearnModule,
LessonProviderData,
- MyCertificationProgressProviderData,
- MyCertificationProgressStatus,
- startMyCertificationsProgressAsync,
- UpdateMyCertificateProgressActions,
- updateMyCertificationsProgressAsync,
- useCoursesProvider,
+ useCourses,
useLessonProvider,
- useMyCertificationProgress,
+ UserCertificationProgressProviderData,
+ userCertificationProgressStartAsync,
+ UserCertificationProgressStatus,
+ userCertificationProgressUpdateAsync,
+ UserCertificationUpdateProgressActions,
+ useUserCertificationProgress,
} from '../learn-lib'
-import { getCertificationCompletedPath, getCoursePath, getFccLessonPath } from '../learn.routes'
+import { getCertificationCompletedPath, getCoursePath, getLessonPathFromModule } from '../learn.routes'
import { FccFrame } from './fcc-frame'
import styles from './FreeCodeCamp.module.scss'
@@ -46,15 +56,19 @@ const FreeCodeCamp: FC<{}> = () => {
const [lessonParam, setLessonParam]: [string, Dispatch>] = useState(routeParams.lesson ?? '')
const {
- certificateProgress,
+ certificationProgress: certificateProgress,
setCertificateProgress,
ready: progressReady,
- }: MyCertificationProgressProviderData = useMyCertificationProgress(profile?.userId, routeParams.provider, certificationParam)
+ }: UserCertificationProgressProviderData = useUserCertificationProgress(
+ profile?.userId,
+ routeParams.provider,
+ certificationParam
+ )
const {
course: courseData,
ready: courseDataReady,
- }: CoursesProviderData = useCoursesProvider(providerParam, certificationParam)
+ }: CoursesProviderData = useCourses(providerParam, certificationParam)
const { lesson, ready: lessonReady }: LessonProviderData = useLessonProvider(
providerParam,
@@ -71,27 +85,27 @@ const FreeCodeCamp: FC<{}> = () => {
{ url: '/learn/fcc', name: lesson?.module.title ?? '' },
], [providerParam, lesson])
- const currentModuleData: LearnModule|undefined = useMemo(() => {
+ const currentModuleData: LearnModule | undefined = useMemo(() => {
return courseData?.modules.find(d => d.key === moduleParam)
}, [courseData, moduleParam])
const currentStepIndex: number = useMemo(() => {
- if (!currentModuleData) {
- return 0
- }
+ if (!currentModuleData) {
+ return 0
+ }
- const lessonIndex: number = currentModuleData.lessons.findIndex(l => l.dashedName === lessonParam)
- return lessonIndex + 1
+ const lessonIndex: number = currentModuleData.lessons.findIndex(l => l.dashedName === lessonParam)
+ return lessonIndex + 1
}, [currentModuleData, lessonParam])
const handleNavigate: (direction: number) => void = useCallback((direction = 1) => {
- const nextStep: LearnLesson|undefined = currentModuleData?.lessons[(currentStepIndex - 1) + direction]
+ const nextStep: LearnLesson | undefined = currentModuleData?.lessons[(currentStepIndex - 1) + direction]
if (!nextStep) {
return
}
- const lessonPath: string = getFccLessonPath(
+ const lessonPath: string = getLessonPathFromModule(
providerParam,
certificationParam,
moduleParam,
@@ -108,12 +122,19 @@ const FreeCodeCamp: FC<{}> = () => {
])
function updatePath(lessonPath: string, modulePath: string, coursePath: string): void {
- if (coursePath !== certificationParam) { setCourseParam(coursePath) }
- if (modulePath !== moduleParam) { setModuleParam(modulePath) }
- if (lessonPath !== lessonParam) { setLessonParam(lessonPath) }
+
+ if (coursePath !== certificationParam) {
+ setCourseParam(coursePath)
+ }
+ if (modulePath !== moduleParam) {
+ setModuleParam(modulePath)
+ }
+ if (lessonPath !== lessonParam) {
+ setLessonParam(lessonPath)
+ }
if (lessonPath !== lessonParam || modulePath !== moduleParam || coursePath !== certificationParam) {
- const nextLessonPath: string = getFccLessonPath(
+ const nextLessonPath: string = getLessonPathFromModule(
providerParam,
coursePath,
modulePath,
@@ -124,10 +145,11 @@ const FreeCodeCamp: FC<{}> = () => {
}
function handleFccLessonReady(lessonPath: string): void {
+
const [nLessonPath, modulePath, coursePath]: Array = lessonPath.replace(/\/$/, '').split('/').reverse()
updatePath(nLessonPath, modulePath, coursePath)
- const currentLesson: {[key: string]: string} = {
+ const currentLesson: { [key: string]: string } = {
lesson: nLessonPath,
module: modulePath,
}
@@ -141,7 +163,7 @@ const FreeCodeCamp: FC<{}> = () => {
}
if (!certificateProgress) {
- startMyCertificationsProgressAsync(
+ userCertificationProgressStartAsync(
profile.userId,
lesson.course.certificationId,
lesson.course.id,
@@ -151,51 +173,51 @@ const FreeCodeCamp: FC<{}> = () => {
// TODO: remove this delay!!
// TEMP_FIX: delay this api call to allow for previous "completeLesson" call to write in the api
setTimeout(() => {
- updateMyCertificationsProgressAsync(
- certificateProgress.id,
- UpdateMyCertificateProgressActions.currentLesson,
- currentLesson
- )
+ userCertificationProgressUpdateAsync(
+ certificateProgress.id,
+ UserCertificationUpdateProgressActions.currentLesson,
+ currentLesson
+ )
.then(setCertificateProgress)
}, 500)
}
}
function handleFccLessonComplete(): void {
- const currentLesson: {[key: string]: string} = {
+ const currentLesson: { [key: string]: string } = {
lesson: lessonParam,
module: moduleParam,
}
if (certificateProgress) {
- updateMyCertificationsProgressAsync(
+ userCertificationProgressUpdateAsync(
certificateProgress.id,
- UpdateMyCertificateProgressActions.completeLesson,
+ UserCertificationUpdateProgressActions.completeLesson,
currentLesson
).then(setCertificateProgress)
}
}
useEffect(() => {
- if (
- certificateProgress &&
- certificateProgress.courseProgressPercentage === 100 &&
- certificateProgress.status === MyCertificationProgressStatus.inProgress
- ) {
- updateMyCertificationsProgressAsync(
- certificateProgress.id,
- UpdateMyCertificateProgressActions.completeCertificate,
- {}
- )
- .then(setCertificateProgress)
- .then(() => {
- const completedPath: string = getCertificationCompletedPath(
- providerParam,
- certificationParam
- )
+ if (
+ certificateProgress &&
+ certificateProgress.courseProgressPercentage === 100 &&
+ certificateProgress.status === UserCertificationProgressStatus.inProgress
+ ) {
+ userCertificationProgressUpdateAsync(
+ certificateProgress.id,
+ UserCertificationUpdateProgressActions.completeCertificate,
+ {}
+ )
+ .then(setCertificateProgress)
+ .then(() => {
+ const completedPath: string = getCertificationCompletedPath(
+ providerParam,
+ certificationParam
+ )
- navigate(completedPath)
- })
- }
+ navigate(completedPath)
+ })
+ }
}, [
certificateProgress,
certificationParam,
diff --git a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/certification.store.ts b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/all-certifications.store.ts
similarity index 92%
rename from src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/certification.store.ts
rename to src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/all-certifications.store.ts
index b0e8f3cbb..e42c28e5f 100755
--- a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/certification.store.ts
+++ b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/all-certifications.store.ts
@@ -3,7 +3,7 @@ import { getPath } from '../../learn-url.config'
import { LearnCertification } from './learn-certification.model'
-export function getCertificationsAsync(
+export function getAsync(
providerName: string = 'freeCodeCamp',
certificationId?: string
): Promise> {
diff --git a/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/index.ts b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/index.ts
new file mode 100755
index 000000000..4e1ec9d24
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/index.ts
@@ -0,0 +1,4 @@
+export {
+ getAsync as allCertificationsGetAsync,
+} from './all-certifications.store'
+export * from './learn-certification.model'
diff --git a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/learn-certification.model.ts b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/learn-certification.model.ts
similarity index 83%
rename from src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/learn-certification.model.ts
rename to src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/learn-certification.model.ts
index 6bd6ca18e..6104d6201 100644
--- a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/learn-certification.model.ts
+++ b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-functions/learn-certification.model.ts
@@ -5,6 +5,6 @@ export interface LearnCertification {
key: string
providerId: string
providerName: string
- state: string
+ state: 'active' | 'coming-soon'
title: string
}
diff --git a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-provider-data.model.ts b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-provider-data.model.ts
similarity index 57%
rename from src-ts/tools/learn/learn-lib/certifications-provider/certifications-provider-data.model.ts
rename to src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-provider-data.model.ts
index a7851fd88..cc5d28762 100755
--- a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-provider-data.model.ts
+++ b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications-provider-data.model.ts
@@ -1,6 +1,6 @@
-import { LearnCertification } from './certifications-functions'
+import { LearnCertification } from './all-certifications-functions'
-export interface CertificationsProviderData {
+export interface AllCertificationsProviderData {
certification?: LearnCertification
certifications: Array
certificationsCount: number
diff --git a/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications.provider.tsx b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications.provider.tsx
new file mode 100644
index 000000000..c68739ee4
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/all-certifications-provider/all-certifications.provider.tsx
@@ -0,0 +1,50 @@
+import { Dispatch, SetStateAction, useEffect, useState } from 'react'
+
+import { allCertificationsGetAsync, LearnCertification } from './all-certifications-functions'
+import { AllCertificationsProviderData } from './all-certifications-provider-data.model'
+
+interface CertificationsAllProviderOptions {
+ enabled?: boolean
+}
+
+export function useAllCertifications(
+ provider?: string,
+ certificationId?: string,
+ options?: CertificationsAllProviderOptions
+): AllCertificationsProviderData {
+
+ const [state, setState]:
+ [AllCertificationsProviderData, Dispatch>]
+ = useState({
+ certifications: [],
+ certificationsCount: 0,
+ loading: false,
+ ready: false,
+ })
+
+ useEffect(() => {
+ setState((prevState) => ({
+ ...prevState,
+ loading: true,
+ }))
+
+ if (options?.enabled === false) {
+ return
+ }
+
+ allCertificationsGetAsync(provider, certificationId)
+ .then((certifications) => {
+ setState((prevState) => ({
+ ...prevState,
+ ...(certificationId ? { certification: certifications as unknown as LearnCertification } : {
+ certifications: [...certifications],
+ }),
+ certificationsCount: certifications.length,
+ loading: false,
+ ready: true,
+ }))
+ })
+ }, [provider, certificationId, options?.enabled])
+
+ return state
+}
diff --git a/src-ts/tools/learn/learn-lib/all-certifications-provider/index.ts b/src-ts/tools/learn/learn-lib/all-certifications-provider/index.ts
new file mode 100755
index 000000000..f8e61f839
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/all-certifications-provider/index.ts
@@ -0,0 +1,3 @@
+export * from './all-certifications-functions'
+export * from './all-certifications-provider-data.model'
+export * from './all-certifications.provider'
diff --git a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/index.ts b/src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/index.ts
deleted file mode 100755
index 17186582c..000000000
--- a/src-ts/tools/learn/learn-lib/certifications-provider/certifications-functions/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './certification.store'
-export * from './learn-certification.model'
diff --git a/src-ts/tools/learn/learn-lib/certifications-provider/certifications.provider.tsx b/src-ts/tools/learn/learn-lib/certifications-provider/certifications.provider.tsx
deleted file mode 100644
index 39ab8c339..000000000
--- a/src-ts/tools/learn/learn-lib/certifications-provider/certifications.provider.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Dispatch, SetStateAction, useEffect, useState } from 'react'
-
-import { getCertificationsAsync, LearnCertification } from './certifications-functions'
-import { CertificationsProviderData } from './certifications-provider-data.model'
-
-interface CertificationsProviderOptions {
- enabled?: boolean
-}
-
-export function useCertificationsProvider(
- provider?: string,
- certificationId?: string,
- options?: CertificationsProviderOptions
-): CertificationsProviderData {
- const [state, setState]: [CertificationsProviderData, Dispatch>] = useState({
- certifications: [],
- certificationsCount: 0,
- loading: false,
- ready: false,
- })
-
- useEffect(() => {
- setState((prevState) => ({
- ...prevState,
- loading: true,
- }))
-
- if (options?.enabled === false) {
- return
- }
-
- getCertificationsAsync(provider, certificationId).then((certifications) => {
- setState((prevState) => ({
- ...prevState,
- ...(certificationId ? {certification: certifications as unknown as LearnCertification} : {
- certifications: [...certifications],
- }),
- certificationsCount: certifications.length,
- loading: false,
- ready: true,
- }))
- })
- }, [provider, certificationId, options?.enabled])
-
- return state
-}
diff --git a/src-ts/tools/learn/learn-lib/certifications-provider/index.ts b/src-ts/tools/learn/learn-lib/certifications-provider/index.ts
deleted file mode 100755
index c4af9fcdf..000000000
--- a/src-ts/tools/learn/learn-lib/certifications-provider/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './certifications-functions'
-export * from './certifications-provider-data.model'
-export * from './certifications.provider'
diff --git a/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx b/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx
index 7b74df4a6..63015da4e 100644
--- a/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx
+++ b/src-ts/tools/learn/learn-lib/course-outline/CourseOutline.tsx
@@ -6,9 +6,9 @@ import {
LearnCourse,
LearnLesson,
LearnModule,
- LearnMyCertificationProgress,
+ LearnUserCertificationProgress,
} from '../../learn-lib'
-import { getFccLessonPath } from '../../learn.routes'
+import { getLessonPathFromModule } from '../../learn.routes'
import { CollapsibleItem } from './collapsible-item'
import styles from './CourseOutline.module.scss'
@@ -16,20 +16,21 @@ import styles from './CourseOutline.module.scss'
interface CourseOutlineProps {
course?: LearnCourse
currentStep?: string
- progress?: LearnMyCertificationProgress
+ progress?: LearnUserCertificationProgress
ready?: boolean
}
const CourseOutline: FC = (props: CourseOutlineProps) => {
- const lessonPath: (course: LearnCourse, module: LearnModule, lesson: LearnLesson) => string = useCallback((course: LearnCourse, module: LearnModule, lesson: LearnLesson) => {
- return getFccLessonPath(
- course.provider,
- course.certification,
- module.key,
- lesson.dashedName,
- )
- }, [])
+ const lessonPath: (course: LearnCourse, module: LearnModule, lesson: LearnLesson) => string
+ = useCallback((course: LearnCourse, module: LearnModule, lesson: LearnLesson) => {
+ return getLessonPathFromModule(
+ course.provider,
+ course.certification,
+ module.key,
+ lesson.dashedName,
+ )
+ }, [])
return (
diff --git a/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.tsx b/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.tsx
index e88fe12d9..36f23db12 100644
--- a/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.tsx
+++ b/src-ts/tools/learn/learn-lib/course-outline/collapsible-item/CollapsibleItem.tsx
@@ -3,7 +3,7 @@ import { Dispatch, FC, ReactNode, SetStateAction, useCallback, useMemo, useState
import { Link } from 'react-router-dom'
import { IconOutline, IconSolid } from '../../../../../lib'
-import { LearnModule, LearnMyCertificationProgress, LearnMyModuleProgress } from '../../../learn-lib'
+import { LearnModule, LearnModuleProgress, LearnUserCertificationProgress } from '../../../learn-lib'
import { StatusIcon } from '../status-icon'
import { StepIcon } from '../step-icon'
@@ -22,7 +22,7 @@ interface CollapsibleItemProps {
lessonsCount: number
moduleKey: string
path?: (item: any) => string
- progress?: LearnMyCertificationProgress['modules']
+ progress?: LearnUserCertificationProgress['modules']
shortDescription: Array
title: string
}
@@ -36,7 +36,7 @@ const CollapsibleItem: FC = (props: CollapsibleItemProps)
setIsOpen(open => !open)
}, [])
- const progress: LearnMyModuleProgress|undefined = useMemo(() => {
+ const progress: LearnModuleProgress | undefined = useMemo(() => {
return props.progress?.find(m => m.module === props.moduleKey)
}, [props.progress, props.moduleKey])
diff --git a/src-ts/tools/learn/learn-lib/courses-provider/courses.provider.tsx b/src-ts/tools/learn/learn-lib/courses-provider/courses.provider.tsx
index 780cd6781..963e56348 100644
--- a/src-ts/tools/learn/learn-lib/courses-provider/courses.provider.tsx
+++ b/src-ts/tools/learn/learn-lib/courses-provider/courses.provider.tsx
@@ -3,11 +3,13 @@ import { Dispatch, SetStateAction, useEffect, useState } from 'react'
import { getCourseAsync } from './courses-functions'
import { CoursesProviderData } from './courses-provider-data.model'
-export function useCoursesProvider(provider: string, certification?: string): CoursesProviderData {
- const [state, setState]: [CoursesProviderData, Dispatch>] = useState({
- loading: false,
- ready: false,
- })
+export function useCourses(provider: string, certification?: string): CoursesProviderData {
+
+ const [state, setState]: [CoursesProviderData, Dispatch>]
+ = useState({
+ loading: false,
+ ready: false,
+ })
useEffect(() => {
if (!certification) {
diff --git a/src-ts/tools/learn/learn-lib/index.ts b/src-ts/tools/learn/learn-lib/index.ts
index abd290825..af4a0dcb8 100755
--- a/src-ts/tools/learn/learn-lib/index.ts
+++ b/src-ts/tools/learn/learn-lib/index.ts
@@ -1,13 +1,12 @@
-export * from './certifications-provider'
-export * from './resource-provider-provider'
+export * from './all-certifications-provider'
export * from './collapsible-pane'
+export * from './course-outline'
+export * from './course-title'
export * from './courses-provider'
export * from './curriculum-summary'
export * from './lesson-provider'
-export * from './my-certifications-provider'
export * from './my-course-card'
-
-export * from './course-outline'
-export * from './course-title'
+export * from './resource-provider-provider'
export * from './svgs'
+export * from './user-certifications-provider'
export * from './wave-hero'
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/index.ts b/src-ts/tools/learn/learn-lib/my-certifications-provider/index.ts
deleted file mode 100755
index 9f7a8661c..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from './my-certification-progress-provider-data.model'
-export * from './my-certification-progress.provider'
-export * from './my-certifications-provider-data.model'
-export * from './my-certifications.provider'
-export * from './my-certifications-functions'
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certification-progress-provider-data.model.ts b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certification-progress-provider-data.model.ts
deleted file mode 100755
index 8ea447619..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certification-progress-provider-data.model.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { LearnMyCertificationProgress } from './my-certifications-functions'
-
-export interface MyCertificationProgressProviderData {
- certificateProgress?: LearnMyCertificationProgress
- loading: boolean
- ready: boolean
- setCertificateProgress: (progess: LearnMyCertificationProgress) => void,
-}
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certification-progress.provider.tsx b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certification-progress.provider.tsx
deleted file mode 100644
index ddc93a577..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certification-progress.provider.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { Dispatch, SetStateAction, useEffect, useState } from 'react'
-
-import { MyCertificationProgressProviderData } from './my-certification-progress-provider-data.model'
-import { getMyCertificationsProgressAsync, LearnMyCertificationProgress } from './my-certifications-functions'
-
-export function useMyCertificationProgress(userId?: number, provider?: string, certification?: string): MyCertificationProgressProviderData {
- function setCertificateProgress(progress: LearnMyCertificationProgress): void {
- setState((prevState) => ({...prevState, certificateProgress: progress}))
- }
-
- const [state, setState]: [MyCertificationProgressProviderData, Dispatch>] = useState({
- certificateProgress: undefined,
- loading: false,
- ready: false,
- setCertificateProgress,
- })
-
- useEffect(() => {
- setState((prevState) => ({
- ...prevState,
- loading: true,
- }))
-
- if (!userId) {
- return
- }
-
- getMyCertificationsProgressAsync(userId, provider, certification).then((myCertifications) => {
- setState((prevState) => ({
- ...prevState,
- certificateProgress: myCertifications.find(c => c.certification === certification),
- loading: false,
- ready: true,
- }))
- })
- }, [userId, provider, certification])
-
- return state
-}
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/certificate-progress.decorators.ts b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/certificate-progress.decorators.ts
deleted file mode 100755
index 39cca583f..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/certificate-progress.decorators.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { LearnMyCertificationProgress } from './learn-my-certification-progress.model'
-
-export function decorateCompletedPercentage(myCertification: LearnMyCertificationProgress): LearnMyCertificationProgress {
- const progress: {completedLessons: number, lessonCount: number } = myCertification.modules.reduce((prev, m) => ({
- completedLessons: prev.completedLessons + m.completedLessons.length,
- lessonCount: prev.lessonCount + m.lessonCount,
- }), {lessonCount: 0, completedLessons: 0})
-
- return {
- ...myCertification,
- completedPercentage: progress.completedLessons / progress.lessonCount,
- }
-}
-
-export function mapCompletedPercentage(myCertifications: Array): Array {
- return myCertifications.map(decorateCompletedPercentage)
-}
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/index.ts b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/index.ts
deleted file mode 100755
index c5eebf2e5..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './learn-my-certification-progress.model'
-export * from './learn-my-module-progress.model'
-export * from './my-certification-progress-status.enum'
-export * from './my-certifications.store'
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/my-certification-progress-status.enum.ts b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/my-certification-progress-status.enum.ts
deleted file mode 100755
index b9a3c8e6f..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/my-certification-progress-status.enum.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export enum MyCertificationProgressStatus {
- inProgress = 'in-progress',
- completed = 'completed',
-}
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/my-certifications.store.ts b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/my-certifications.store.ts
deleted file mode 100755
index eb4fbcb1c..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/my-certifications.store.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { xhrGetAsync, xhrPostAsync, xhrPutAsync } from '../../../../../lib/functions'
-import { getPath } from '../../learn-url.config'
-
-import { LearnMyCertificationProgress } from './learn-my-certification-progress.model'
-
-export enum UpdateMyCertificateProgressActions {
- acceptHonestyPolicy = 'honesty-policy',
- currentLesson = 'current-lesson',
- completeLesson = 'complete-lesson',
- completeCertificate = 'complete-certification',
-}
-
-export function getMyCertificationsProgressAsync(userId: number, provider?: string, certification?: string): Promise> {
- return xhrGetAsync>(getPath(
- 'certification-progresses',
- [
- `?userId=${userId}`,
- provider && `provider=${provider}`,
- certification && `certification=${certification}`,
- ].filter(Boolean).join('&'),
- ))
-}
-
-export function startMyCertificationsProgressAsync(userId: number, certificationId: string, courseId: string, data: any): Promise {
- return xhrPostAsync<{}, LearnMyCertificationProgress>(getPath(
- 'certification-progresses',
- `${userId}`,
- certificationId,
- courseId,
- ), data)
-}
-
-export function updateMyCertificationsProgressAsync(certificationProgressId: string, action: UpdateMyCertificateProgressActions, data: any): Promise {
- return xhrPutAsync<{}, LearnMyCertificationProgress>(getPath(
- 'certification-progresses',
- certificationProgressId,
- action
- ), data)
-}
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-provider-data.model.ts b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-provider-data.model.ts
deleted file mode 100755
index 9efa7186c..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-provider-data.model.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { LearnMyCertificationProgress } from './my-certifications-functions'
-
-export interface MyCertificationsProviderData {
- completed: Array
- inProgress: Array
- loading: boolean
- ready: boolean
-}
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications.provider.tsx b/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications.provider.tsx
deleted file mode 100644
index 81a21cdf1..000000000
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications.provider.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { Dispatch, SetStateAction, useEffect, useState } from 'react'
-
-import { getMyCertificationsProgressAsync, MyCertificationProgressStatus } from './my-certifications-functions'
-import { MyCertificationsProviderData } from './my-certifications-provider-data.model'
-
-export function useMyCertifications(userId?: number): MyCertificationsProviderData {
- const [state, setState]: [MyCertificationsProviderData, Dispatch>] = useState({
- completed: [],
- inProgress: [],
- loading: false,
- ready: false,
- })
-
- useEffect(() => {
- setState((prevState) => ({
- ...prevState,
- loading: true,
- }))
-
- if (!userId) {
- return
- }
-
- getMyCertificationsProgressAsync(userId).then((myCertifications) => {
- setState((prevState) => ({
- ...prevState,
- completed: myCertifications.filter(c => c.status === MyCertificationProgressStatus.completed) as MyCertificationsProviderData['completed'],
- inProgress: myCertifications.filter(c => c.status === MyCertificationProgressStatus.inProgress) as MyCertificationsProviderData['inProgress'],
- loading: false,
- ready: true,
- }))
- })
- }, [userId])
-
- return state
-}
diff --git a/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.tsx b/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.tsx
index 0cb6a0780..50eebb624 100644
--- a/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.tsx
+++ b/src-ts/tools/learn/learn-lib/my-course-card/in-progress/InProgress.tsx
@@ -11,9 +11,9 @@ import {
CoursesProviderData,
CourseTitle,
LearnCertification,
- useCoursesProvider,
+ useCourses,
} from '../../../learn-lib'
-import { getCoursePath, getFccLessonPath } from '../../../learn.routes'
+import { getCoursePath, getLessonPathFromCurrentLesson } from '../../../learn.routes'
import { CurriculumSummary } from '../../curriculum-summary'
import styles from './InProgress.module.scss'
@@ -23,30 +23,28 @@ interface InProgressProps {
completedPercentage: number
currentLesson?: string
startDate?: string
- theme: 'detailed'|'minimum'
+ theme: 'detailed' | 'minimum'
}
const InProgress: FC = (props: InProgressProps) => {
+
const navigate: NavigateFunction = useNavigate()
const isDetailed: boolean = props.theme === 'detailed'
const isMinimum: boolean = props.theme === 'minimum'
const certification: string = props.certification?.certification ?? ''
const provider: string = props.certification?.providerName ?? ''
- const {course}: CoursesProviderData = useCoursesProvider(provider, certification)
+ const { course }: CoursesProviderData = useCourses(provider, certification)
const resumeCourse: () => void = () => {
if (!props.currentLesson) {
return
}
- const [module, lesson]: Array = (props.currentLesson ?? '').split('/')
-
- const coursePath: string = getFccLessonPath(
+ const coursePath: string = getLessonPathFromCurrentLesson(
provider,
certification,
- module,
- lesson,
+ props.currentLesson,
)
navigate(coursePath)
}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/index.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/index.ts
new file mode 100755
index 000000000..2c2e9770c
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/index.ts
@@ -0,0 +1,7 @@
+export * from './user-certification-completed.model'
+export * from './user-certification-in-progress.model'
+export * from './user-certification-progress-provider-data.model'
+export * from './user-certification-progress.provider'
+export * from './user-certifications-functions'
+export * from './user-certifications-provider-data.model'
+export * from './user-certifications.provider'
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-completed.model.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-completed.model.ts
new file mode 100644
index 000000000..2f6c4a198
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-completed.model.ts
@@ -0,0 +1,5 @@
+import { LearnUserCertificationProgress } from './user-certifications-functions'
+
+export interface UserCertificationCompleted extends LearnUserCertificationProgress {
+ completedDate: string
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-in-progress.model.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-in-progress.model.ts
new file mode 100644
index 000000000..699eaf308
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-in-progress.model.ts
@@ -0,0 +1,6 @@
+import { LearnUserCertificationProgress } from './user-certifications-functions'
+
+export interface UserCertificationInProgress extends LearnUserCertificationProgress {
+ currentLesson: string
+ startDate: string
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-progress-provider-data.model.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-progress-provider-data.model.ts
new file mode 100755
index 000000000..2f75dbe98
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-progress-provider-data.model.ts
@@ -0,0 +1,8 @@
+import { LearnUserCertificationProgress } from './user-certifications-functions'
+
+export interface UserCertificationProgressProviderData {
+ certificationProgress?: LearnUserCertificationProgress
+ loading: boolean
+ ready: boolean
+ setCertificateProgress: (progess: LearnUserCertificationProgress) => void,
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-progress.provider.tsx b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-progress.provider.tsx
new file mode 100644
index 000000000..6326b2856
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certification-progress.provider.tsx
@@ -0,0 +1,48 @@
+import { Dispatch, SetStateAction, useEffect, useState } from 'react'
+
+import { UserCertificationProgressProviderData } from './user-certification-progress-provider-data.model'
+import { LearnUserCertificationProgress, userCertificationProgressGetAsync } from './user-certifications-functions'
+
+export function useUserCertificationProgress(userId?: number, provider?: string, certification?: string):
+ UserCertificationProgressProviderData {
+
+ function setCertificateProgress(progress: LearnUserCertificationProgress): void {
+ setState((prevState) => ({ ...prevState, certificationProgress: progress }))
+ }
+
+ const [state, setState]:
+ [UserCertificationProgressProviderData, Dispatch>]
+ = useState({
+ certificationProgress: undefined,
+ loading: false,
+ ready: false,
+ setCertificateProgress,
+ })
+
+ useEffect(() => {
+
+ setState((prevState) => ({
+ ...prevState,
+ loading: true,
+ }))
+
+ if (!userId) {
+ return
+ }
+
+ userCertificationProgressGetAsync(userId, provider, certification)
+ .then((myCertifications) => {
+ setState((prevState) => ({
+ ...prevState,
+ certificationProgress: myCertifications.find(c => c.certification === certification),
+ loading: false,
+ ready: true,
+ }))
+ })
+ }, [
+ certification,
+ provider,
+ ])
+
+ return state
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/index.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/index.ts
new file mode 100755
index 000000000..507435d3c
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/index.ts
@@ -0,0 +1,9 @@
+export * from './learn-user-certification-progress.model'
+export * from './learn-module-progress.model'
+export * from './user-certification-progress-status.enum'
+export * from './user-certification-update-progress-actions.enum'
+export {
+ getAsync as userCertificationProgressGetAsync,
+ startAsync as userCertificationProgressStartAsync,
+ updateAsync as userCertificationProgressUpdateAsync
+} from './user-certification-progress.store'
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/learn-my-module-progress.model.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/learn-module-progress.model.ts
similarity index 82%
rename from src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/learn-my-module-progress.model.ts
rename to src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/learn-module-progress.model.ts
index 19f9e5229..d5e474c24 100644
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/learn-my-module-progress.model.ts
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/learn-module-progress.model.ts
@@ -1,4 +1,4 @@
-export interface LearnMyModuleProgress {
+export interface LearnModuleProgress {
completedLessons: Array<{
completedDate?: string
dashedName: string
diff --git a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/learn-my-certification-progress.model.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/learn-user-certification-progress.model.ts
similarity index 50%
rename from src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/learn-my-certification-progress.model.ts
rename to src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/learn-user-certification-progress.model.ts
index ff43b5847..f218dfd15 100644
--- a/src-ts/tools/learn/learn-lib/my-certifications-provider/my-certifications-functions/learn-my-certification-progress.model.ts
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/learn-user-certification-progress.model.ts
@@ -1,7 +1,7 @@
-import { LearnMyModuleProgress } from './learn-my-module-progress.model'
-import { MyCertificationProgressStatus } from './my-certification-progress-status.enum'
+import { LearnModuleProgress } from './learn-module-progress.model'
+import { UserCertificationProgressStatus } from './user-certification-progress-status.enum'
-export interface LearnMyCertificationProgress {
+export interface LearnUserCertificationProgress {
academicHonestyPolicyAcceptedAt?: number,
certification: string
certificationId: string
@@ -11,8 +11,8 @@ export interface LearnMyCertificationProgress {
courseProgressPercentage: number
currentLesson?: string
id: string
- modules: Array
+ modules: Array
provider: string
startDate: string
- status: MyCertificationProgressStatus
+ status: UserCertificationProgressStatus
}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-progress-status.enum.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-progress-status.enum.ts
new file mode 100755
index 000000000..fd5998abb
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-progress-status.enum.ts
@@ -0,0 +1,5 @@
+export enum UserCertificationProgressStatus {
+ inititialized = 'init',
+ inProgress = 'in-progress',
+ completed = 'completed',
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-progress.store.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-progress.store.ts
new file mode 100755
index 000000000..1174416d0
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-progress.store.ts
@@ -0,0 +1,33 @@
+import { xhrGetAsync, xhrPostAsync, xhrPutAsync } from '../../../../../lib/functions'
+import { getPath } from '../../learn-url.config'
+
+import { LearnUserCertificationProgress } from './learn-user-certification-progress.model'
+import { UserCertificationUpdateProgressActions } from './user-certification-update-progress-actions.enum'
+
+export function getAsync(userId: number, provider?: string, certification?: string): Promise> {
+ return xhrGetAsync>(getPath(
+ 'certification-progresses',
+ [
+ `?userId=${userId}`,
+ provider && `provider=${provider}`,
+ certification && `certification=${certification}`,
+ ].filter(Boolean).join('&'),
+ ))
+}
+
+export function startAsync(userId: number, certificationId: string, courseId: string, data: any): Promise {
+ return xhrPostAsync<{}, LearnUserCertificationProgress>(getPath(
+ 'certification-progresses',
+ `${userId}`,
+ certificationId,
+ courseId,
+ ), data)
+}
+
+export function updateAsync(certificationProgressId: string, action: UserCertificationUpdateProgressActions, data: any): Promise {
+ return xhrPutAsync<{}, LearnUserCertificationProgress>(getPath(
+ 'certification-progresses',
+ certificationProgressId,
+ action
+ ), data)
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-update-progress-actions.enum.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-update-progress-actions.enum.ts
new file mode 100644
index 000000000..9e7017ba0
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-functions/user-certification-update-progress-actions.enum.ts
@@ -0,0 +1,6 @@
+export enum UserCertificationUpdateProgressActions {
+ acceptHonestyPolicy = 'honesty-policy',
+ currentLesson = 'current-lesson',
+ completeLesson = 'complete-lesson',
+ completeCertificate = 'complete-certification',
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-provider-data.model.ts b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-provider-data.model.ts
new file mode 100755
index 000000000..807a60252
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications-provider-data.model.ts
@@ -0,0 +1,11 @@
+import { LearnUserCertificationProgress } from './user-certifications-functions'
+
+export interface UserCertificationsProviderData {
+ completed: Array
+ inProgress: Array
+ loading: boolean
+ ready: boolean
+}
diff --git a/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications.provider.tsx b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications.provider.tsx
new file mode 100644
index 000000000..750c1ef4e
--- /dev/null
+++ b/src-ts/tools/learn/learn-lib/user-certifications-provider/user-certifications.provider.tsx
@@ -0,0 +1,51 @@
+import { Dispatch, SetStateAction, useContext, useEffect, useState } from 'react'
+
+import { profileContext, ProfileContextData } from '../../../../lib'
+
+import { UserCertificationCompleted } from './user-certification-completed.model'
+import { UserCertificationInProgress } from './user-certification-in-progress.model'
+import { userCertificationProgressGetAsync, UserCertificationProgressStatus } from './user-certifications-functions'
+import { UserCertificationsProviderData } from './user-certifications-provider-data.model'
+
+export function useUserCertifications(): UserCertificationsProviderData {
+
+ const profileContextData: ProfileContextData = useContext(profileContext)
+ const [state, setState]: [UserCertificationsProviderData, Dispatch>] = useState({
+ completed: [],
+ inProgress: [],
+ loading: false,
+ ready: false,
+ })
+
+ useEffect(() => {
+
+ setState((prevState) => ({
+ ...prevState,
+ loading: true,
+ }))
+
+ const userId: number | undefined = profileContextData?.profile?.userId
+ if (!userId) {
+ return
+ }
+
+ userCertificationProgressGetAsync(userId)
+ .then((myCertifications) => {
+ const completed: Array = myCertifications
+ .filter(c => c.status === UserCertificationProgressStatus.completed)
+ .map(c => c as UserCertificationCompleted)
+ const inProgress: Array = myCertifications
+ .filter(c => c.status === UserCertificationProgressStatus.inProgress)
+ .map(c => c as UserCertificationInProgress)
+ setState((prevState) => ({
+ ...prevState,
+ completed,
+ inProgress,
+ loading: false,
+ ready: true,
+ }))
+ })
+ }, [profileContextData?.profile?.userId])
+
+ return state
+}
diff --git a/src-ts/tools/learn/learn.routes.tsx b/src-ts/tools/learn/learn.routes.tsx
index 15d1fdec6..20833a468 100644
--- a/src-ts/tools/learn/learn.routes.tsx
+++ b/src-ts/tools/learn/learn.routes.tsx
@@ -3,7 +3,7 @@ import { authUrlLogin, PlatformRoute } from '../../lib'
import { CourseCompletedPage } from './course-completed'
import { CourseDetailsPage } from './course-details'
import { FreeCodeCamp } from './free-code-camp'
-import Learn, { toolTitle } from './Learn'
+import { default as Learn, toolTitle } from './Learn'
import { MyCertificate } from './my-certificate'
import { MyLearning } from './my-learning'
import { WelcomePage } from './welcome'
@@ -20,7 +20,18 @@ export function getCertificationCompletedPath(provider: string, certification: s
return `/learn/${provider}/${certification}/completed`
}
-export function getFccLessonPath(
+export function getLessonPathFromCurrentLesson(
+ provider: string,
+ certification: string,
+ currentLesson: string | undefined,
+ fallbackModule?: string,
+ fallbackLesson?: string,
+): string {
+ const [module, lesson]: Array = (currentLesson ?? '').split('/')
+ return `${getCoursePath(provider, certification)}/${module || fallbackModule}/${lesson || fallbackLesson}`
+}
+
+export function getLessonPathFromModule(
provider: string,
certification: string,
module: string,
diff --git a/src-ts/tools/learn/my-certificate/MyCertificate.tsx b/src-ts/tools/learn/my-certificate/MyCertificate.tsx
index c9c7c2e43..8fbd166a7 100755
--- a/src-ts/tools/learn/my-certificate/MyCertificate.tsx
+++ b/src-ts/tools/learn/my-certificate/MyCertificate.tsx
@@ -12,10 +12,10 @@ import {
} from '../../../lib'
import {
CoursesProviderData,
- MyCertificationProgressProviderData,
- MyCertificationProgressStatus,
- useCoursesProvider,
- useMyCertificationProgress,
+ useCourses,
+ UserCertificationProgressProviderData,
+ UserCertificationProgressStatus,
+ useUserCertificationProgress,
} from '../learn-lib'
import { getCoursePath } from '../learn.routes'
@@ -32,21 +32,21 @@ const MyCertificate: FC<{}> = () => {
const providerParam: string = routeParams.provider ?? ''
const certificationParam: string = routeParams.certification ?? ''
const coursePath: string = getCoursePath(providerParam, certificationParam)
- const certificateElRef: MutableRefObject = useRef()
- const certificateWrapRef: MutableRefObject = useRef()
+ const certificateElRef: MutableRefObject = useRef()
+ const certificateWrapRef: MutableRefObject = useRef()
const userName: string = [profile?.firstName, profile?.lastName].filter(Boolean).join(' ')
const {
course,
ready: courseReady,
- }: CoursesProviderData = useCoursesProvider(providerParam, certificationParam)
+ }: CoursesProviderData = useCourses(providerParam, certificationParam)
const certificationTitle: string = `${userName} - ${course?.title} Certification`
const {
- certificateProgress,
+ certificationProgress: certificateProgress,
ready: progressReady,
- }: MyCertificationProgressProviderData = useMyCertificationProgress(
+ }: UserCertificationProgressProviderData = useUserCertificationProgress(
profile?.userId,
routeParams.provider,
routeParams.certification
@@ -60,7 +60,7 @@ const MyCertificate: FC<{}> = () => {
navigate(-1)
}
- async function getCertificateCanvas(): Promise {
+ async function getCertificateCanvas(): Promise {
if (!certificateElRef.current) {
return
}
@@ -81,7 +81,7 @@ const MyCertificate: FC<{}> = () => {
}
async function handleDownload(): Promise {
- const canvas: HTMLCanvasElement|void = await getCertificateCanvas()
+ const canvas: HTMLCanvasElement | void = await getCertificateCanvas()
if (!canvas) {
return
}
@@ -89,11 +89,11 @@ const MyCertificate: FC<{}> = () => {
}
async function handlePrint(): Promise {
- const canvas: HTMLCanvasElement|void = await getCertificateCanvas()
+ const canvas: HTMLCanvasElement | void = await getCertificateCanvas()
if (!canvas) {
return
}
- const printWindow: Window|null = window.open('')
+ const printWindow: Window | null = window.open('')
if (!printWindow) {
return
@@ -106,7 +106,7 @@ const MyCertificate: FC<{}> = () => {
}
async function handleShare(): Promise {
- const canvas: HTMLCanvasElement|void = await getCertificateCanvas()
+ const canvas: HTMLCanvasElement | void = await getCertificateCanvas()
if (!canvas) {
return
}
@@ -118,15 +118,15 @@ const MyCertificate: FC<{}> = () => {
files: [sharedImg],
title: certificationTitle,
})
- } catch (error) {}
+ } catch (error) { }
}
}
useEffect(() => {
- if (ready && certificateProgress?.status !== MyCertificationProgressStatus.completed) {
- navigate(coursePath)
+ if (ready && certificateProgress?.status !== UserCertificationProgressStatus.completed) {
+ navigate(coursePath)
}
- }, [
+ }, [
certificateProgress,
coursePath,
navigate,
diff --git a/src-ts/tools/learn/my-learning/MyLearning.tsx b/src-ts/tools/learn/my-learning/MyLearning.tsx
index e7ea6b341..90412c0e5 100755
--- a/src-ts/tools/learn/my-learning/MyLearning.tsx
+++ b/src-ts/tools/learn/my-learning/MyLearning.tsx
@@ -2,14 +2,14 @@ import { FC, useContext, useMemo } from 'react'
import { Breadcrumb, BreadcrumbItemModel, ContentLayout, Portal, profileContext, ProfileContextData } from '../../../lib'
import {
- CertificationsProviderData,
+ AllCertificationsProviderData,
LearnCertification,
LearningHat,
- MyCertificationsProviderData,
MyCourseCompletedCard,
MyCourseInProgressCard,
- useCertificationsProvider,
- useMyCertifications,
+ useAllCertifications,
+ UserCertificationsProviderData,
+ useUserCertifications,
WaveHero
} from '../learn-lib'
import { LEARN_PATHS } from '../learn.routes'
@@ -24,17 +24,14 @@ interface CertificatesByIdType {
const MyLearning: FC<{}> = () => {
const { profile }: ProfileContextData = useContext(profileContext)
- const { completed, inProgress }: MyCertificationsProviderData = useMyCertifications(profile?.userId)
-
- const {
- certifications,
- }: CertificationsProviderData = useCertificationsProvider()
+ const { completed, inProgress }: UserCertificationsProviderData = useUserCertifications()
+ const { certifications }: AllCertificationsProviderData = useAllCertifications()
const certificatesById: CertificatesByIdType = useMemo(() => (
certifications.reduce((certifs, certificate) => {
certifs[certificate.id] = certificate
return certifs
-}, {} as unknown as CertificatesByIdType)
+ }, {} as unknown as CertificatesByIdType)
), [certifications])
const breadcrumb: Array = useMemo(() => [
diff --git a/src-ts/tools/learn/welcome/WelcomePage.tsx b/src-ts/tools/learn/welcome/WelcomePage.tsx
index 653290552..cd7842056 100644
--- a/src-ts/tools/learn/welcome/WelcomePage.tsx
+++ b/src-ts/tools/learn/welcome/WelcomePage.tsx
@@ -1,18 +1,24 @@
import { FC } from 'react'
import { ContentLayout, LoadingSpinner, Portal } from '../../../lib'
-import { CertificationsProviderData, useCertificationsProvider, WaveHero } from '../learn-lib'
-import { getCoursePath } from '../learn.routes'
+import {
+ AllCertificationsProviderData,
+ useAllCertifications,
+ UserCertificationsProviderData,
+ useUserCertifications,
+ WaveHero,
+} from '../learn-lib'
import { CoursesCard } from './courses-card'
import { ProgressBlock } from './progress-block'
import styles from './WelcomePage.module.scss'
const WelcomePage: FC<{}> = () => {
- const {
- certifications,
- ready,
- }: CertificationsProviderData = useCertificationsProvider()
+
+ const allCertsData: AllCertificationsProviderData = useAllCertifications()
+ const userCertsData: UserCertificationsProviderData = useUserCertifications()
+
+ const coursesReady: boolean = allCertsData.ready && userCertsData.ready
return (
@@ -35,28 +41,33 @@ const WelcomePage: FC<{}> = () => {
`}
theme='light'
>
-
+
Courses Available
- {!ready && (
+ {!coursesReady && (
)}
- {ready && (
+ {coursesReady && (
- {certifications.map((certification) => (
-
- ))}
+ {allCertsData.certifications
+ .map((certification) => (
+
+ ))}
)}
diff --git a/src-ts/tools/learn/welcome/courses-card/CoursesCard.tsx b/src-ts/tools/learn/welcome/courses-card/CoursesCard.tsx
index 587b579a5..a17a20460 100644
--- a/src-ts/tools/learn/welcome/courses-card/CoursesCard.tsx
+++ b/src-ts/tools/learn/welcome/courses-card/CoursesCard.tsx
@@ -1,36 +1,102 @@
import classNames from 'classnames'
-import { FC } from 'react'
+import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'
import { Button } from '../../../../lib'
-import { CourseTitle } from '../../learn-lib'
+import {
+ CourseTitle,
+ LearnCertification,
+ UserCertificationCompleted,
+ UserCertificationInProgress,
+} from '../../learn-lib'
+import { getCertificatePath, getCoursePath, getLessonPathFromCurrentLesson } from '../../learn.routes'
import styles from './CoursesCard.module.scss'
interface CoursesCardProps {
- credits?: string
- link?: string
- title: string
- type: string
+ certification: LearnCertification
+ userCompletedCertifications: Array
+ userInProgressCertifications: Array
}
const CoursesCard: FC = (props: CoursesCardProps) => {
+ const [buttonLabel, setButtonLabel]: [string, Dispatch>]
+ = useState('')
+ const [link, setLink]: [string, Dispatch>]
+ = useState('')
+
+ const courseEnabled: boolean = props.certification.state === 'active'
+ useEffect(() => {
+
+ // if the course isn't enabled, there's nothing to do
+ if (!courseEnabled) {
+ return
+ }
+
+ // set the button text and link based on the progress of the user for this course
+ const isCompleted: boolean = props.userCompletedCertifications
+ .some(comp => comp.certificationId === props.certification.id)
+ const inProgress: UserCertificationInProgress | undefined
+ = props.userInProgressCertifications
+ .find(i => i.certificationId === props.certification.id)
+
+ if (isCompleted) {
+ // if the course is completed, View the Certificate
+ setButtonLabel('View Certificate')
+ setLink(getCertificatePath(
+ props.certification.providerName,
+ props.certification.certification
+ ))
+
+ } else if (!inProgress) {
+ // if there is no in-progress lesson for the course, Get Started by going to the course details
+ setButtonLabel('Get Started')
+ setLink(getCoursePath(
+ props.certification.providerName,
+ props.certification.certification
+ ))
+
+ } else {
+ // otherwise this course is in-progress, so Resume the course at the next lesson
+ setButtonLabel('Resume')
+ setLink(getLessonPathFromCurrentLesson(
+ props.certification.providerName,
+ props.certification.certification,
+ inProgress.currentLesson
+ ))
+ }
+ }, [
+ courseEnabled,
+ getCertificatePath,
+ getCoursePath,
+ getLessonPathFromCurrentLesson,
+ props.certification,
+ props.userCompletedCertifications,
+ props.userInProgressCertifications,
+ setButtonLabel,
+ setLink,
+ ])
+
return (
-
+
- {props.type}
+ {props.certification.category}
-
+
- {props.link && (
+ {!!link && (
)}
- {!props.link && (
+ {!courseEnabled && (
Coming Soon
)}
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 b05aba83c..ad8703417 100644
--- a/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss
+++ b/src-ts/tools/learn/welcome/progress-block/ProgressBlock.module.scss
@@ -16,22 +16,3 @@
padding: $pad-lg;
}
}
-
-.title-line {
- display: flex;
- align-items: center;
- justify-content: space-between;
- flex-wrap: wrap;
- gap: $pad-lg;
-
- svg {
- @include icon-mx;
- margin-right: $pad-xs;
- }
-}
-
-.title {
- display: flex;
- align-items: center;
- gap: $pad-md;
-}
diff --git a/src-ts/tools/learn/welcome/progress-block/ProgressBlock.tsx b/src-ts/tools/learn/welcome/progress-block/ProgressBlock.tsx
index 30442a5ae..79c3c0667 100644
--- a/src-ts/tools/learn/welcome/progress-block/ProgressBlock.tsx
+++ b/src-ts/tools/learn/welcome/progress-block/ProgressBlock.tsx
@@ -1,93 +1,34 @@
-import { FC, ReactNode, useContext, useMemo } from 'react'
+import { FC } from 'react'
-import { Button, profileContext, ProfileContextData } from '../../../../lib'
import {
LearnCertification,
- LearningHat,
- MyCertificationsProviderData,
- MyCourseCompletedCard,
- MyCourseInProgressCard,
- useMyCertifications
+ UserCertificationCompleted,
+ UserCertificationInProgress
} from '../../learn-lib'
-import { LEARN_PATHS } from '../../learn.routes'
-import InitState from './init-state/InitState'
+import { NoProgress } from './no-progress'
+import { ProgressAction } from './progress-action'
import styles from './ProgressBlock.module.scss'
interface ProgressBlockProps {
- certificates: Array
+ allCertifications: Array
+ ready: boolean
+ userCompletedCertifications: Array
+ userInProgressCertifications: Array
}
const ProgressBlock: FC = (props: ProgressBlockProps) => {
- const { profile }: ProfileContextData = useContext(profileContext)
- const { completed, inProgress }: MyCertificationsProviderData = useMyCertifications(profile?.userId)
- const isInit: boolean = !inProgress.length && !completed.length
+ if (!props.ready) {
+ return <>>
+ }
- const certificatesById: {[key: string]: LearnCertification} = useMemo(() => (
- props.certificates.reduce((certifs, certificate) => {
- certifs[certificate.id] = certificate
- return certifs
-}, {} as unknown as {[key: string]: LearnCertification})
- ), [props.certificates])
-
- const allMyLearningsLink: ReactNode = (
-
-
-
- )
+ const isStarted: boolean = !!props.userInProgressCertifications.length || !!props.userCompletedCertifications.length
return (
-
- {isInit &&
}
- {!isInit && (
- <>
- {!!inProgress.length && (
-
-
In progress
-
- {allMyLearningsLink}
-
-
- )}
- {inProgress.map((certifProgress) => (
-
- ))}
- {!!completed.length && (
-
-
-
-
Congratulations!
-
- {!inProgress.length && (
-
- {allMyLearningsLink}
-
- )}
-
- )}
- {completed.map((certif) => (
-
- ))}
-
- {allMyLearningsLink}
-
- >
- )}
+
+ {!isStarted &&
}
+ {isStarted &&
}
)
}
diff --git a/src-ts/tools/learn/welcome/progress-block/init-state/index.ts b/src-ts/tools/learn/welcome/progress-block/init-state/index.ts
deleted file mode 100644
index c3d2712c7..000000000
--- a/src-ts/tools/learn/welcome/progress-block/init-state/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as InitState } from './InitState'
diff --git a/src-ts/tools/learn/welcome/progress-block/init-state/InitState.module.scss b/src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.module.scss
similarity index 100%
rename from src-ts/tools/learn/welcome/progress-block/init-state/InitState.module.scss
rename to src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.module.scss
diff --git a/src-ts/tools/learn/welcome/progress-block/init-state/InitState.tsx b/src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.tsx
similarity index 81%
rename from src-ts/tools/learn/welcome/progress-block/init-state/InitState.tsx
rename to src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.tsx
index cc3ca38b4..9dc57e46c 100644
--- a/src-ts/tools/learn/welcome/progress-block/init-state/InitState.tsx
+++ b/src-ts/tools/learn/welcome/progress-block/no-progress/NoProgress.tsx
@@ -2,9 +2,9 @@ import { FC } from 'react'
import { LearningHat } from '../../../learn-lib'
-import styles from './InitState.module.scss'
+import styles from './NoProgress.module.scss'
-const InitState: FC<{}> = () => {
+const NoProgress: FC<{}> = () => {
return (
@@ -18,4 +18,4 @@ const InitState: FC<{}> = () => {
)
}
-export default InitState
+export default NoProgress
diff --git a/src-ts/tools/learn/welcome/progress-block/no-progress/index.ts b/src-ts/tools/learn/welcome/progress-block/no-progress/index.ts
new file mode 100644
index 000000000..3863f59ea
--- /dev/null
+++ b/src-ts/tools/learn/welcome/progress-block/no-progress/index.ts
@@ -0,0 +1 @@
+export { default as NoProgress } from './NoProgress'
diff --git a/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.module.scss b/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.module.scss
new file mode 100644
index 000000000..d00ffc894
--- /dev/null
+++ b/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.module.scss
@@ -0,0 +1,20 @@
+@import '../../../../../lib/styles/includes';
+
+.title-line {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ gap: $pad-lg;
+
+ svg {
+ @include icon-mx;
+ margin-right: $pad-xs;
+ }
+}
+
+.title {
+ display: flex;
+ align-items: center;
+ gap: $pad-md;
+}
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
new file mode 100644
index 000000000..000e322ab
--- /dev/null
+++ b/src-ts/tools/learn/welcome/progress-block/progress-action/ProgressAction.tsx
@@ -0,0 +1,93 @@
+import { FC, ReactNode, useMemo } from 'react'
+
+import { Button } from '../../../../../lib'
+import {
+ LearnCertification,
+ LearningHat,
+ MyCourseCompletedCard,
+ MyCourseInProgressCard,
+ UserCertificationCompleted,
+ UserCertificationInProgress,
+} from '../../../learn-lib'
+import { LEARN_PATHS } from '../../../learn.routes'
+
+import styles from './ProgressAction.module.scss'
+
+interface ProgressActionProps {
+ allCertifications: Array
+ userCompletedCertifications: Array
+ userInProgressCertifications: Array
+}
+
+const ProgressAction: FC = (props: ProgressActionProps) => {
+
+ const {
+ allCertifications,
+ userCompletedCertifications: myCompletedCertifications,
+ userInProgressCertifications: myInProgressCertifications,
+ }: ProgressActionProps = props
+
+ const allMyLearningsLink: ReactNode = (
+
+
+
+ )
+
+ const certificationsById: { [key: string]: LearnCertification } = useMemo(() => (
+ allCertifications
+ .reduce((certifs, certificate) => {
+ certifs[certificate.id] = certificate
+ return certifs
+ }, {} as unknown as { [key: string]: LearnCertification })
+ ), [allCertifications])
+
+ return (
+ <>
+ {!!myInProgressCertifications.length && (
+
+
In progress
+
+ {allMyLearningsLink}
+
+
+ )}
+ {myInProgressCertifications
+ .map((cert) => (
+
+ ))}
+ {!!myCompletedCertifications.length && (
+
+
+
+
Congratulations!
+
+ {!myInProgressCertifications.length && (
+
+ {allMyLearningsLink}
+
+ )}
+
+ )}
+ {myCompletedCertifications
+ .map((cert) => (
+
+ ))}
+ >
+ )
+}
+
+export default ProgressAction
diff --git a/src-ts/tools/learn/welcome/progress-block/progress-action/index.ts b/src-ts/tools/learn/welcome/progress-block/progress-action/index.ts
new file mode 100644
index 000000000..0cf97b323
--- /dev/null
+++ b/src-ts/tools/learn/welcome/progress-block/progress-action/index.ts
@@ -0,0 +1 @@
+export { default as ProgressAction } from './ProgressAction'