Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create form validation lab #627

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions frontend-cert/js-projects/form-validation-lab/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>Customer Complaint Form</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
</head>

<body>
<h1>Complaint Form</h1>
<form id="form">
<fieldset id="personal-info">
<div>
<label for="full-name">Full Name:</label>
<input type="text" id="full-name" name="full-name" placeholder="John Doe">
</div>

<div>
<label for="email">Email Address:</label>
<input type="email" id="email" name="email" placeholder="[email protected]">
</div>
</fieldset>
<hr>
<fieldset id="product-info">
<div>
<label for="order-no">Order No:</label>
<input type="text" id="order-no" name="order-no" placeholder="2024######">
</div>
<div>
<label for="product-code">Product Code:</label>
<input type="text" id="product-code" name="product-code" placeholder="XX##-X###-XX#">
</div>
<div>
<label for="quantity">Quantity:</label>
<input type="number" id="quantity" name="quantity" min="1">
</div>
</fieldset>

<fieldset id="complaints-group">
<legend>Complaint Reason:</legend>
<div>
<input type="checkbox" id="damaged-product" name="complaint" value="damaged-product">
<label for="damaged-product">Damaged Product</label>
</div>

<div>
<input type="checkbox" id="nonconforming-product" name="complaint" value="nonconforming-product">
<label for="nonconforming-product">Nonconforming Product</label>
</div>

<div>
<input type="checkbox" id="delayed-dispatch" name="complaint" value="delayed-dispatch">
<label for="delayed-dispatch">Delayed Dispatch</label>
</div>

<div>
<input type="checkbox" id="other-complaint" name="complaint" value="other">
<label for="other-complaint">Other</label>
</div>
</fieldset>

<div id="complaint-description-container">
<legend>Description of Complaint Reason</legend>
<textarea placeholder="Describe the reason of your complaint in at least 20 characters"
name="complaint-textarea" id="complaint-description"></textarea>
</div>

<fieldset id="solutions-group">
<legend>Desired Solution</legend>
<input type="radio" name="solutions" id="refund" value="refund">
<label for="refund">Refund</label>

<input type="radio" name="solutions" id="exchange" value="exchange">
<label for="exchange">Exchange</label>

<input type="radio" name="solutions" id="other-solution" value="other">
<label for="other-solution">Other</label>
</fieldset>

<div id="solution-description-container">
<legend>Description of Desired Solution</legend>
<textarea placeholder="Describe the desired solution to your issue in at least 20 characters"
name="solution-textarea" id="solution-description"></textarea>
</div>
<div id="btn-container">
<button type="submit" id="submit-btn">Submit</button>
<span id="message-box"></span>
<button type="button" id="clear-btn">Clear</button>
</div>

</form>

<script src="script.js"></script>
</body>

</html>
125 changes: 125 additions & 0 deletions frontend-cert/js-projects/form-validation-lab/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
const form = document.getElementById("form");
const fullName = document.getElementById("full-name");
const emailAddress = document.getElementById("email");
const orderNo = document.getElementById("order-no");
const productCode = document.getElementById("product-code");
const quantity = document.getElementById("quantity");
const complaints = document.querySelectorAll('input[name="complaint"]');
const complaintDescription = document.getElementById("complaint-description");
const complaintTextAreaDiv = document.getElementById("complaint-description-container");
const solutions = document.querySelectorAll('input[name="solutions"]');
const solutionDescription = document.getElementById("solution-description");
const solutionTextAreaDiv = document.getElementById("solution-description-container");
const submitBtn = document.getElementById("submit-btn");
const messageBox = document.getElementById("message-box");
const clearBtn = document.getElementById("clear-btn");

const hideTextareas = () => {
complaintTextAreaDiv.style.display = "none";
solutionTextAreaDiv.style.display = "none";
}

hideTextareas();

const formFields = {
"full-name": fullName,
"email": emailAddress,
"order-no": orderNo,
"product-code": productCode,
"quantity": quantity,
"complaints-group": Array.from(complaints),
"complaint-description": complaintDescription,
"solutions-group": Array.from(solutions),
"solution-description": solutionDescription
}

const clearForm = () => {
Object.entries(formFields).forEach(entry => {
const [key, val] = entry;
if (Array.isArray(val)) {
val.forEach(i => i.checked = false);
} else {
val.value = "";
}
hideTextareas();
messageBox.innerText = "";
document.getElementById(key).style.borderColor = "rgb(118, 118, 118)";
})
}

