mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(curriculum): add checkout page lab (#56094)
Co-authored-by: Ilenia <26656284+ilenia-magoni@users.noreply.github.com> Co-authored-by: Dario-DC <105294544+Dario-DC@users.noreply.github.com>
This commit is contained in:
@@ -1760,7 +1760,10 @@
|
||||
"xzam": { "title": "23", "intro": [] },
|
||||
"isho": { "title": "24", "intro": [] },
|
||||
"ghoc": { "title": "25", "intro": [] },
|
||||
"cikh": { "title": "26", "intro": [] },
|
||||
"lab-checkout-page": {
|
||||
"title": "Build a Checkout Page",
|
||||
"intro": ["In this lab, you will create an accessible checkout page."]
|
||||
},
|
||||
"fqai": { "title": "27", "intro": [] },
|
||||
"cayd": { "title": "28", "intro": [] },
|
||||
"pspj": { "title": "29", "intro": [] },
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Introduction to the Build a Checkout Page
|
||||
block: lab-checkout-page
|
||||
superBlock: front-end-development
|
||||
---
|
||||
|
||||
## Introduction to the Build a Checkout Page
|
||||
|
||||
For this lab, you will build a checkout page.
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "Build a Checkout Page",
|
||||
"blockType": "lab",
|
||||
"isUpcomingChange": true,
|
||||
"usesMultifileEditor": true,
|
||||
"dashedName": "lab-checkout-page",
|
||||
"order": 26,
|
||||
"superBlock": "front-end-development",
|
||||
"challengeOrder": [{ "id": "66da326c02141df538f29ba5", "title": "Build a Checkout Page" }],
|
||||
"helpCategory": "HTML-CSS"
|
||||
}
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
---
|
||||
id: 66da326c02141df538f29ba5
|
||||
title: Build a Checkout Page
|
||||
challengeType: 14
|
||||
dashedName: build-a-checkout-page
|
||||
demoType: onClick
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
**Objective:** Fulfill the user stories below and get all the tests to pass to complete the lab.
|
||||
|
||||
**User Stories:**
|
||||
|
||||
1. You should have an `h1` element with the text `Checkout`.
|
||||
1. You should have two `section` elements immediately after the `h1` element.
|
||||
1. You should have an `h2` element with the text `Your Cart` within the first section.
|
||||
1. You should have an image of an item in the first section with appropriate alternate text. You can use this image if you would like: `https://cdn.freecodecamp.org/curriculum/labs/cube.jpg`
|
||||
1. You should have an `h2` element with the text `Payment Information` within the second section.
|
||||
1. You should have a `form` element within the second section.
|
||||
1. You should have an input with an `id` and `name` of `card-name` within your form and a `label` associated with it.
|
||||
1. You should have an input with an `id` and `name` of `card-number` within your form and a `label` associated with it.
|
||||
1. At least two of your input elements should be required and have an `aria-required` attribute set to `true`.
|
||||
1. You should use `tab-index` at least once.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `h1` element with the text `Checkout`.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('h1')?.innerText, 'Checkout');
|
||||
```
|
||||
|
||||
You should only have one `h1` element on your page.
|
||||
|
||||
```js
|
||||
assert.lengthOf(document.querySelectorAll('h1'), 1);
|
||||
```
|
||||
|
||||
You should have at least two `section` elements after the `h1` element.
|
||||
|
||||
```js
|
||||
const h1 = document.querySelector('h1');
|
||||
const firstSibling = h1?.nextElementSibling;
|
||||
const secondSibling = firstSibling?.nextElementSibling;
|
||||
assert.equal(firstSibling?.tagName, 'SECTION');
|
||||
assert.equal(secondSibling?.tagName, 'SECTION');
|
||||
```
|
||||
|
||||
You should have an `h2` element with the text `Your Cart` within the first section.
|
||||
|
||||
```js
|
||||
const firstSection = document.querySelectorAll('section')?.[0];
|
||||
assert.equal(firstSection?.querySelector('h2')?.innerText, 'Your Cart');
|
||||
```
|
||||
|
||||
You should have at least one image with alternate text in your first section.
|
||||
|
||||
```js
|
||||
const firstSection = document.querySelectorAll('section')?.[0];
|
||||
assert.isAtLeast(firstSection?.querySelector('img')?.alt?.length, 1);
|
||||
```
|
||||
|
||||
You should have an `h2` element with the text `Payment Information` within the second section.
|
||||
|
||||
```js
|
||||
const secondSection = document.querySelectorAll('section')?.[1];
|
||||
assert.equal(secondSection?.querySelector('h2')?.innerText, 'Payment Information');
|
||||
```
|
||||
|
||||
You should have a `form` element within the second `section` element.
|
||||
|
||||
```js
|
||||
const secondSection = document.querySelectorAll('section')?.[1];
|
||||
assert.exists(secondSection?.querySelector('form'));
|
||||
```
|
||||
|
||||
You should have an `input` element with an `id` and `name` of `card-name` within your form.
|
||||
|
||||
```js
|
||||
const secondSection = document.querySelectorAll('section')?.[1];
|
||||
assert.exists(secondSection?.querySelector('form input#card-name'));
|
||||
assert.exists(secondSection?.querySelector('form input[name="card-name"]'));
|
||||
```
|
||||
|
||||
You should have an `input` element with an `id` and `name` of `card-number` within your form.
|
||||
|
||||
```js
|
||||
const secondSection = document.querySelectorAll('section')?.[1];
|
||||
assert.exists(secondSection?.querySelector('form input#card-number'));
|
||||
assert.exists(secondSection?.querySelector('form input[name="card-number"]'));
|
||||
```
|
||||
|
||||
All of your `input` elements that aren't a `type` of `submit` should have a `label` element associated with them.
|
||||
|
||||
```js
|
||||
const inputs = document.querySelectorAll('input:not([type="submit"])');
|
||||
assert.isAtLeast(inputs.length, 1);
|
||||
inputs.forEach(input => assert.exists(document.querySelector(`label[for="${input.id}"]`)));
|
||||
```
|
||||
|
||||
At least two of your `input` elements should be required and have an `aria-required` attribute set to `true`.
|
||||
|
||||
```js
|
||||
const inputs = document.querySelectorAll('input');
|
||||
const requiredInputs = Array.from(inputs).filter(input => input.required && input.getAttribute('aria-required') === 'true');
|
||||
assert.isAtLeast(requiredInputs?.length, 2)
|
||||
```
|
||||
|
||||
You should use `tabindex` at least once.
|
||||
|
||||
```js
|
||||
const els = document.querySelectorAll('[tabindex]');
|
||||
assert.isAtLeast(els.length, 1);
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Checkout Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Checkout Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Checkout</h1>
|
||||
|
||||
<section>
|
||||
<h2>Your Cart</h2>
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/labs/spoon.jpg" alt="Left-handed spoon">
|
||||
<p>Left-handed spoon</p>
|
||||
<p>$29.99</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Payment Information</h2>
|
||||
<form action="/submit-payment" method="POST">
|
||||
<div>
|
||||
<label for="card-name">Cardholder Name</label>
|
||||
<input type="text" id="card-name" name="card-name" required aria-required="true" tabindex="0">
|
||||
</div>
|
||||
<div>
|
||||
<label for="card-number">Card Number</label>
|
||||
<input type="number" id="card-number" name="card-number" required aria-required="true">
|
||||
</div>
|
||||
<div>
|
||||
<label for="expiry-date">Expiry Date</label>
|
||||
<input type="text" id="expiry-date" name="expiry-date" placeholder="MM/YY" required aria-required="true">
|
||||
</div>
|
||||
<div>
|
||||
<label for="cvv">CVV</label>
|
||||
<input type="number" id="cvv" name="cvv" required aria-required="true" aria-label="Card Verification Value">
|
||||
</div>
|
||||
<input type="submit" value="Place Order">
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
Reference in New Issue
Block a user