From b0e616a35a045d5d7ceabc32fc63553b231b425d Mon Sep 17 00:00:00 2001 From: Kolade Chris <65571316+Ksound22@users.noreply.github.com> Date: Wed, 7 May 2025 21:49:18 +0100 Subject: [PATCH] feat(curriculum): adding superhero application form (React forms) workshop (#59932) Co-authored-by: Oliver Eyton-Williams Co-authored-by: Tom <20648924+moT01@users.noreply.github.com> --- client/i18n/locales/english/intro.json | 8 +- .../index.md | 9 + .../meta.json | 97 ++++ .../6808fe91a5cb0c3355f23027.md | 157 +++++++ .../680900675ae3d54ee19590c3.md | 196 ++++++++ .../680900675ae3d54ee19590c4.md | 148 ++++++ .../680900675ae3d54ee19590c5.md | 162 +++++++ .../680900675ae3d54ee19590c6.md | 151 +++++++ .../680900675ae3d54ee19590c7.md | 177 ++++++++ .../680900675ae3d54ee19590c8.md | 171 +++++++ .../680900675ae3d54ee19590c9.md | 214 +++++++++ .../680900675ae3d54ee19590ca.md | 204 +++++++++ .../680900675ae3d54ee19590cb.md | 234 ++++++++++ .../680900675ae3d54ee19590cc.md | 185 ++++++++ .../680900675ae3d54ee19590cd.md | 188 ++++++++ .../680900675ae3d54ee19590ce.md | 217 +++++++++ .../680900675ae3d54ee19590cf.md | 208 +++++++++ .../680900675ae3d54ee19590d0.md | 211 +++++++++ .../680900675ae3d54ee19590d1.md | 216 +++++++++ .../680900675ae3d54ee19590d2.md | 222 +++++++++ .../680900675ae3d54ee19590d3.md | 424 ++++++++++++++++++ .../680fc849a6f2be0a8597c593.md | 198 ++++++++ .../68148d280ee30e5a567a0e2d.md | 208 +++++++++ .../68149b101d905a6fc2fcd6d8.md | 208 +++++++++ .../superblock-structure/full-stack.json | 3 + 25 files changed, 4413 insertions(+), 3 deletions(-) create mode 100644 client/src/pages/learn/full-stack-developer/workshop-superhero-application-form/index.md create mode 100644 curriculum/challenges/_meta/workshop-superhero-application-form/meta.json create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/6808fe91a5cb0c3355f23027.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c3.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c4.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c5.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c6.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c7.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c8.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c9.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ca.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cb.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cc.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cd.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ce.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cf.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d0.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d1.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d2.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d3.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680fc849a6f2be0a8597c593.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68148d280ee30e5a567a0e2d.md create mode 100644 curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68149b101d905a6fc2fcd6d8.md diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index a6816b21933..444e5e30224 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -3539,9 +3539,11 @@ "In these lecture videos, you will learn about working with forms in React." ] }, - "sgau": { - "title": "276", - "intro": [] + "workshop-superhero-application-form": { + "title": "Build a Superhero Application Form", + "intro": [ + "In this workshop, you will build a superhero application form." + ] }, "lab-event-rsvp": { "title": "Build an Event RSVP", diff --git a/client/src/pages/learn/full-stack-developer/workshop-superhero-application-form/index.md b/client/src/pages/learn/full-stack-developer/workshop-superhero-application-form/index.md new file mode 100644 index 00000000000..73193bbd234 --- /dev/null +++ b/client/src/pages/learn/full-stack-developer/workshop-superhero-application-form/index.md @@ -0,0 +1,9 @@ +--- +title: Introduction to the Build a Superhero Application Form +block: workshop-superhero-application-form +superBlock: full-stack-developer +--- + +## Introduction to the Build a Superhero Application Form + +This is workshop will cover how to work with forms in React. diff --git a/curriculum/challenges/_meta/workshop-superhero-application-form/meta.json b/curriculum/challenges/_meta/workshop-superhero-application-form/meta.json new file mode 100644 index 00000000000..900d3de4f51 --- /dev/null +++ b/curriculum/challenges/_meta/workshop-superhero-application-form/meta.json @@ -0,0 +1,97 @@ +{ + "name": "Build a Superhero Application Form", + "isUpcomingChange": true, + "usesMultifileEditor": true, + "hasEditableBoundaries": true, + "blockType": "workshop", + "blockLayout": "challenge-grid", + "dashedName": "workshop-superhero-application-form", + "superBlock": "full-stack-developer", + "challengeOrder": [ + { + "id": "6808fe91a5cb0c3355f23027", + "title": "Step 1" + }, + { + "id": "680900675ae3d54ee19590c3", + "title": "Step 2" + }, + { + "id": "680fc849a6f2be0a8597c593", + "title": "Step 3" + }, + { + "id": "680900675ae3d54ee19590c4", + "title": "Step 4" + }, + { + "id": "680900675ae3d54ee19590c5", + "title": "Step 5" + }, + { + "id": "680900675ae3d54ee19590c6", + "title": "Step 6" + }, + { + "id": "680900675ae3d54ee19590c7", + "title": "Step 7" + }, + { + "id": "680900675ae3d54ee19590c8", + "title": "Step 8" + }, + { + "id": "680900675ae3d54ee19590c9", + "title": "Step 9" + }, + { + "id": "680900675ae3d54ee19590ca", + "title": "Step 10" + }, + { + "id": "680900675ae3d54ee19590cb", + "title": "Step 11" + }, + { + "id": "680900675ae3d54ee19590cc", + "title": "Step 12" + }, + { + "id": "680900675ae3d54ee19590cd", + "title": "Step 13" + }, + { + "id": "680900675ae3d54ee19590ce", + "title": "Step 14" + }, + { + "id": "68148d280ee30e5a567a0e2d", + "title": "Step 15" + }, + { + "id": "680900675ae3d54ee19590cf", + "title": "Step 16" + }, + { + "id": "680900675ae3d54ee19590d0", + "title": "Step 17" + }, + { + "id": "68149b101d905a6fc2fcd6d8", + "title": "Step 18" + }, + { + "id": "680900675ae3d54ee19590d1", + "title": "Step 19" + }, + { + "id": "680900675ae3d54ee19590d2", + "title": "Step 20" + }, + { + "id": "680900675ae3d54ee19590d3", + "title": "Step 21" + } + ], + "helpCategory": "JavaScript" +} \ No newline at end of file diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/6808fe91a5cb0c3355f23027.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/6808fe91a5cb0c3355f23027.md new file mode 100644 index 00000000000..799c364c40e --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/6808fe91a5cb0c3355f23027.md @@ -0,0 +1,157 @@ +--- +id: 6808fe91a5cb0c3355f23027 +title: Step 1 +challengeType: 0 +dashedName: step-1 +demoType: onLoad +--- + +# --description-- + +In this workshop, you'll learn how to work with forms in React by building a superhero application form. + +Some boilerplate has been provided, you just need to create the rest of the React component. + +Begin by returning a `div` element with a `className` of `form-wrap`. Inside the `div`, create an `h2` element with the text `Superhero Application Form`. Below that, create a `p` element with the text `Please complete all fields`. + +# --hints-- + +You should return a `div` element with the `className` of `form-wrap`. + +```js +assert.exists(document?.querySelector("div.form-wrap")); +``` + +You should create an `h2` element inside your `div` element. + +```js +assert.exists(document?.querySelector(".form-wrap > h2")); +``` + +Your `h2` element should have the text `Superhero Application Form`. + +```js +const h2El = document?.querySelector("h2") +assert.equal(h2El?.textContent, "Superhero Application Form"); +``` + +You should create a `p` element inside your `div` element. Make sure it comes after the `h2`. + +```js +assert.exists(document?.querySelector(".form-wrap > h2 + p")); +``` + +Your `p` element should have the text `Please complete all fields`. + +```js +const pEl = document?.querySelector("p") +assert.equal(pEl?.textContent, "Please complete all fields"); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + --fcc-editable-region-- + + --fcc-editable-region-- + +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c3.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c3.md new file mode 100644 index 00000000000..5040c0b456d --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c3.md @@ -0,0 +1,196 @@ +--- +id: 680900675ae3d54ee19590c3 +title: Step 2 +challengeType: 0 +dashedName: step-2 +--- + +# --description-- + +Before building out the form itself, you will create the state variables you need. They are `heroName`, `realName`, `powerSource`, and `powers`. + +For now, create the variables and setters for `heroName` and `realName`. Both should have an intitial value of empty strings. + +# --hints-- + +You should use the array destructuring syntax to set a `heroName` state variable and a `setHeroName` setter. + +```js +assert.match(code, /(const|let)\s+\[\s*heroName\s*,\s*setHeroName\s*\]/); +``` + +Your `heroName` and `setHeroName` should use the `useState` hook. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + assert.isAtLeast(abuseState.calls.length, 1); +} +``` + +Your `useState` hook for `heroName` should have an initial value of empty string. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + assert.equal(abuseState.calls[0]?.[0], ""); +} +``` + +You should use the array destructuring syntax to set a `realName` state variable and a `setRealName` setter. + +```js +assert.match(code, /(const|let)\s+\[\s*realName\s*,\s*setRealName\s*\]/); +``` + +Your `realName` and `setRealName` should use the `useState` hook. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + assert.isAtLeast(abuseState.calls.length, 2); +} +``` + +Your `useState` hook for `realName` should have an initial value of empty string. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + assert.equal(abuseState.calls[1]?.[0], ""); +} +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + --fcc-editable-region-- + + --fcc-editable-region-- + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c4.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c4.md new file mode 100644 index 00000000000..d799decea79 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c4.md @@ -0,0 +1,148 @@ +--- +id: 680900675ae3d54ee19590c4 +title: Step 4 +challengeType: 0 +dashedName: step-4 +--- + +# --description-- + +Below the paragraph, create a `form` element. Within it, add a `div` with a `className` of `section`. + +# --hints-- + +You should create a `form` element. + +```js +assert.exists(document?.querySelector("form")); +``` + +You should create a `div` element inside your `form` element. + +```js +assert.exists(document?.querySelector("form > div")); +``` + +Your `div` element should have a `className` of `section`. + +```js +assert.exists(document?.querySelector("form > div.section")); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+ --fcc-editable-region-- + + --fcc-editable-region-- +
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c5.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c5.md new file mode 100644 index 00000000000..a972e28d011 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c5.md @@ -0,0 +1,162 @@ +--- +id: 680900675ae3d54ee19590c5 +title: Step 5 +challengeType: 0 +dashedName: step-5 +--- + +# --description-- + +Time to create the labels and inputs. In the form, create a `label` with the text `Hero Name` and an `input` element of type `text` inside it. + +Connect the `input` for `Hero Name` to the `heroName` state variable by giving it a `value` attribute set to `heroName`. + +# --hints-- + +You should create a `label` element. + +```js +assert.exists(document?.querySelector("label")); +``` + +Your `label` element should have `Hero Name` as its text. + +```js +const labelEl = document.querySelector("label") +assert.equal(labelEl?.textContent, "Hero Name"); +``` + +You should create an `input` of type `text` element inside your `label` element. + +```js +const inputEl = document.querySelector("label > input"); +assert.equal(inputEl?.getAttribute("type"), "text"); +``` + +Your `input` element should have its value set to the `heroName` state variable. + +```js +assert.match(code, /value\s*=\s*\{\s*heroName\s*\}/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ --fcc-editable-region-- + + --fcc-editable-region-- +
+
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c6.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c6.md new file mode 100644 index 00000000000..90dc1ac9f45 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c6.md @@ -0,0 +1,151 @@ +--- +id: 680900675ae3d54ee19590c6 +title: Step 6 +challengeType: 0 +dashedName: step-6 +--- + +# --description-- + +You may notice you can't type in the `input`. If you open up the console you will see a warning. + +To remove the warning, use the `onChange` event to update `heroName`. The value for the `onChange` event should be an arrow function with `e` for the parameter. The arrow function should implicitly return `setHeroName(e.target.value)`. + +# --hints-- + +Your `input` element should have an `onChange` attribute. + +```js +assert.match(code, /onChange\s*=\s*\{/) +``` + +You should use the `onChange` to set the value of the `heroName` state variable so you can type in the input field. + +```js +assert.match(code, /onChange\s*=\s*\{\s*(e|\(\s*e\s*\))\s*=>\s*setHeroName\s*\(\s*e\s*\.\s*target\s*\.\s*value\s*\)\s*\}/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ --fcc-editable-region-- + + --fcc-editable-region-- +
+
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c7.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c7.md new file mode 100644 index 00000000000..f9d4e38eb02 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c7.md @@ -0,0 +1,177 @@ +--- +id: 680900675ae3d54ee19590c7 +title: Step 7 +challengeType: 0 +dashedName: step-7 +--- + +# --description-- + +Create another `label` with the text `Real Name` and an `input` of type `password` within it. Give the `input` a `value` of `realName`. + +Then use the `onChange` event to update `realName` in the same way you updated `heroName`. + +# --hints-- + +You should create a `label` element. + +```js +const labels = document.querySelectorAll("label"); +assert.lengthOf(labels, 2); +``` + +Your `label` element should have `Real Name` as its text. + +```js +const labels = document.querySelectorAll("label"); +assert.equal(labels[1]?.textContent.trim(), "Real Name"); +``` + +You should create an `input` of type `password` inside your `label` element. + +```js +const inputEl = document.querySelectorAll("label > input"); +assert.equal(inputEl[1]?.getAttribute("type"), "password"); +``` + +Your `input` element should have its value set to the `realName` state variable. + +```js +assert.match(code, /value\s*=\s*\{\s*realName\s*\}/) +``` + +You should use the `onChange` event to set the value of the `realName` state variable so you can type in the `input` field. + +```js +assert.match(code, /onChange\s*=\s*\{\s*(e|\(\s*e\s*\))\s*=>\s*setRealName\s*\(\s*e\s*\.\s*target\s*\.\s*value\s*\)\s*\}/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + --fcc-editable-region-- + + --fcc-editable-region-- +
+
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c8.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c8.md new file mode 100644 index 00000000000..676953d63b3 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c8.md @@ -0,0 +1,171 @@ +--- +id: 680900675ae3d54ee19590c8 +title: Step 8 +challengeType: 0 +dashedName: step-8 +--- + +# --description-- + +Next, create a `label` with the `className` of `section` and `column`, and the text `How did you get your powers?`. Inside the `label`, create a `select` element. + +# --hints-- + +You should create a `label` element with a `className` of `section` and `column`. + +```js +const labelEl = document?.querySelector("label.section.column"); +assert.exists(labelEl); +``` + +Your `label` element should have the text `How did you get your powers?`. + +```js +const labelEl = document?.querySelector("label.section.column"); +assert.equal(labelEl?.textContent, "How did you get your powers?") +``` + +You should create a `select` element inside your `label` element. + +```js +const selectEl = document?.querySelector("label > select"); +assert.exists(selectEl); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ --fcc-editable-region-- + + --fcc-editable-region-- +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c9.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c9.md new file mode 100644 index 00000000000..1389744b350 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590c9.md @@ -0,0 +1,214 @@ +--- +id: 680900675ae3d54ee19590c9 +title: Step 9 +challengeType: 0 +dashedName: step-9 +--- + +# --description-- + +Inside your `select` element, you need to create options for the user to choose as their power source. The `select` should have seven options listed below: + +| Power Source | +|-------------------------------| +| `Select one` | +| `Bitten by a strange creature` | +| `Radioactive exposure` | +| `Science experiment` | +| `Alien heritage ` | +| `Ancient artifact discovery` | +| `Other` | + +# --hints-- + +Your should create the first `option` element with the text `Select one` inside your `select` element. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.equal(optionEls[0]?.textContent, "Select one"); +``` + +Your should create a second `option` element with the text `Bitten by a strange creature` inside your `select` element. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.equal(optionEls[1]?.textContent, "Bitten by a strange creature"); +``` + +Your should create a third `option` element with the text `Radioactive exposure` inside your `select` element. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.equal(optionEls[2]?.textContent, "Radioactive exposure"); +``` + +Your should create a fourth `option` element with the text `Science experiment` inside your `select` element. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.equal(optionEls[3]?.textContent, "Science experiment"); +``` + +Your should create a fifth `option` element with the text `Alien heritage` inside your `select` element. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.equal(optionEls[4]?.textContent, "Alien heritage"); +``` + +Your should create a sixth `option` element with the text `Ancient artifact discovery` inside your `select` element. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.equal(optionEls[5]?.textContent, "Ancient artifact discovery"); +``` + +Your should create a seventh `option` element with the text `Other` inside your `select` element. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.equal(optionEls[6]?.textContent, "Other"); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ca.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ca.md new file mode 100644 index 00000000000..66fabe1f440 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ca.md @@ -0,0 +1,204 @@ +--- +id: 680900675ae3d54ee19590ca +title: Step 10 +challengeType: 0 +dashedName: step-10 +--- + +# --description-- + +To account for the setter function, you will have to attach a `value` attribute and an `onChange` event to the `select` and a `value` attribute to each of the `option` elements. + +That's a long process, right? So the best way to handle this is to have an array of the option values and map over it to create the `option` elements. + +A `powerSourceOptions` array has been added at the top of your component. Give it a look. + +For now, remove all the options inside the `select` element except for the first one. In the next step you will map over the array. + +# --hints-- + +You should have the first option element in your code. + +```js +const optionEl = document?.querySelectorAll("select > option"); +assert.equal(optionEl[0]?.textContent, "Select one"); +``` + +You should remove all the option elements apart from the first one. + +```js +const optionEls = document?.querySelectorAll("select > option"); +assert.lengthOf(optionEls, 1) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cb.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cb.md new file mode 100644 index 00000000000..f38151a8aee --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cb.md @@ -0,0 +1,234 @@ +--- +id: 680900675ae3d54ee19590cb +title: Step 11 +challengeType: 0 +dashedName: step-11 +--- + +# --description-- + +In a prior lecture video, you learned how to render a list of options using the `map()` method like this: + +```jsx +function FruitList() { + const fruits = ["Apple", "Banana", "Cherry", "Date"]; + return ( + + ); +} +``` + +Remember that the `key` must always be unique. It helps React identify which items have changed, and been added or removed. + +After the first `option`, use an arrow function to map through the `powerSourceOptions` array using `source` as the parameter. + +Then inside the `map()` method, create an `option` element with a `key` of `source` and a `value` of `source`. Lastly, use `{source}` to display the name of each power source in the dropdown. + +# --hints-- + +You should map through `powerSourceOptions`. + +```js +assert.match(code, /\{\s*powerSourceOptions\s*\.\s*map\s*\(/) +``` + +You should pass in `source` as the parameter of the map. + +```js +assert.match(code, /\{\s*powerSourceOptions\s*\.\s*map\s*\(\s*(source|\(\s*source\s*\))\s*=>/) +``` + +You should create an `option` element with a `key` of `source` and `value` of `source`. + +```js +assert.match(code, /<\s*option\s+(key\s*=\s*{\s*source\s*}\s*value\s*=\s*{\s*source\s*}|value\s*=\s*{\s*source\s*}\s*key\s*=\s*{\s*source\s*})\s*>\s*{\s*source\s*}\s*<\/\s*option\s*>/) +``` + +You should have a total of seven `option` elements. + +```js +const optionElements = document?.querySelectorAll("option"); +assert.lengthOf(optionElements, 7); +``` + +For the last six `option` elements, each text content should correspond to one of the power source options from the `powerSourceOptions` array. + +```js +const optionElements = document?.querySelectorAll("option"); + +const powerSourceOptions = [ + "Bitten by a strange creature", + "Radioactive exposure", + "Science experiment", + "Alien heritage", + "Ancient artifact discovery", + "Other" +]; + +for (let i = 0; i < powerSourceOptions.length; i++) { + const option = optionElements[i+1]; + const expected = powerSourceOptions[i]; + + assert.strictEqual(option?.textContent, expected); + assert.strictEqual(option.value, expected); +} +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cc.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cc.md new file mode 100644 index 00000000000..bb678384b05 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cc.md @@ -0,0 +1,185 @@ +--- +id: 680900675ae3d54ee19590cc +title: Step 12 +challengeType: 0 +dashedName: step-12 +--- + +# --description-- + +The values of the `powerSourceOptions` now show up as the options for the `select` element. + +Now, use `powerSource` as the value of the `select`. Then, add an `onChange` to set that value using the `setPowerSource` setter function and `e.target.value` like you did with the other form elements. + +# --hints-- + +You should use `{powerSource}` as the value of the `select` element. + +```js +assert.match(code, /<\s*select\s+[\s\S]*value\s*=\s*\{\s*powerSource\s*\}/) +``` + +You should set the value of the `select` element with `onChange` and `setPowerSource`. + +```js +assert.match(code, /<\s*select\s+[\s\S]*onChange\s*=\s*\{\s*(e|\(\s*e\s*\))\s*=>\s*setPowerSource\s*\(\s*e\s*\.\s*target\s*\.\s*value\s*\)/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cd.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cd.md new file mode 100644 index 00000000000..a75f7e3ea6b --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cd.md @@ -0,0 +1,188 @@ +--- +id: 680900675ae3d54ee19590cd +title: Step 13 +challengeType: 0 +dashedName: step-13 +--- + +# --description-- + +The next `input` is a checkbox to mark all super hero powers that apply to the user. + +Create a `label` element with a `className` of `section` and `column`, and the text of `List your powers (select all that apply):`. + +# --hints-- + +You shold create a `label` element with a `className` of `section` and `column`. + +```js +const labelEl = document?.querySelectorAll("label.section.column"); +assert.equal(labelEl?.length, 2) +``` + +Your `label` element should have the text `List your powers (select all that apply):`. + +```js +const labelEl = document?.querySelectorAll("label.section.column"); +assert.equal(labelEl[1]?.textContent, "List your powers (select all that apply):") +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + --fcc-editable-region-- + + --fcc-editable-region-- +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ce.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ce.md new file mode 100644 index 00000000000..4c8da229c93 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590ce.md @@ -0,0 +1,217 @@ +--- +id: 680900675ae3d54ee19590ce +title: Step 14 +challengeType: 0 +dashedName: step-14 +--- + +# --description-- + +There will be six checkboxes, so it's also best to create an array for them and map through them to display them as checkboxes. For that, a `powersOptions` array has been provided for you. + +Use an arrow function to map through the `powersOptions` array using parameter of `power`. Inside the map, create a `label` element with a `key` of `power`, and a text of `Hello`. + +After that, you should see six `Hello` text. You will fill in the elements of the array in the next step. + +# --hints-- + +You should map through `powersOptions`. + +```js +assert.match(code, /\{\s*powersOptions\s*\.\s*map\s*\(/) +``` + +You should use `power` as the parameter of your map. + +```js +assert.match(code, /{\s*powersOptions\s*\.\s*map\s*\(\s*(power|\(\s*power\s*\))\s*=>/) +``` + +You should create a `label` element with a `key` of `power`. + +```js +assert.match(code, /\{\s*powersOptions\s*\.\s*map\s*\([\s\S]*<\s*label\s+key\s*=\s*\{\s*power\s*\}\s*>[\s\S]*<\s*\/\s*label\s*>/) +``` + +Your `label` element should have the text `Hello`. + +```js +const labelEls = document?.querySelectorAll("label") +const targetLabelEls = Array.from(labelEls).slice(4) + +for (const label of targetLabelEls) { + assert.equal(label.textContent, "Hello"); +} +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cf.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cf.md new file mode 100644 index 00000000000..608951a40d8 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590cf.md @@ -0,0 +1,208 @@ +--- +id: 680900675ae3d54ee19590cf +title: Step 16 +challengeType: 0 +dashedName: step-16 +--- + +# --description-- + +To mark the checkboxes, add a `checked` attribute to the checkbox `input`. Use the `includes` method to verify if the current `power` is in the `powers` array. + +The `onChange` will be a separate function, set it to `handlePowersChange` for now. This will lead to an error you will fix in the next step. + +# --hints-- + +You should set the checkbox `checked` state to reflect whether the current `power` value exists in the powers array. + +```js +assert.match(code, /checked\s*=\s*\{\s*powers\s*\.\s*includes\s*\(\s*power\s*\)\s*\}/) +``` + +You should set the checkbox `onChange` attribute to `{handlePowersChange}`. + +```js +assert.match(code, /onChange\s*=\s*\{\s*handlePowersChange\s*\}/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d0.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d0.md new file mode 100644 index 00000000000..9046e679a8f --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d0.md @@ -0,0 +1,211 @@ +--- +id: 680900675ae3d54ee19590d0 +title: Step 17 +challengeType: 0 +dashedName: step-17 +--- + +# --description-- + +To fix the error, create a `handlePowersChange` arrow function with an `e` parameter. + +Inside the function, destructure `value` and `checked` from `e.target` to get the value of the checkbox and whether it is checked or not. + +# --hints-- + +You should create an `handlePowersChange` function with an `e` parameter. + +```js +assert.match(code, /(const|let)\s+handlePowersChange\s*=\s*(e|\(\s*e\s*\))\s*=>\s*{/) +``` + +You should destructure `value` and `checked` from `e.target`. + +```js +assert.match(code, /(const|let)\s+handlePowersChange\s*=\s*(e|\(\s*e\s*\))\s*=>\s*{\s*(const|let)\s*{\s*(value\s*,\s*checked|checked\s*,\s*value)\s*}\s*=\s*e\s*\.\s*target/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + --fcc-editable-region-- + + --fcc-editable-region-- + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d1.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d1.md new file mode 100644 index 00000000000..3786d631e60 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d1.md @@ -0,0 +1,216 @@ +--- +id: 680900675ae3d54ee19590d1 +title: Step 19 +challengeType: 0 +dashedName: step-19 +--- + +# --description-- + +Next, tell the form how to submit. Add a `method` attribute with a value of `post` and an `action` attribute with a value of `https://superhero-application-form.freecodecamp.org` to the form element. + +Now, submitting form will send it to that URL. You will do that in the next step. + +# --hints-- + +Your `form` element should have a `method` attribute set to `post`. + +```js +const formEl = document?.querySelector("form") +assert.equal(formEl?.getAttribute("method"), "post") +``` + +Your `form` elmement should have an `action` attribute set to `https://superhero-application-form.freecodecamp.org`. + +```js +const formEl = document?.querySelector("form") +assert.equal(formEl?.getAttribute("action"), "https://superhero-application-form.freecodecamp.org") +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + const handlePowersChange = e => { + const { value, checked } = e.target; + setPowers(checked ? [...powers, value] : powers.filter(p => p !== value)); + } + + return ( +
+

Superhero Application Form

+

Please complete all fields

+ --fcc-editable-region-- +
+ --fcc-editable-region-- +
+ + +
+ + +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d2.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d2.md new file mode 100644 index 00000000000..04643ffaa15 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d2.md @@ -0,0 +1,222 @@ +--- +id: 680900675ae3d54ee19590d2 +title: Step 20 +challengeType: 0 +dashedName: step-20 +--- + +# --description-- + +Create a `button` element with the `className` of `submit-btn` and a `type` of `submit`. Give the button the text `Join the League`. + +After you do that, try to submit the form and see what happens. + +# --hints-- + +You should create a `button` element. + +```js +assert.exists(document.querySelector("button")); +``` + +Your button element should have a `className` attribute set to `submit-btn`. + +```js +assert.exists(document.querySelector("button.submit-btn")); +``` + +Your `button` element should have `Join the League` as its text. + +```js +const btnEl = document.querySelector("button") +assert.equal(btnEl.textContent, "Join the League"); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + const handlePowersChange = e => { + const { value, checked } = e.target; + setPowers(checked ? [...powers, value] : powers.filter(p => p !== value)); + } + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + + --fcc-editable-region-- + + --fcc-editable-region-- +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d3.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d3.md new file mode 100644 index 00000000000..61a97665f30 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680900675ae3d54ee19590d3.md @@ -0,0 +1,424 @@ +--- +id: 680900675ae3d54ee19590d3 +title: Step 21 +challengeType: 0 +dashedName: step-21 +--- + +# --description-- + +Did you notice that you can submit the form without filling in the inputs? + +To stop that, add the `disabled` attribute to disable the submit button if `heroName`, `realName`, or `powerSource` are falsy, or if the length of `powers` is `0`. + +Now, the button will be disabled if something isn't filled in. Fill in the form with your superhero information and submit it to join the league. + +With that, you superhero application form is complete. + +# --hints-- + +You should not modify the existing content of the button. + +```js +assert.match(code, /<\s*button\s+className\s*=\s*('|")\s*submit-btn\s*\1\s*type\s*=\s*('|")\s*submit\s*\2/) +``` + +Your `button` element should have a `disabled` property. + +```js +assert.match(code, /<\s*button\s+className\s*=\s*('|")\s*submit-btn\s*\1\s*type\s*=\s*('|")\s*submit\s*\2\s*disabled/) +``` + +You should disable the `button` if any of `heroName`, `realName`, and `powerSource` is false, or if the length of `powers` is `0`. + +```js +assert.match(code, /disabled\s*=\s*\{\s*(?:!heroName\s*\|\|\s*!realName\s*\|\|\s*!powerSource\s*\|\|\s*powers\.length\s*===\s*0|!heroName\s*\|\|\s*!realName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!powerSource|!heroName\s*\|\|\s*!powerSource\s*\|\|\s*!realName\s*\|\|\s*powers\.length\s*===\s*0|!heroName\s*\|\|\s*!powerSource\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!realName|!heroName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!realName\s*\|\|\s*!powerSource|!heroName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!powerSource\s*\|\|\s*!realName|!realName\s*\|\|\s*!heroName\s*\|\|\s*!powerSource\s*\|\|\s*powers\.length\s*===\s*0|!realName\s*\|\|\s*!heroName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!powerSource|!realName\s*\|\|\s*!powerSource\s*\|\|\s*!heroName\s*\|\|\s*powers\.length\s*===\s*0|!realName\s*\|\|\s*!powerSource\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!heroName|!realName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!heroName\s*\|\|\s*!powerSource|!realName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!powerSource\s*\|\|\s*!heroName|!powerSource\s*\|\|\s*!heroName\s*\|\|\s*!realName\s*\|\|\s*powers\.length\s*===\s*0|!powerSource\s*\|\|\s*!heroName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!realName|!powerSource\s*\|\|\s*!realName\s*\|\|\s*!heroName\s*\|\|\s*powers\.length\s*===\s*0|!powerSource\s*\|\|\s*!realName\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!heroName|!powerSource\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!heroName\s*\|\|\s*!realName|!powerSource\s*\|\|\s*powers\.length\s*===\s*0\s*\|\|\s*!realName\s*\|\|\s*!heroName|powers\.length\s*===\s*0\s*\|\|\s*!heroName\s*\|\|\s*!realName\s*\|\|\s*!powerSource|powers\.length\s*===\s*0\s*\|\|\s*!heroName\s*\|\|\s*!powerSource\s*\|\|\s*!realName|powers\.length\s*===\s*0\s*\|\|\s*!realName\s*\|\|\s*!heroName\s*\|\|\s*!powerSource|powers\.length\s*===\s*0\s*\|\|\s*!realName\s*\|\|\s*!powerSource\s*\|\|\s*!heroName|powers\.length\s*===\s*0\s*\|\|\s*!powerSource\s*\|\|\s*!heroName\s*\|\|\s*!realName|powers\.length\s*===\s*0\s*\|\|\s*!powerSource\s*\|\|\s*!realName\s*\|\|\s*!heroName)\s*\}/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + const handlePowersChange = e => { + const { value, checked } = e.target; + setPowers(checked ? [...powers, value] : powers.filter(p => p !== value)); + } + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + +--fcc-editable-region-- + +--fcc-editable-region-- +
+
+ ) +}; +``` + +# --solutions-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + const handlePowersChange = e => { + const { value, checked } = e.target; + setPowers(checked ? [...powers, value] : powers.filter(p => p !== value)); + } + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + + +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680fc849a6f2be0a8597c593.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680fc849a6f2be0a8597c593.md new file mode 100644 index 00000000000..e949838d2ea --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/680fc849a6f2be0a8597c593.md @@ -0,0 +1,198 @@ +--- +id: 680fc849a6f2be0a8597c593 +title: Step 3 +challengeType: 0 +dashedName: step-3 +--- + +# --description-- + +Now, create the state variables and setters for `powerSource` and `powers`. `powerSource` should have an initial value of empty string, and `powers` should have an initial value of an empty array. + +# --hints-- + +You should use array destructuring to set a `powerSource` state variable and a `setPowerSource` setter. + +```js +assert.match(code, /(const|let)\s+\[\s*powerSource\s*,\s*setPowerSource\s*\]/); +``` + +Your `powerSource` and `setPowerSource` should use the `useState` hook. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + assert.isAtLeast(abuseState.calls.length, 3); +} +``` + +Your `useState` hook for `powerSource` should have an initial value of empty string. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + assert.equal(abuseState.calls[2]?.[0], ""); +} +``` + +You should use array destructuring to set a `powers` state variable and a `setPowers` setter. + +```js +assert.match(code, /(const|let)\s+\[\s*powers\s*,\s*setPowers\s*\]/); +``` + +Your `powers` and `setPowers` should use the `useState` hook. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + assert.isAtLeast(abuseState.calls.length, 4); +} +``` + +Your `useState` hook for `powers` should have an initial value of empty array. + +```js +async () => { + const abuseState = __helpers.spyOn(React, "useState"); + const script = [...document.querySelectorAll("script")].find((s) => s.dataset.src === "index.jsx").innerText; + const exports = {}; + const _a = eval(script); + const _b = await __helpers.prepTestComponent(exports.SuperheroForm); + + console.log("State calls:", abuseState.calls) + + assert.deepEqual(abuseState.calls[3]?.[0], []); +} +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + + --fcc-editable-region-- + + --fcc-editable-region-- + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68148d280ee30e5a567a0e2d.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68148d280ee30e5a567a0e2d.md new file mode 100644 index 00000000000..7836830908d --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68148d280ee30e5a567a0e2d.md @@ -0,0 +1,208 @@ +--- +id: 68148d280ee30e5a567a0e2d +title: Step 15 +challengeType: 0 +dashedName: step-15 +--- + +# --description-- + +Remove the `Hello` text inside the `label`, then create an `input` of type `checkbox` and a `value` of `power`. + +Finally, display the values from the array next to each checkbox by creating a `span` element just before the closing `label` with a text content of `{power}`. + +# --hints-- + +You should remove the `Hello` text from the `label` element. + +```js +assert.notMatch(code, /hello/i) +``` + +You should create an `input` with its `type` set to `checkbox` and a `value` set to `power` as the first child of the label. + +```js +assert.match(code, /<\s*label\s+key\s*=\s*{\s*power\s*}\s*>\s*<\s*input\s+type\s*=\s*("|')checkbox\1\s*value\s*=\s*\{\s*power\s*\}\s*\/>[\s\S]*<\/\s*label\s*>/) +``` + +You should create a `span` element with `{power}` for its text content as the last child of the label. + +```js +assert.match(code, /<\s*label\s+key\s*=\s*{\s*power\s*}\s*>[\s\S]*<\s*span\s*>\s*{\s*power\s*}\s*<\/\s*span\s*>\s*<\/\s*label\s*>/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + +
+
+ ) +}; +``` diff --git a/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68149b101d905a6fc2fcd6d8.md b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68149b101d905a6fc2fcd6d8.md new file mode 100644 index 00000000000..112de36ef36 --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/workshop-superhero-application-form/68149b101d905a6fc2fcd6d8.md @@ -0,0 +1,208 @@ +--- +id: 68149b101d905a6fc2fcd6d8 +title: Step 18 +challengeType: 0 +dashedName: step-18 +--- + +# --description-- + +Below the destructured `value` and `checked`, call the `setPowers` function to update the list of checked powers. + +The function needs an array argument. In the function parameter, use a ternary operator to check if `checked` is true. If it is, spread in the existing `powers` array into a new array and add the `value` to it. If it is not true, filter out the `value` from `powers` with `powers.filter(p => p !== value)`. + +# --hints-- + +You should use a ternary operator to check if `checked` is true. If it is, spread in the existing `powers` and `value` into an array. If it is not, filter out the `value` from `powers`. + +```js +assert.match(code, /(const|let)\s*{\s*(value\s*,\s*checked|checked\s*,\s*value)\s*}\s*=\s*e\s*\.\s*target\s*;?\s*setPowers\s*\(\s*checked\s*\?\s*\[\s*\.\.\.powers\s*,\s*value\s*\]\s*:\s*powers\s*\.\s*filter\s*\(\s*(p|\(\s*p\s*\))\s*=>\s*p\s*!==?\s*value\s*\)\s*\)/) +``` + +# --seed-- + +## --seed-contents-- + +```html + + + + + Superhero Application Form + + + + + + + + +
+ + + +``` + +```css +body { + margin: 0; + padding: 0; + min-height: 100vh; + font-family: Arial, sans-serif; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(30deg, #ff9999 50%, #6699ff 50%) +} + +.form-wrap { + background-color: white; + width: 400px; + padding: 20px; + border: 1px solid black; + box-shadow: 5px 5px 10px black; +} + +.form-wrap h2, +.form-wrap p { + text-align: center; +} + +.form-wrap p { + position: relative; + top: -18px; +} + +.section { + display: flex; + margin-bottom: 30px; +} + +.column { + flex-direction: column; +} + +.submit-wrap { + text-align: center; +} + +.submit-btn { + display: block; + margin: 0 auto; + padding: 0.4rem 0.5rem; + border: 1px solid black +} + +.submit-btn:hover { + cursor: pointer; + background-color: #f3f3f3; +} + +.submit-btn:disabled { + cursor: not-allowed; +} +``` + +```jsx +const { useState } = React; + +export const SuperheroForm = () => { + + const powerSourceOptions = [ + 'Bitten by a strange creature', + 'Radioactive exposure', + 'Science experiment', + 'Alien heritage', + 'Ancient artifact discovery', + 'Other' + ]; + + const powersOptions = [ + 'Super Strength', + 'Super Speed', + 'Flight', + 'Invisibility', + 'Telekinesis', + 'Other' + ]; + + const [heroName, setHeroName] = useState(''); + const [realName, setRealName] = useState(''); + const [powerSource, setPowerSource] = useState(''); + const [powers, setPowers] = useState([]); + +--fcc-editable-region-- + const handlePowersChange = e => { + const { value, checked } = e.target; + + } +--fcc-editable-region-- + + return ( +
+

Superhero Application Form

+

Please complete all fields

+
+
+ + +
+ + +
+
+ ) +}; +``` diff --git a/curriculum/superblock-structure/full-stack.json b/curriculum/superblock-structure/full-stack.json index 1ed25febdbc..eb2c40d7b03 100644 --- a/curriculum/superblock-structure/full-stack.json +++ b/curriculum/superblock-structure/full-stack.json @@ -1078,6 +1078,9 @@ { "dashedName": "quiz-react-state-and-hooks" }, + { + "dashedName": "workshop-superhero-application-form" + }, { "dashedName": "lecture-working-with-forms-in-react" },