From 3d9ffa5cff9510d81f20f58d6afd21934a33bb08 Mon Sep 17 00:00:00 2001 From: Zaira <33151350+zairahira@users.noreply.github.com> Date: Wed, 2 Oct 2024 20:10:31 +0500 Subject: [PATCH] feat(curriculum): add contact form lab (#56270) Co-authored-by: Tom <20648924+moT01@users.noreply.github.com> Co-authored-by: Ilenia <26656284+ilenia-magoni@users.noreply.github.com> --- client/i18n/locales/english/intro.json | 7 +- .../lab-contact-form/index.md | 9 + .../_meta/lab-contact-form/meta.json | 11 + .../66f26c32ec6f90df01a44f60.md | 455 ++++++++++++++++++ 4 files changed, 481 insertions(+), 1 deletion(-) create mode 100644 client/src/pages/learn/front-end-development/lab-contact-form/index.md create mode 100644 curriculum/challenges/_meta/lab-contact-form/meta.json create mode 100644 curriculum/challenges/english/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index fc932dd5e0e..65a1bb7ff06 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -1893,7 +1893,12 @@ }, "jnqt": { "title": "68", "intro": [] }, "vkei": { "title": "69", "intro": [] }, - "jows": { "title": "70", "intro": [] }, + "lab-contact-form": { + "title": "Design a Contact Form", + "intro": [ + "In this lab, you will design a contact form in HTML and style it using CSS." + ] + }, "ipmw": { "title": "71", "intro": [] }, "quiz-styling-forms": { "title": "Styling Forms Quiz", diff --git a/client/src/pages/learn/front-end-development/lab-contact-form/index.md b/client/src/pages/learn/front-end-development/lab-contact-form/index.md new file mode 100644 index 00000000000..c07b3ff8143 --- /dev/null +++ b/client/src/pages/learn/front-end-development/lab-contact-form/index.md @@ -0,0 +1,9 @@ +--- +title: Introduction to the Design a Contact Form +block: lab-contact-form +superBlock: front-end-development +--- + +## Introduction to the Design a Contact Form + +In this lab, you will design a contact form in HTML and style it using CSS. diff --git a/curriculum/challenges/_meta/lab-contact-form/meta.json b/curriculum/challenges/_meta/lab-contact-form/meta.json new file mode 100644 index 00000000000..283e4f784fb --- /dev/null +++ b/curriculum/challenges/_meta/lab-contact-form/meta.json @@ -0,0 +1,11 @@ +{ + "name": "Design a Contact Form", + "isUpcomingChange": true, + "usesMultifileEditor": true, + "dashedName": "lab-contact-form", + "order": 70, + "superBlock": "front-end-development", + "challengeOrder": [{ "id": "66f26c32ec6f90df01a44f60", "title": "Design a Contact Form" }], + "helpCategory": "HTML-CSS", + "blockType": "lab" +} diff --git a/curriculum/challenges/english/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md b/curriculum/challenges/english/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md new file mode 100644 index 00000000000..ea69c75648b --- /dev/null +++ b/curriculum/challenges/english/25-front-end-development/lab-contact-form/66f26c32ec6f90df01a44f60.md @@ -0,0 +1,455 @@ +--- +id: 66f26c32ec6f90df01a44f60 +title: Design a Contact Form +challengeType: 14 +dashedName: design-a-contact-form +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 a `div` with a class of `form-container` to hold your form. + +2. You should have a `form` element within the `.form-container` `div`. + +3. Within the `form` element, you should have the following elements and input fields: + + - A `h2` element with some text. + - A text input field for the name with the `type` set to `text` and `id`, `name`, `required` attributes. + - An email input field with the `type` set to `email` and `id`, `name`, `required` attributes. + - A textarea for the message with `id`, `name`, and the `required` attribute. + - A `button` element with the text `"Submit"` and a `type` attribute of `submit`. + +4. Each `input` and `textarea` elements should have their corresponding `label` element with a `for` attribute set to the element's `id`. + +5. The `.form-container` `div` should have a background color, and have values for `border-radius`, `padding`, and `width`. + +6. The `label` elements should have a margin and a font color. + +7. The `input` and `textarea` elements should have values for: + + - `width`. + - `padding`. + - Margin on the bottom. + +8. The `button` element should have a: + + - Background color + - Font size apart from the default. + +9. The button should have a hover effect that changes the background color. + +**Note:** Be sure to link your stylesheet in your HTML and apply your CSS. + +# --hints-- + +You should have a `div` with a class of `form-container`. + +```js +const el = document.querySelector('div.form-container'); +assert.isNotNull(el); +``` + +You should have a `form` element within the `.form-container` `div`. + +```js +const el = document.querySelector('.form-container form'); +assert.isNotNull(el); +``` + +Within the `form`, you should have an `h2` element with some text. + +```js +const el = document.querySelector('.form-container form h2'); +assert.isNotEmpty(el.innerText); +// assert.isAtLeast(document.querySelector('h1').innerText.length, 1); + +``` + +Within the `form`, you should have a text input field with the type set to `text`. + +```js +const el = document.querySelector('.form-container form input[type="text"]'); +assert.isNotNull(el); +``` + +Your `type=text` input field should have an `id`, a `name`, and a `required` attribute. + +```js +const el = document.querySelector('.form-container form input[type="text"]'); + +assert(!!el && el.required); +assert.isNotEmpty(el?.getAttribute('id')); +assert.isNotEmpty(el?.getAttribute('name')); +``` + +Within the `form`, you should have an email input field with the `type` set to `email`. + +```js +const el = document.querySelector('.form-container form input[type="email"]'); +assert.isNotNull(el); +``` + +Your `type=email` input field should have an `id`, a `name`, and a `required` attribute. + +```js +const el = document.querySelector('.form-container form input[type="email"]'); +assert.isTrue(el?.required); +assert.isNotEmpty(el?.getAttribute('id')); +assert.isNotEmpty(el?.getAttribute('name')); +``` + +Within the `form`, you should have a `textarea` with an `id`, `name`, and a `required` attribute. + +```js +const el = document.querySelector('.form-container form textarea'); +assert.isNotNull(el); +assert.isNotNull(document.querySelector('.form-container form textarea[required]')); +assert.isNotEmpty(el?.getAttribute('id')); +assert.isNotEmpty(el?.getAttribute('name')); +``` + +Within the `form`, you should have a `button` element with a `type` attribute of `submit`. + +```js +const el = document.querySelector('.form-container form button'); +assert.strictEqual(el?.getAttribute('type'), 'submit'); +``` + +Your button should have a text of `"Submit"`. + +```js +const el = document.querySelector('.form-container form button'); +assert.strictEqual(document.querySelector('.form-container form button').textContent, 'Submit'); +``` + +You should have a `label` element for the `#name` `input` with a `for` attribute matching the `id` value on the corresponding `input`. + +```js +const nameInput = document.querySelector('.form-container form input[type="text"]')?.getAttribute('id'); + +const labels = document.querySelectorAll('.form-container form label'); + +assert.isAbove(labels.length, 0); + +// check if id has a value +assert.isNotEmpty(nameInput); +let found = false; + +for (let label of labels) { + if (label.getAttribute('for') === nameInput) { + found = true; + break; + } +} + +assert.isTrue(found); +``` + +You should have a `label` element for the `#email` `input` with a `for` attribute matching the `id` value on the corresponding `input`. + +```js +const emailInput = document.querySelector('.form-container form input[type="email"]')?.getAttribute('id'); +const labels = document.querySelectorAll('.form-container form label'); + +assert.isAbove(labels.length, 0); +// check if id has a value +assert.isNotEmpty(emailInput); +let found = false; + +for (let label of labels) { + if (label.getAttribute('for') === emailInput) { + found = true; + break; + } +} + +assert.isTrue(found); +``` + +You should have a `label` element for the `#message` `textarea` with a `for` attribute matching the `id` value on the `textarea`. + +```js +const messageInput = document.querySelector('.form-container form textarea')?.getAttribute('id'); +const labels = document.querySelectorAll('.form-container form label'); + +assert.isAbove(labels.length, 0); + +// check if id has a value + +assert.isNotEmpty(messageInput); + +assert.exists(document.querySelector(`label[for="${messageInput}"]`)); +``` + +The labels shouldn't be empty. + +```js +const labels = document.querySelectorAll('.form-container form label'); + +assert.isAbove(labels.length, 0); + +for (let label of labels) { + const labelText = label.textContent.trim(); + assert.isNotEmpty(labelText); +} + +``` + +The `form-container` `div` should have a background color. + +```js +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('.form-container')?.backgroundColor); +``` + +The `form-container` `div` should have a `border-radius`. + +```js +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('.form-container')?.borderRadius); +``` + +The `form-container` `div` should have padding. + +```js +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('.form-container')?.padding); +``` + +The `form-container` `div` should have a width. + +```js +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('.form-container')?.width); +``` + +Your labels should have a margin and font color. + +```js +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('label')?.margin); +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('label')?.color); +``` + +Your `input` elements should have a width, padding, and a margin on the bottom. + +```js +// Helper function to extract properties from multiple selectors +function getStyleProperties(selectors, properties) { + const result = {}; + properties.forEach((property) => { + result[property] = selectors.map((selector) => selector?.[property]).find(Boolean); + }); + return result; +} + +// Initializing selectors +const selectors = [ + new __helpers.CSSHelp(document).getStyle('input'), + new __helpers.CSSHelp(document).getStyle('input, textarea'), + new __helpers.CSSHelp(document).getStyle('textarea, input') +]; + +// Extract width, padding, and margin properties +const { width } = getStyleProperties(selectors, ['width']); +assert.isNotEmpty(width); + +const { + padding, + paddingTop, + paddingBottom, + paddingLeft, + paddingRight +} = getStyleProperties(selectors, ['padding', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight']); + +// Assert padding properties +assert.isOk( + padding || + (paddingTop && paddingBottom && paddingLeft && paddingRight) +); + +const { marginBottom } = getStyleProperties(selectors, ['marginBottom']); +assert.isNotEmpty(marginBottom); + +``` + +Your `textarea` element should have a width, padding, margin on the bottom. + +```js +// Helper function to extract properties from multiple selectors +function getStyleProperties(selectors, properties) { + const result = {}; + properties.forEach((property) => { + result[property] = selectors.map((selector) => selector?.[property]).find(Boolean); + }); + return result; +} + +// Initializing selectors +const selectors = [ + new __helpers.CSSHelp(document).getStyle('textarea'), + new __helpers.CSSHelp(document).getStyle('input, textarea'), + new __helpers.CSSHelp(document).getStyle('textarea, input') +]; + +// Extract width, padding, and margin properties +const { width } = getStyleProperties(selectors, ['width']); +assert.isNotEmpty(width); + +const { + padding, + paddingTop, + paddingBottom, + paddingLeft, + paddingRight +} = getStyleProperties(selectors, ['padding', 'paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight']); + +// Assert padding properties +assert.isOk( + padding || + (paddingTop && paddingBottom && paddingLeft && paddingRight) +); + +const { marginBottom } = getStyleProperties(selectors, ['marginBottom']); +assert.isNotEmpty(marginBottom); +``` + +Your `button` element should have a background color. + +```js +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('button')?.backgroundColor); +``` + +Your `button` element should have a font size. + +```js +assert.isNotEmpty(new __helpers.CSSHelp(document).getStyle('button')?.fontSize); +``` + +Your `button` element should have a hover effect that changes the background color. + +```js +const gs = (s) => new __helpers.CSSHelp(document).getStyle(s); +const btn_hover = gs('button:hover')?.backgroundColor; +assert.isNotEmpty(btn_hover); +``` + +# --seed-- + +## --seed-contents-- + +```html + + + +
+ +