From 7802d05fa5a7b4b90320e88196925d6116341060 Mon Sep 17 00:00:00 2001 From: Zaira <33151350+zairahira@users.noreply.github.com> Date: Wed, 11 Dec 2024 01:41:58 +0500 Subject: [PATCH] feat(curriculum): add mood board lab for React props (#57205) Co-authored-by: moT01 <20648924+moT01@users.noreply.github.com> Co-authored-by: Kolade Chris <65571316+Ksound22@users.noreply.github.com> --- client/i18n/locales/english/intro.json | 7 +- .../lab-mood-board/index.md | 9 + .../challenges/_meta/lab-mood-board/meta.json | 11 + .../673b3d6b7ef7318eef926d5a.md | 354 ++++++++++++++++++ .../superblock-structure/full-stack.json | 1 + 5 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 client/src/pages/learn/full-stack-developer/lab-mood-board/index.md create mode 100644 curriculum/challenges/_meta/lab-mood-board/meta.json create mode 100644 curriculum/challenges/english/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index 018d7d731f6..29c6cf939fb 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -3324,7 +3324,12 @@ ] }, "cdfr": { "title": "263", "intro": [] }, - "bgtd": { "title": "264", "intro": [] }, + "lab-mood-board": { + "title": "Build a Mood Board", + "intro": [ + "In this lab, you will create a mood board using a React with props." + ] + }, "review-react-basics": { "title": "React Basics Review", "intro": [ diff --git a/client/src/pages/learn/full-stack-developer/lab-mood-board/index.md b/client/src/pages/learn/full-stack-developer/lab-mood-board/index.md new file mode 100644 index 00000000000..6364ec695a3 --- /dev/null +++ b/client/src/pages/learn/full-stack-developer/lab-mood-board/index.md @@ -0,0 +1,9 @@ +--- +title: Introduction to the Build a Mood Board +block: lab-mood-board +superBlock: full-stack-developer +--- + +## Introduction to the Build a Mood Board + +In this lab, you will create a mood board using a React with props. diff --git a/curriculum/challenges/_meta/lab-mood-board/meta.json b/curriculum/challenges/_meta/lab-mood-board/meta.json new file mode 100644 index 00000000000..01d3dc71e08 --- /dev/null +++ b/curriculum/challenges/_meta/lab-mood-board/meta.json @@ -0,0 +1,11 @@ +{ + "name": "Build a Mood Board", + "isUpcomingChange": true, + "usesMultifileEditor": true, + "dashedName": "lab-mood-board", + "superBlock": "full-stack-developer", + "challengeOrder": [{ "id": "673b3d6b7ef7318eef926d5a", "title": "Build a Mood Board" }], + "helpCategory": "HTML-CSS", + "blockLayout": "link", + "blockType": "lab" +} diff --git a/curriculum/challenges/english/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md b/curriculum/challenges/english/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md new file mode 100644 index 00000000000..3a892ab0e37 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/lab-mood-board/673b3d6b7ef7318eef926d5a.md @@ -0,0 +1,354 @@ +--- +id: 673b3d6b7ef7318eef926d5a +title: Build a Mood Board +challengeType: 14 +dashedName: build-a-mood-board +demoType: onClick +--- + +# --description-- + +A mood board is a collage of images and text that conveys a general idea, goal, or feeling about a particular topic. + +In this lab, you will create a mood board using reusable React components. The CSS has already been provided for you. + +Fulfil the user stories below and get all the tests to pass to complete the lab. + +**User Stories:** + +1. You should create and export a `MoodBoardItem` component that accepts three props: `color`, `image`, and `description`. +2. Your `MoodBoardItem` component should return a `div` with the class `mood-board-item` as its top-level element. +3. You should set the background color of the `.mood-board-item` element to the value of the `color` prop using inline styles. +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. +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. +6. You should create and export a `MoodBoard`. +7. Your `MoodBoard` component should return a `div` as its top-level element. +8. Your `MoodBoard` component should render an `h1` element with a class of `mood-board-heading` and the text `Destination Mood Board`. +9. Your `MoodBoard` component should render a `div` with a class of `mood-board`. +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. + +You can use the following images in your Mood Board if you would like: + +- `https://cdn.freecodecamp.org/curriculum/labs/pathway.jpg` +- `https://cdn.freecodecamp.org/curriculum/labs/shore.jpg` +- `https://cdn.freecodecamp.org/curriculum/labs/grass.jpg` +- `https://cdn.freecodecamp.org/curriculum/labs/ship.jpg` +- `https://cdn.freecodecamp.org/curriculum/labs/santorini.jpg` +- `https://cdn.freecodecamp.org/curriculum/labs/pigeon.jpg` + + +# --hints-- + +You should export a `MoodBoardItem` component. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem)); +assert.lengthOf(mockedComponent.find('MoodBoardItem'), 1); +``` + +Your `MoodBoardItem` component should return a `div` with a class of `mood-board-item` at its top-level element. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem)); +assert.equal(mockedComponent.childAt(0).type(), 'div'); +assert.isTrue(mockedComponent.childAt(0).hasClass('mood-board-item')); +``` + +The background color of the `.mood-board-item` element should be set to the value of `color` prop using inline styles. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem)); +mockedComponent.setProps({ color: "colorValue" }); +assert.equal(mockedComponent.find('.mood-board-item').prop('style').backgroundColor, 'colorValue'); +``` + +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. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem)); +mockedComponent.setProps({ image: "imageValue" }); +const img = mockedComponent.find('img.mood-board-image'); +assert.lengthOf(img, 1); +assert.equal(img.prop('src'), 'imageValue'); +``` + +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. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoardItem)); +mockedComponent.setProps({ description: "descriptionValue" }); +const h3 = mockedComponent.find('h3.mood-board-text'); +assert.lengthOf(h3, 1); +assert.equal(h3.text(), 'descriptionValue'); +``` + +You should export a `MoodBoard` component. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard)); +assert.lengthOf(mockedComponent.find('MoodBoard'), 1); +``` + +Your `MoodBoard` component should return a `div` as its top-level element. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard)); +assert.equal(mockedComponent.childAt(0).type(), 'div'); +``` + +Your `MoodBoard` component should render an `h1` element with a class of `mood-board-heading` and the text `Destination Mood Board`. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard)); +const h1 = mockedComponent.find('h1.mood-board-heading'); +assert.lengthOf(h1, 1); +assert.equal(h1.text(), 'Destination Mood Board'); +``` + +Your `MoodBoard` component should render at least three `MoodBoardItem` components, each should pass `color`, `image`, and `description` props with valid values. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard)); +const mbItems = mockedComponent.find(window.index.MoodBoardItem); +assert.isAtLeast(mbItems.length, 3) +const propsList = mbItems.map(item => item.props()); +propsList.forEach(({ color, image, description }) => { + assert.isAtLeast(color.length, 1); + assert.isAtLeast(image.length, 1); + assert.isAtLeast(description.length, 1); +}); +``` + +Your `MoodBoard` component should be rendered to the page's `#root` element. + +```js +const mockedComponent = Enzyme.mount(React.createElement(window.index.MoodBoard)); +assert.equal(mockedComponent.html(), document.getElementById('root').innerHTML); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + + Mood Board + + + + + + + + +
+ + + + +``` + +```css +body { + background-color: #ffffcc; +} + +.mood-board-heading { + text-align: center; + font-size: 2.5em; + color: #333; + margin-top: 20px; +} + +.mood-board { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; + padding: 20px; + max-width: 900px; + margin: 0 auto; +} + +.mood-board-item { + border-radius: 10px; + padding: 10px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + text-align: center; + height: 250px; +} + +.mood-board-image { + border-radius: 5px; + width: 180px; + height:150px; + object-fit: cover; +} + +.mood-board-text { + margin-top: 20px; + font-size: 1.2em; +} +``` + +```jsx + +``` + +# --solutions-- + +```html + + + + + + Mood Board + + + + + + + + +
+ + + + +``` + +```css +body { + background-color: #ffffcc; +} + +.mood-board-heading { + text-align: center; + font-size: 2.5em; + color: #333; + margin-top: 20px; +} + +.mood-board { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; + padding: 20px; + max-width: 900px; + margin: 0 auto; +} + +.mood-board-item { + border-radius: 10px; + padding: 10px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: #fff; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + text-align: center; + height: 250px; +} + +.mood-board-image { + border-radius: 5px; + width: 180px; + height:150px; + object-fit: cover; +} + +.mood-board-text { + margin-top: 20px; + font-size: 1.2em; +} +``` + +```jsx +export function MoodBoardItem(props) { + return ( +
+ Mood +

{props.description}

+
+ ); +} + +export function MoodBoard() { + return ( +
+

Destination Mood Board

+
+ + + + + + +
+
+ ); +} +``` diff --git a/curriculum/superblock-structure/full-stack.json b/curriculum/superblock-structure/full-stack.json index 247f5b20e1a..5fa9571ed7d 100644 --- a/curriculum/superblock-structure/full-stack.json +++ b/curriculum/superblock-structure/full-stack.json @@ -551,6 +551,7 @@ { "dashedName": "lab-reusable-footer" }, { "dashedName": "lecture-working-with-data-in-react" }, { "dashedName": "workshop-reusable-mega-navbar" }, + { "dashedName": "lab-mood-board" }, { "dashedName": "review-react-basics" }, { "dashedName": "quiz-react-basics" } ]