const validateForm = () => {
const complaintsArr = Array.from(complaints).map(i => i.checked);
const solutionsArr = Array.from(solutions).map(i => i.checked);
const validationObject = {
"full-name": Boolean(fullName.value.trim()),
"email": /^\S+@\S+\.\S+$/.test(emailAddress.value.trim()),
"order-no": /^2024\d{6}$/.test(orderNo.value.trim()),
"product-code": /[A-Z]{2}\d{2}-[A-Z]\d{3}-[A-Z]{2}\d/i.test(productCode.value.trim()),
"quantity": Number(quantity.value.trim()) > 0,
"complaints-group": complaintsArr.some(i => i),
"complaint-description": null,
"solutions-group": solutionsArr.some(i => i),
"solution-description": null
}

if (complaintsArr[3]) {
complaintTextAreaDiv.style.display = "block";
const complaintsDescriptionVal = complaintDescription.value.trim();
if (complaintsDescriptionVal.length < 20) {
validationObject["complaint-description"] = false;
} else {
validationObject["complaint-description"] = true;
}
} else {
complaintTextAreaDiv.style.display = "none";
}
if (solutionsArr[2]) {
solutionTextAreaDiv.style.display = "block";
const solutionDescriptionVal = solutionDescription.value.trim();
if (solutionDescriptionVal.length < 20) {
validationObject["solution-description"] = false;
} else {
validationObject["solution-description"] = true;
}
} else {
solutionTextAreaDiv.style.display = "none";
}
if (validationObject["complaint-description"] === null) delete validationObject["complaint-description"];
if (validationObject["solution-description"] === null) delete validationObject["solution-description"];

return validationObject;
}

clearBtn.addEventListener("click", clearForm);

Object.keys(formFields).forEach(key => {
document.getElementById(key).addEventListener("change", (e) => {
const validationObject = validateForm();
if (Object.values(validationObject).every(val => val)) messageBox.innerText = "";
if (!validationObject[key]) {
document.getElementById(key).style.borderColor = "red";
} else {
document.getElementById(key).style.borderColor = "green";
}
});
});

form.addEventListener("submit", (e) => {
e.preventDefault();
const validationObject = validateForm();
const isValid = Object.values(validationObject).every(i => i);
if (!isValid) {
messageBox.innerText = "Please, fill out the required fields correctly before submitting.";
Object.keys(validationObject).forEach(key => {
if (!validationObject[key]) {
document.getElementById(key).style.borderColor = "red";
} else {
document.getElementById(key).style.borderColor = "green";
}
});
} else {
messageBox.innerText = "";
alert("Form successfully submitted.");
location.reload()
}
});
46 changes: 46 additions & 0 deletions frontend-cert/js-projects/form-validation-lab/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
* {
box-sizing: border-box;
}

h1 {
text-align: center;
}

#form {
max-width: 70%;
margin: auto;
border-radius: 10px;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
padding: 10px;
}

input {
border-color: rgb(118, 118, 118);
}

#personal-info input, #product-info input {
width: 100%;
margin-bottom: 10px;
}


fieldset {
margin-bottom: 10px;
border-radius: 5px;
border-color: rgb(118, 118, 118);
}

textarea {
width: 100%;
border-color: rgb(118, 118, 118);
}

#btn-container {
display: flex;
justify-content: space-between;
align-items: center;
}

#submit-btn, #clear-btn {
margin: 10px 15px 0;
}
17 changes: 17 additions & 0 deletions frontend-cert/js-projects/form-validation-lab/user-stories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
For this lab, you have been provided with all the HTML and CSS. You will use JavaScript to validate the complaint form.

1. When the form is submitted, you should ensure that `#full-name` is not empty.
1. When the form is submitted, you should ensure that `#email` is a valid email address format.
1. When the form is submitted, you should ensure that `#order-no` is a sequence of ten numbers starting with `2024`.
1. When the form is submitted, you should ensure that `#product-code` follows the pattern `XX##-X###-XX#`, where `X` represents either a lowercase letter or an uppercase letter and `#` represents a number.
1. When the form is submitted, you should ensure that `#quantity` is a positive integer.
1. When the form is submitted, you should ensure that at least one checkbox from `#complaints-group` is checked.
1. When the form is submitted, you should ensure that `#complaint-description` contains at least twenty characters if the `Other` checkbox is checked.
1. When the form is submitted, you should ensure that a radio button from `#solutions-group` is selected.
1. When the form is submitted, you should ensure that `#solution-description` contains at least twenty characters if the `Other` radio button is selected.
1. Once a form field is filled with a valid value, you should set its border color to `green`. In case of checkbox and radio button groups, you should set the border color of the parent `fieldset`.
1. Once a form field is filled with an invalid value, you should set its border color to `red`. In case of checkbox and radio button groups, you should set the border color of the parent `fieldset`.
1. When you click the submit button, if the form has any invalid field, you should set the inner text of `#message-box` to `Please, fill out the required fields correctly before submitting.`
1. When you click the submit button, if the form has any invalid field, each invalid field should be highlighted by setting the border color of each invalid input, textarea or fieldset (in case of checkbox and radio button groups) to `red`.
1. When each form field is valid, you should reset the inner text of `#message-box` to an empty string.
1. When you click the submit button, if the form is filled correctly, you should display an alert saying `Form successfully submitted.`