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
+
+
+ )
+};
+```
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
+
+
+ )
+};
+```
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
+
+
+ )
+};
+```
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
+
+
+ )
+};
+```
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 (
+
+ {fruits.map((fruit, index) => (
+ - {fruit}
+ ))}
+
+ );
+}
+```
+
+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
+
+
+ )
+};
+```
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--
+
+
+ )
+};
+```
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
+
+
+ )
+};
+```
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
+
+
+ )
+};
+```
+
+# --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"
},