Skip to content

Commit 7802d05

Browse files
zairahiramoT01Ksound22
authored
feat(curriculum): add mood board lab for React props (freeCodeCamp#57205)
Co-authored-by: moT01 <[email protected]> Co-authored-by: Kolade Chris <[email protected]>
1 parent 2c7932d commit 7802d05

File tree

5 files changed

+381
-1
lines changed

5 files changed

+381
-1
lines changed

client/i18n/locales/english/intro.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3324,7 +3324,12 @@
33243324
]
33253325
},
33263326
"cdfr": { "title": "263", "intro": [] },
3327-
"bgtd": { "title": "264", "intro": [] },
3327+
"lab-mood-board": {
3328+
"title": "Build a Mood Board",
3329+
"intro": [
3330+
"In this lab, you will create a mood board using a React with props."
3331+
]
3332+
},
33283333
"review-react-basics": {
33293334
"title": "React Basics Review",
33303335
"intro": [
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
title: Introduction to the Build a Mood Board
3+
block: lab-mood-board
4+
superBlock: full-stack-developer
5+
---
6+
7+
## Introduction to the Build a Mood Board
8+
9+
In this lab, you will create a mood board using a React with props.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "Build a Mood Board",
3+
"isUpcomingChange": true,
4+
"usesMultifileEditor": true,
5+
"dashedName": "lab-mood-board",
6+
"superBlock": "full-stack-developer",
7+
"challengeOrder": [{ "id": "673b3d6b7ef7318eef926d5a", "title": "Build a Mood Board" }],
8+
"helpCategory": "HTML-CSS",
9+
"blockLayout": "link",
10+
"blockType": "lab"
11+
}
Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
---
2+
id: 673b3d6b7ef7318eef926d5a
3+
title: Build a Mood Board
4+
challengeType: 14
5+
dashedName: build-a-mood-board
6+
demoType: onClick
7+
---
8+
9+
# --description--
10+
11+
A mood board is a collage of images and text that conveys a general idea, goal, or feeling about a particular topic.
12+
13+
In this lab, you will create a mood board using reusable React components. The CSS has already been provided for you.
14+
15+
Fulfil the user stories below and get all the tests to pass to complete the lab.
16+
17+
**User Stories:**
18+
19+
1. You should create and export a `MoodBoardItem` component that accepts three props: `color`, `image`, and `description`.
20+
2. Your `MoodBoardItem` component should return a `div` with the class `mood-board-item` as its top-level element.
21+
3. You should set the background color of the `.mood-board-item` element to the value of the `color` prop using inline styles.
22+
4. You should render an `img` element, with a class of `mood-board-image` and its `src` attribute set to the value of the `image` prop, within the `.mood-board-item` element.
23+
5. You should render an `h3` element, with a class of `mood-board-text` and its text the value of the `description` prop, within the `.mood-board-item` element.
24+
6. You should create and export a `MoodBoard`.
25+
7. Your `MoodBoard` component should return a `div` as its top-level element.
26+
8. Your `MoodBoard` component should render an `h1` element with a class of `mood-board-heading` and the text `Destination Mood Board`.
27+
9. Your `MoodBoard` component should render a `div` with a class of `mood-board`.
28+
10. Your `MoodBoard` component should render at least three `MoodBoardItem` components within the `.mood-board` element, each should pass `color`, `image`, and `description` props with valid values.
29+
30+
You can use the following images in your Mood Board if you would like:
31+
32+
- `https://cdn.freecodecamp.org/curriculum/labs/pathway.jpg`
33+
- `https://cdn.freecodecamp.org/curriculum/labs/shore.jpg`
34+
- `https://cdn.freecodecamp.org/curriculum/labs/grass.jpg`
35+
- `https://cdn.freecodecamp.org/curriculum/labs/ship.jpg`
36+
- `https://cdn.freecodecamp.org/curriculum/labs/santorini.jpg`
37+
- `https://cdn.freecodecamp.org/curriculum/labs/pigeon.jpg`
38+
39+
40+
# --hints--
41+
42+
You should export a `MoodBoardItem` component.
43+
44+
```js
45+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
46+
assert.lengthOf(mockedComponent.find('MoodBoardItem'), 1);
47+
```
48+
49+
Your `MoodBoardItem` component should return a `div` with a class of `mood-board-item` at its top-level element.
50+
51+
```js
52+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
53+
assert.equal(mockedComponent.childAt(0).type(), 'div');
54+
assert.isTrue(mockedComponent.childAt(0).hasClass('mood-board-item'));
55+
```
56+
57+
The background color of the `.mood-board-item` element should be set to the value of `color` prop using inline styles.
58+
59+
```js
60+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
61+
mockedComponent.setProps({ color: "colorValue" });
62+
assert.equal(mockedComponent.find('.mood-board-item').prop('style').backgroundColor, 'colorValue');
63+
```
64+
65+
Your `MoodBoardItem` component should render an `img` element with a class of `mood-board-image` and its `src` set to the value of the `image` prop.
66+
67+
```js
68+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
69+
mockedComponent.setProps({ image: "imageValue" });
70+
const img = mockedComponent.find('img.mood-board-image');
71+
assert.lengthOf(img, 1);
72+
assert.equal(img.prop('src'), 'imageValue');
73+
```
74+
75+
Your `MoodBoardItem` component should render an `h3` element with a class of `mood-board-text` and its text set to the value of the `description` prop.
76+
77+
```js
78+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem));
79+
mockedComponent.setProps({ description: "descriptionValue" });
80+
const h3 = mockedComponent.find('h3.mood-board-text');
81+
assert.lengthOf(h3, 1);
82+
assert.equal(h3.text(), 'descriptionValue');
83+
```
84+
85+
You should export a `MoodBoard` component.
86+
87+
```js
88+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
89+
assert.lengthOf(mockedComponent.find('MoodBoard'), 1);
90+
```
91+
92+
Your `MoodBoard` component should return a `div` as its top-level element.
93+
94+
```js
95+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
96+
assert.equal(mockedComponent.childAt(0).type(), 'div');
97+
```
98+
99+
Your `MoodBoard` component should render an `h1` element with a class of `mood-board-heading` and the text `Destination Mood Board`.
100+
101+
```js
102+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
103+
const h1 = mockedComponent.find('h1.mood-board-heading');
104+
assert.lengthOf(h1, 1);
105+
assert.equal(h1.text(), 'Destination Mood Board');
106+
```
107+
108+
Your `MoodBoard` component should render at least three `MoodBoardItem` components, each should pass `color`, `image`, and `description` props with valid values.
109+
110+
```js
111+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
112+
const mbItems = mockedComponent.find(window.index.MoodBoardItem);
113+
assert.isAtLeast(mbItems.length, 3)
114+
const propsList = mbItems.map(item => item.props());
115+
propsList.forEach(({ color, image, description }) => {
116+
assert.isAtLeast(color.length, 1);
117+
assert.isAtLeast(image.length, 1);
118+
assert.isAtLeast(description.length, 1);
119+
});
120+
```
121+
122+
Your `MoodBoard` component should be rendered to the page's `#root` element.
123+
124+
```js
125+
const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard));
126+
assert.equal(mockedComponent.html(), document.getElementById('root').innerHTML);
127+
```
128+
129+
# --seed--
130+
131+
## --seed-contents--
132+
133+
```html
134+
<!DOCTYPE html>
135+
<html>
136+
137+
<head>
138+
<meta charset="UTF-8" />
139+
<title>Mood Board</title>
140+
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
141+
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
142+
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
143+
<script
144+
data-plugins="transform-modules-umd"
145+
type="text/babel"
146+
src="index.jsx"
147+
></script>
148+
<link rel="stylesheet" href="styles.css" />
149+
</head>
150+
151+
<body>
152+
<div id="root"></div>
153+
<script
154+
data-plugins="transform-modules-umd"
155+
type="text/babel"
156+
data-presets="react"
157+
data-type="module"
158+
>
159+
import { MoodBoard } from './index.jsx';
160+
ReactDOM.createRoot(document.getElementById('root')).render(
161+
<MoodBoard />
162+
);
163+
</script>
164+
</body>
165+
166+
</html>
167+
```
168+
169+
```css
170+
body {
171+
background-color: #ffffcc;
172+
}
173+
174+
.mood-board-heading {
175+
text-align: center;
176+
font-size: 2.5em;
177+
color: #333;
178+
margin-top: 20px;
179+
}
180+
181+
.mood-board {
182+
display: grid;
183+
grid-template-columns: repeat(3, 1fr);
184+
gap: 20px;
185+
padding: 20px;
186+
max-width: 900px;
187+
margin: 0 auto;
188+
}
189+
190+
.mood-board-item {
191+
border-radius: 10px;
192+
padding: 10px;
193+
display: flex;
194+
flex-direction: column;
195+
align-items: center;
196+
justify-content: center;
197+
color: #fff;
198+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
199+
text-align: center;
200+
height: 250px;
201+
}
202+
203+
.mood-board-image {
204+
border-radius: 5px;
205+
width: 180px;
206+
height:150px;
207+
object-fit: cover;
208+
}
209+
210+
.mood-board-text {
211+
margin-top: 20px;
212+
font-size: 1.2em;
213+
}
214+
```
215+
216+
```jsx
217+
218+
```
219+
220+
# --solutions--
221+
222+
```html
223+
<!DOCTYPE html>
224+
<html>
225+
226+
<head>
227+
<meta charset="UTF-8" />
228+
<title>Mood Board</title>
229+
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
230+
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
231+
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
232+
<script
233+
data-plugins="transform-modules-umd"
234+
type="text/babel"
235+
src="index.jsx"
236+
></script>
237+
<link rel="stylesheet" href="styles.css" />
238+
</head>
239+
240+
<body>
241+
<div id="root"></div>
242+
<script
243+
data-plugins="transform-modules-umd"
244+
type="text/babel"
245+
data-presets="react"
246+
data-type="module"
247+
>
248+
import { MoodBoard } from './index.jsx';
249+
ReactDOM.createRoot(document.getElementById('root')).render(
250+
<MoodBoard />
251+
);
252+
</script>
253+
</body>
254+
255+
</html>
256+
```
257+
258+
```css
259+
body {
260+
background-color: #ffffcc;
261+
}
262+
263+
.mood-board-heading {
264+
text-align: center;
265+
font-size: 2.5em;
266+
color: #333;
267+
margin-top: 20px;
268+
}
269+
270+
.mood-board {
271+
display: grid;
272+
grid-template-columns: repeat(3, 1fr);
273+
gap: 20px;
274+
padding: 20px;
275+
max-width: 900px;
276+
margin: 0 auto;
277+
}
278+
279+
.mood-board-item {
280+
border-radius: 10px;
281+
padding: 10px;
282+
display: flex;
283+
flex-direction: column;
284+
align-items: center;
285+
justify-content: center;
286+
color: #fff;
287+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
288+
text-align: center;
289+
height: 250px;
290+
}
291+
292+
.mood-board-image {
293+
border-radius: 5px;
294+
width: 180px;
295+
height:150px;
296+
object-fit: cover;
297+
}
298+
299+
.mood-board-text {
300+
margin-top: 20px;
301+
font-size: 1.2em;
302+
}
303+
```
304+
305+
```jsx
306+
export function MoodBoardItem(props) {
307+
return (
308+
<div className="mood-board-item" style={{ backgroundColor: props.color }}>
309+
<img src={props.image} alt="Mood" className="mood-board-image" />
310+
<h3 className="mood-board-text">{props.description}</h3>
311+
</div>
312+
);
313+
}
314+
315+
export function MoodBoard() {
316+
return (
317+
<div>
318+
<h1 className="mood-board-heading">Destination Mood Board</h1>
319+
<div className="mood-board">
320+
<MoodBoardItem
321+
color="#2da64f"
322+
image="https://cdn.freecodecamp.org/curriculum/labs/pathway.jpg"
323+
description="Carribean"
324+
/>
325+
<MoodBoardItem
326+
color="#8e44ad"
327+
image="https://cdn.freecodecamp.org/curriculum/labs/shore.jpg"
328+
description="Gawadar Beach"
329+
/>
330+
<MoodBoardItem
331+
color="#3498db"
332+
image="https://cdn.freecodecamp.org/curriculum/labs/grass.jpg"
333+
description="Cape Town"
334+
/>
335+
<MoodBoardItem
336+
color="#bf3d7e"
337+
image="https://cdn.freecodecamp.org/curriculum/labs/ship.jpg"
338+
description="Suez Canal"
339+
/>
340+
<MoodBoardItem
341+
color="#e74c3c"
342+
image="https://cdn.freecodecamp.org/curriculum/labs/santorini.jpg"
343+
description="Santorini"
344+
/>
345+
<MoodBoardItem
346+
color="#95a5a6"
347+
image="https://cdn.freecodecamp.org/curriculum/labs/pigeon.jpg"
348+
description="Istanbul"
349+
/>
350+
</div>
351+
</div>
352+
);
353+
}
354+
```

curriculum/superblock-structure/full-stack.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@
551551
{ "dashedName": "lab-reusable-footer" },
552552
{ "dashedName": "lecture-working-with-data-in-react" },
553553
{ "dashedName": "workshop-reusable-mega-navbar" },
554+
{ "dashedName": "lab-mood-board" },
554555
{ "dashedName": "review-react-basics" },
555556
{ "dashedName": "quiz-react-basics" }
556557
]

0 commit comments

Comments
 (0)