Skip to content

Commit 1dacb5e

Browse files
committed
TCA-996 - implement certificate not found error pages for tca certifications and FCC courses
1 parent 1697222 commit 1dacb5e

File tree

32 files changed

+551
-133
lines changed

32 files changed

+551
-133
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
$tca-certif-aspect-ratio: 1.25715;
1+
$tca-certif-aspect-ratio: 1.2571;

src-ts/lib/svgs/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ReactComponent as SocialIconYoutube } from './social-yt-icon.svg'
2121
import { ReactComponent as TooltipArrowIcon } from './tooltip-arrow.svg'
2222
import { ReactComponent as TcAcademyLogoSvg } from './tc-academy-logo.svg'
2323
import { ReactComponent as TCAcademyLogoWhiteSvg } from './tc-academy-logo-white.svg'
24+
import { ReactComponent as TCAcademyLogoMixedSvg } from './tc-academy-logo-mixed.svg'
2425
import { ReactComponent as TcLogoSvg } from './tc-logo.svg'
2526
import { ReactComponent as TCLogoSvg } from './tc-logo-white.svg'
2627
import { ReactComponent as FccLogoSvg } from './vendor-fcc-logo.svg'
@@ -49,6 +50,7 @@ export {
4950
IconCheck,
5051
TcAcademyLogoSvg,
5152
TCAcademyLogoWhiteSvg,
53+
TCAcademyLogoMixedSvg,
5254
TcLogoSvg,
5355
TCLogoSvg,
5456
FccLogoSvg,

src-ts/lib/svgs/tc-academy-logo-mixed.svg

Lines changed: 24 additions & 0 deletions
Loading
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
@import '../../../../lib/styles/includes';
2+
3+
.wrap {
4+
display: flex;
5+
height: 100%;
6+
z-index: 1;
7+
overflow: hidden;
8+
9+
@include ltemd {
10+
border: 1px dashed $blue-25;
11+
border-radius: 8px;
12+
}
13+
> svg {
14+
position: absolute;
15+
top: 50%;
16+
left: 0;
17+
width: 100%;
18+
height: auto;
19+
display: block;
20+
z-index: -1;
21+
transform: translateY(-50%);
22+
23+
@include ltemd {
24+
:global(.rect-border) {
25+
display: none;
26+
}
27+
}
28+
}
29+
}
30+
31+
.details {
32+
width: 55%;
33+
padding: calc($space-mx + $space-lg);
34+
display: flex;
35+
flex-direction: column;
36+
flex: 1;
37+
38+
&Inner {
39+
max-width: 385px;
40+
flex: 1;
41+
display: flex;
42+
flex-direction: column;
43+
}
44+
45+
h2 {
46+
color: $blue-25;
47+
}
48+
49+
h3 {
50+
font-size: 48px;
51+
line-height: 50px;
52+
font-weight: 500;
53+
color: $tc-white;
54+
margin-top: $space-sm;
55+
56+
:global(.nw) {
57+
white-space: nowrap;
58+
}
59+
}
60+
}
61+
62+
.logos {
63+
margin-top: auto;
64+
display: flex;
65+
}
66+
67+
.logo {
68+
display: flex;
69+
align-items: center;
70+
height: 52px;
71+
72+
svg {
73+
width: auto;
74+
75+
}
76+
&.whiteLogo svg > path {
77+
fill: $tc-white;
78+
}
79+
}
80+
81+
.divider {
82+
width: $border;
83+
background: $black-10;
84+
margin: 0 $space-lg;
85+
flex: 0 0 auto;
86+
}
87+
88+
.rightSide {
89+
width: 45%;
90+
91+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { FC } from 'react'
2+
import classNames from 'classnames'
3+
4+
import { TCAcademyLogoMixedSvg, TcLogoSvg } from '../../../../lib'
5+
import { CertificateNotFoundContent } from '../../learn-lib'
6+
7+
import { ReactComponent as BackgroundSvg } from './bg.svg'
8+
import styles from './CertificateNotFound.module.scss'
9+
10+
const CertificateNotFound: FC<{}> = () => (
11+
<div className={styles.wrap}>
12+
<BackgroundSvg />
13+
<div className={styles.details}>
14+
<div className={styles.detailsInner}>
15+
<h2 className='details'>Topcoder Academy</h2>
16+
<h3>
17+
Certificate
18+
{' '}
19+
<span className='nw'>not found</span>
20+
</h3>
21+
<CertificateNotFoundContent className='mobile-hide' />
22+
<div className={styles.logos}>
23+
<div className={classNames(styles.logo, styles.whiteLogo)}>
24+
<TcLogoSvg />
25+
</div>
26+
<div className={styles.divider} />
27+
<div className={styles.logo}>
28+
<TCAcademyLogoMixedSvg />
29+
</div>
30+
</div>
31+
</div>
32+
</div>
33+
<div className={styles.rightSide} />
34+
</div>
35+
)
36+
37+
export default CertificateNotFound
Lines changed: 38 additions & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as CertificateNotFound } from './CertificateNotFound'

src-ts/tools/learn/course-certificate/certificate-view/CertificateView.tsx

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import {
22
FC,
33
MutableRefObject,
4-
useEffect,
4+
ReactNode,
55
useMemo,
66
useRef,
77
} from 'react'
88

99
import {
1010
AllCertificationsProviderData,
11+
CertificateNotFoundContent,
1112
CertificatePageLayout,
1213
CoursesProviderData,
1314
useGetCertification,
@@ -20,13 +21,13 @@ import {
2021
getUserCertificateSsr,
2122
} from '../../learn.routes'
2223
import { UserProfile } from '../../../../lib'
24+
import { CertificateNotFound } from '../certificate-not-found'
2325

2426
import Certificate from './certificate/Certificate'
2527

2628
interface CertificateViewProps {
2729
certification: string
2830
fullScreenCertLayout?: boolean
29-
onCertificationNotCompleted: () => void
3031
profile: UserProfile
3132
provider: string
3233
}
@@ -81,23 +82,14 @@ const CertificateView: FC<CertificateViewProps> = (props: CertificateViewProps)
8182
const ready: boolean = useMemo(() => (
8283
completedCertificateReady && courseReady && certificateReady
8384
), [certificateReady, completedCertificateReady, courseReady])
85+
const certificateNotFoundError: boolean = ready && !hasCompletedTheCertification
8486

85-
useEffect(() => {
87+
function renderCertificate(): ReactNode {
8688
if (ready && !hasCompletedTheCertification) {
87-
props.onCertificationNotCompleted()
89+
return <CertificateNotFound />
8890
}
89-
}, [coursePath, hasCompletedTheCertification, props, ready])
9091

91-
return (
92-
<CertificatePageLayout
93-
certificateElRef={certificateElRef}
94-
fallbackBackUrl={coursePath}
95-
fullScreenCertLayout={props.fullScreenCertLayout}
96-
isCertificateCompleted={hasCompletedTheCertification}
97-
isReady={ready}
98-
ssrUrl={certUrl}
99-
title={certificationTitle}
100-
>
92+
return (
10193
<Certificate
10294
completedDate={completedCertificate?.completedDate ?? ''}
10395
course={course?.title}
@@ -107,6 +99,25 @@ const CertificateView: FC<CertificateViewProps> = (props: CertificateViewProps)
10799
type={certificate?.certificationCategory.track}
108100
userName={userName}
109101
/>
102+
)
103+
}
104+
105+
return (
106+
<CertificatePageLayout
107+
certificateElRef={certificateElRef}
108+
fallbackBackUrl={coursePath}
109+
fullScreenCertLayout={!certificateNotFoundError && props.fullScreenCertLayout}
110+
isCertificateCompleted={hasCompletedTheCertification}
111+
isReady={ready}
112+
ssrUrl={certUrl}
113+
title={certificationTitle}
114+
disableActions={ready && !hasCompletedTheCertification}
115+
className={certificateNotFoundError ? 'cert-not-found-layout' : ''}
116+
afterContent={certificateNotFoundError && (
117+
<CertificateNotFoundContent className='desktop-hide' />
118+
)}
119+
>
120+
{renderCertificate()}
110121
</CertificatePageLayout>
111122
)
112123
}

src-ts/tools/learn/course-certificate/certificate-view/certificate/Certificate.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
.wrap {
44
display: flex;
55
height: 100%;
6+
background: $tc-white;
67
}
78

89
.details {

src-ts/tools/learn/course-certificate/my-certificate/MyCertificate.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ const MyCertificate: FC<{}> = () => {
3737
certification={certificationParam}
3838
profile={profile}
3939
provider={providerParam}
40-
onCertificationNotCompleted={navigateToCourse}
4140
/>
4241
)}
4342
</>

src-ts/tools/learn/course-certificate/user-certificate/UserCertificate.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ const UserCertificate: FC<{}> = () => {
4040
certification={certificationParam}
4141
profile={profile}
4242
provider={providerParam}
43-
onCertificationNotCompleted={() => { }}
4443
fullScreenCertLayout
4544
/>
4645
)}

src-ts/tools/learn/learn-lib/action-button/ActionButton.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@
1818
svg {
1919
@include icon-xxl;
2020
}
21+
22+
@include ltemd {
23+
@include icon-mx;
24+
}
2125
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
@import '../../../../lib/styles/includes';
2+
3+
.content {
4+
color: $blue-25;
5+
margin-top: $space-lg;
6+
7+
@include ltemd {
8+
padding-left: $space-xxl;
9+
padding-right: $space-xxl;
10+
}
11+
12+
@include ltesm {
13+
padding-left: $space-lg;
14+
padding-right: $space-lg;
15+
}
16+
17+
p, ol, li {
18+
margin-top: $space-lg;
19+
}
20+
ol {
21+
list-style: decimal;
22+
padding-left: 16px;
23+
}
24+
25+
ol li a {
26+
display: flex;
27+
align-items: center;
28+
gap: $space-xs;
29+
font-family: $font-roboto;
30+
font-weight: bold;
31+
font-size: 14px;
32+
line-height: 14px;
33+
letter-spacing: 0.03em;
34+
text-transform: uppercase;
35+
color: $tc-white;
36+
margin-top: $space-sm;
37+
svg {
38+
display: block;
39+
width: 14px;
40+
height: 14px;
41+
}
42+
}
43+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { FC } from 'react'
2+
import classNames from 'classnames'
3+
4+
import { IconSolid } from '../../../../lib'
5+
6+
import styles from './CertificateNotFoundContent.module.scss'
7+
8+
interface CertificateNotFoundContentProps {
9+
className?: string
10+
}
11+
12+
const CertificateNotFoundContent: FC<CertificateNotFoundContentProps> = (props: CertificateNotFoundContentProps) => (
13+
<div className={classNames(styles.content, 'body-main', props.className)}>
14+
<p>
15+
Hey there!
16+
</p>
17+
<p>
18+
Looks like we don’t have your certificate.
19+
Have you completed the course? If not, keep going at it! If you have:
20+
</p>
21+
<ol>
22+
<li>
23+
Try again in 60 seconds. We might still be generating your certification!
24+
</li>
25+
<li>
26+
If you already waited, contact our support team.
27+
Please reference Topcoder Academy and the course you completed.
28+
29+
<a href='mailto:support@topcoder.com'>
30+
Contact support
31+
<IconSolid.ArrowRightIcon />
32+
</a>
33+
</li>
34+
</ol>
35+
<p>
36+
Keep Learning away!
37+
</p>
38+
</div>
39+
)
40+
41+
export default CertificateNotFoundContent
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as CertificateNotFoundContent } from './CertificateNotFoundContent'

0 commit comments

Comments
 (0)