Skip to content

Commit 5d10ce3

Browse files
fix(client): daily challenge calendar (freeCodeCamp#66202)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
1 parent b9307e1 commit 5d10ce3

4 files changed

Lines changed: 95 additions & 121 deletions

File tree

client/src/components/daily-coding-challenge/calendar-day.tsx

Lines changed: 25 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import React from 'react';
22
import { useTranslation } from 'react-i18next';
3-
import { Spacer } from '@freecodecamp/ui';
43
import { Link } from '../helpers';
54
import GreenPass from '../../assets/icons/green-pass';
65
import GreenNotCompleted from '../../assets/icons/green-not-completed';
76
import JavaScriptIcon from '../../assets/icons/javascript';
87
import PythonIcon from '../../assets/icons/python';
9-
import { formatDisplayDate } from './helpers';
8+
import { formatDisplayDate, truncate } from './helpers';
109

1110
interface CalendarDayProps {
1211
dayNumber: number;
@@ -17,33 +16,33 @@ interface CalendarDayProps {
1716
title?: string;
1817
}
1918

20-
function Checkmark({ completed }: { completed: boolean }): JSX.Element {
21-
return completed ? (
19+
function Checkmark({ isCompleted }: { isCompleted: boolean }) {
20+
return isCompleted ? (
2221
<span
23-
className='dc-checkmark dc-small-checkmark completed'
22+
className='dc-checkmark completed'
2423
data-playwright-test-label='calendar-day-completed'
2524
>
2625
<GreenPass />
2726
</span>
2827
) : (
2928
<span
30-
className='dc-checkmark dc-small-checkmark not-completed'
29+
className='dc-checkmark not-completed'
3130
data-playwright-test-label='calendar-day-not-completed'
3231
>
3332
<GreenNotCompleted />
3433
</span>
3534
);
3635
}
37-
3836
function DailyCodingChallengeCalendarDay({
3937
dayNumber,
4038
date,
4139
isAvailable = false,
42-
title,
40+
title = '',
4341
completedLanguages = [],
4442
challengeNumber
4543
}: CalendarDayProps): JSX.Element {
4644
const { t } = useTranslation();
45+
const completed = completedLanguages.length > 0;
4746

4847
// dayNumber = 0 -> render nothing
4948
if (dayNumber === 0) return <div></div>;
@@ -74,40 +73,29 @@ function DailyCodingChallengeCalendarDay({
7473
{dayNumber}
7574
</span>
7675

77-
<div className='dc-number'>#{challengeNumber}</div>
76+
<span className='dc-number'>#{challengeNumber}</span>
7877

7978
<div className='dc-info'>
80-
<div className='dc-title'>{title}</div>
79+
<div className='dc-title-wrap'>
80+
<div className='dc-title'>{truncate(title)}</div>
81+
</div>
8182

82-
{completedLanguages.length === 2 ? (
83-
<span className='dc-checkmark dc-big-checkmark completed'>
84-
<span className='dc-spacer'>
85-
<Spacer size='s' />
86-
</span>
87-
<GreenPass />
88-
</span>
89-
) : (
90-
<div className='dc-languages'>
91-
<hr />
92-
<div className='dc-language'>
93-
<div className='dc-language-icon'>
94-
<JavaScriptIcon />
95-
</div>
96-
<div className='dc-language-name'>JavaScript</div>
97-
<Checkmark
98-
completed={completedLanguages.includes('javascript')}
99-
/>
100-
</div>
83+
<Checkmark isCompleted={completed} />
10184

102-
<div className='dc-language'>
103-
<div className='dc-language-icon'>
104-
<PythonIcon />
105-
</div>
106-
<div className='dc-language-name'>Python</div>
107-
<Checkmark completed={completedLanguages.includes('python')} />
85+
<div className='dc-languages'>
86+
{completedLanguages.includes('javascript') && (
87+
<div className='dc-language-icon'>
88+
<JavaScriptIcon />
89+
<span className='sr-only'>JavaScript</span>
90+
</div>
91+
)}
92+
{completedLanguages.includes('python') && (
93+
<div className='dc-language-icon'>
94+
<PythonIcon />
95+
<span className='sr-only'>Python</span>
10896
</div>
109-
</div>
110-
)}
97+
)}
98+
</div>
11199
</div>
112100
</Link>
113101
);

client/src/components/daily-coding-challenge/calendar.css

Lines changed: 62 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
.calendar-day {
3030
position: relative;
31-
padding: 10px 10px 20px;
31+
padding: 5px;
3232
min-height: 200px;
3333
border: 1px solid var(--tertiary-color);
3434
background-color: var(--primary-background);
@@ -37,41 +37,61 @@
3737

3838
.calendar-day-number {
3939
position: absolute;
40+
font-size: 0.8em;
4041
top: 0;
41-
left: 5px;
42+
right: 5px;
43+
color: var(--gray-45);
4244
}
4345

4446
.dc-number {
47+
position: absolute;
48+
top: 0;
49+
left: 5px;
50+
font-size: 0.8em;
4551
font-style: italic;
4652
color: var(--gray-45);
47-
text-align: center;
4853
}
4954

5055
.dc-info {
56+
position: relative;
57+
padding-top: 15px;
5158
display: flex;
5259
flex-direction: column;
5360
height: 100%;
5461
}
5562

56-
.dc-title {
63+
.dc-title-wrap {
5764
width: 100%;
65+
min-height: 55px;
66+
display: flex;
67+
align-items: center;
68+
justify-content: center;
69+
padding: 2px 10px;
70+
}
71+
72+
.dc-title {
5873
text-align: center;
59-
align-self: center;
60-
margin-top: 5px;
61-
height: 50px;
62-
margin-bottom: -5px;
74+
font-size: 0.9em;
6375
}
6476

65-
.dc-languages {
66-
padding: 0 15px;
77+
.dc-checkmark {
78+
width: 100%;
79+
position: absolute;
80+
top: 50%;
81+
}
82+
83+
.dc-checkmark svg {
84+
width: 50px;
85+
height: 50px;
86+
margin: 0 auto;
6787
}
6888

69-
.dc-language {
70-
font-size: 0.8rem;
89+
.dc-languages {
90+
position: absolute;
91+
bottom: 0;
92+
left: 0;
7193
display: flex;
72-
justify-content: space-between;
73-
align-items: center;
74-
gap: 10px;
94+
gap: 2px;
7595
}
7696

7797
.dc-language-icon {
@@ -83,25 +103,6 @@
83103
height: 25px;
84104
}
85105

86-
.dc-small-checkmark {
87-
position: relative;
88-
/* top: -5px; */
89-
}
90-
91-
.dc-small-checkmark svg {
92-
width: 20px;
93-
height: 20px;
94-
}
95-
96-
.dc-big-checkmark {
97-
margin: 0 auto;
98-
}
99-
100-
.dc-big-checkmark svg {
101-
width: 50px;
102-
height: 50px;
103-
}
104-
105106
.not-available:hover,
106107
.not-available:active {
107108
cursor: not-allowed;
@@ -132,6 +133,17 @@
132133
stroke: var(--primary-background);
133134
}
134135

136+
.dc-language-icon svg path {
137+
fill: var(--gray-45);
138+
stroke: var(--gray-45);
139+
}
140+
141+
.available:hover .dc-language-icon svg path,
142+
.available:active .dc-language-icon svg path {
143+
fill: var(--quaternary-background);
144+
stroke: var(--quaternary-background);
145+
}
146+
135147
.available:hover .not-completed svg circle,
136148
.available:active .not-completed svg circle {
137149
fill: var(--primary-color);
@@ -162,74 +174,41 @@
162174
}
163175
}
164176

165-
@media (max-width: 1345px) {
166-
.calendar-day-number,
167-
.dc-number,
168-
.dc-title {
169-
font-size: 0.8rem;
170-
}
171-
172-
.dc-info hr {
173-
margin: 10px 0;
174-
}
175-
176-
.calendar-day {
177-
min-height: 170px;
178-
}
179-
180-
.dc-language {
181-
justify-content: center;
182-
}
183-
184-
.dc-language-name {
185-
display: none;
186-
}
187-
}
188-
189-
@media (max-width: 1115px) {
190-
.calendar-grid {
191-
max-width: unset;
192-
}
193-
177+
@media (max-width: 815px) {
194178
.calendar-day {
195-
min-height: 125px;
196-
padding: 10px;
179+
min-height: 100px;
180+
padding: 0;
197181
}
198182

199-
.dc-title,
200-
.dc-info hr {
183+
.calendar-day-number {
201184
display: none;
202185
}
203186

204187
.dc-info {
205-
display: flex;
188+
padding: 0;
206189
justify-content: center;
207-
align-items: center;
208-
height: 80%;
209190
}
210191

211-
.dc-spacer {
192+
.dc-title-wrap {
212193
display: none;
213194
}
214-
}
215195

216-
@media (max-width: 815px) {
217-
.calendar-day {
218-
min-height: 100px;
219-
padding: 0;
196+
.dc-checkmark {
197+
top: unset;
220198
}
221199

222-
.dc-number {
223-
text-align: right;
224-
padding-right: 5px;
200+
.dc-checkmark svg {
201+
width: 40px;
202+
height: 40px;
225203
}
204+
}
226205

227-
.dc-languages {
206+
@media (max-width: 1300px) {
207+
.dc-title-wrap {
228208
padding: 0;
229209
}
230210

231-
.dc-big-checkmark svg {
232-
width: 40px;
233-
height: 40px;
211+
.dc-title {
212+
font-size: 0.8em;
234213
}
235214
}

client/src/components/daily-coding-challenge/helpers.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,10 @@ export function formatDisplayDate(dateString: string) {
3333
}
3434
return format(parsedDate, 'MMMM d, yyyy');
3535
}
36+
37+
export function truncate(str: string, maxLength = 35) {
38+
if (str.length <= maxLength) {
39+
return str;
40+
}
41+
return str.slice(0, maxLength) + '...';
42+
}

e2e/daily-coding-challenge.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ test.describe('Daily Coding Challenge Archive', () => {
249249

250250
await expect(page.getByTestId('calendar-day-completed')).toHaveCount(1);
251251

252-
await expect(page.getByTestId('calendar-day-not-completed')).toHaveCount(3);
252+
await expect(page.getByTestId('calendar-day-not-completed')).toHaveCount(1);
253253

254254
await page.getByTestId('calendar-day-completed').click();
255255
await expect(page).toHaveURL(

0 commit comments

Comments
 (0)