From b5841e364073f8fbf1dade5606313852fc54586d Mon Sep 17 00:00:00 2001 From: Deepak Pundir Date: Tue, 10 May 2022 20:43:23 +0530 Subject: [PATCH 1/7] A Registration form with validation --- src/meta/play-meta.js | 224 +++++++++------ src/plays/index.js | 1 + src/plays/registration-form/Readme.md | 13 + .../registration-form/Registration-form.css | 46 +++ .../registration-form/RegistrationForm.jsx | 263 ++++++++++++++++++ src/plays/registration-form/cover.png | Bin 0 -> 42113 bytes 6 files changed, 460 insertions(+), 87 deletions(-) create mode 100644 src/plays/registration-form/Readme.md create mode 100644 src/plays/registration-form/Registration-form.css create mode 100644 src/plays/registration-form/RegistrationForm.jsx create mode 100644 src/plays/registration-form/cover.png diff --git a/src/meta/play-meta.js b/src/meta/play-meta.js index 94370b664d..5c7c187a1a 100644 --- a/src/meta/play-meta.js +++ b/src/meta/play-meta.js @@ -13,8 +13,9 @@ import { ExpandingCards, AnalogClock, PasswordGenerator, -WhyTypescript, -//import play here + WhyTypescript, + RegistrationForm, + //import play here } from "plays"; export const plays = [ @@ -84,64 +85,85 @@ export const plays = [ tags: "Recursion, Tree", github: "green-roots", featured: true, - }, { - id: 'pl-counter', - name: 'Counter', - description: 'A simple counter which increments the value upto a certain limit!', - component: () => {return }, - path: '/plays/counter', - level: 'Beginner', - tags: 'JSX, State, Props', - github: 'murtuzaalisurti', - featured: true - }, { - id: 'pl-states', - name: 'States', - description: 'States in Functional Components', - component: () => {return }, - path: '/plays/states', - level: 'Beginner', - tags: 'Hooks,State,JSX', - github: 'Abhishek-90', - cover: '', - blog: 'https://abhishek-90.github.io/My-Portfolio/' - }, { - id: 'pl-social-card', - name: 'Social Card', - description: 'The Social Card helps you telling who you are using photo, name, and other social footprints.', - component: () => {return }, - path: '/plays/social-card', - level: 'Intermediate', - tags: 'Form,Events,Complex State', - github: 'atapas', - cover: '', - blog: 'https://blog.greenroots.info/how-to-create-react-form-with-a-single-change-event-handler', - video: '' - }, { - id: 'pl-random-meme-generator', - name: 'Random Meme Generator', - description: 'A project to demonstrate the use of API to fetch random memes! It also demonstrates how you can do event handling!', - component: () => {return }, - path: '/plays/random-meme-generator', - level: 'Beginner', - tags: 'JSX,Hooks,API,EventHandling', - github: 'murtuzaalisurti', - cover: '', - blog: '', - video: '' - }, { - id: 'pl-keeper', - name: 'Keeper', - description: 'Keeper is the clone of google keep where we can save and delete our notes', - component: () => {return }, - path: '/plays/keeper', - level: 'Intermediate', - tags: 'JSX,Hooks,ReactDOM', - github: 'Shivam-Katare', - cover: 'https://res.cloudinary.com/dbjmy6wdu/image/upload/v1651678725/keepicon_jsn5bh.png', - blog: '', - video: '' - }, { + }, + { + id: "pl-counter", + name: "Counter", + description: + "A simple counter which increments the value upto a certain limit!", + component: () => { + return ; + }, + path: "/plays/counter", + level: "Beginner", + tags: "JSX, State, Props", + github: "murtuzaalisurti", + featured: true, + }, + { + id: "pl-states", + name: "States", + description: "States in Functional Components", + component: () => { + return ; + }, + path: "/plays/states", + level: "Beginner", + tags: "Hooks,State,JSX", + github: "Abhishek-90", + cover: "", + blog: "https://abhishek-90.github.io/My-Portfolio/", + }, + { + id: "pl-social-card", + name: "Social Card", + description: + "The Social Card helps you telling who you are using photo, name, and other social footprints.", + component: () => { + return ; + }, + path: "/plays/social-card", + level: "Intermediate", + tags: "Form,Events,Complex State", + github: "atapas", + cover: "", + blog: "https://blog.greenroots.info/how-to-create-react-form-with-a-single-change-event-handler", + video: "", + }, + { + id: "pl-random-meme-generator", + name: "Random Meme Generator", + description: + "A project to demonstrate the use of API to fetch random memes! It also demonstrates how you can do event handling!", + component: () => { + return ; + }, + path: "/plays/random-meme-generator", + level: "Beginner", + tags: "JSX,Hooks,API,EventHandling", + github: "murtuzaalisurti", + cover: "", + blog: "", + video: "", + }, + { + id: "pl-keeper", + name: "Keeper", + description: + "Keeper is the clone of google keep where we can save and delete our notes", + component: () => { + return ; + }, + path: "/plays/keeper", + level: "Intermediate", + tags: "JSX,Hooks,ReactDOM", + github: "Shivam-Katare", + cover: + "https://res.cloudinary.com/dbjmy6wdu/image/upload/v1651678725/keepicon_jsn5bh.png", + blog: "", + video: "", + }, + { id: "pl-react-todo-app", name: "React Todo App", description: @@ -157,7 +179,8 @@ export const plays = [ "https://res.cloudinary.com/atapas/image/upload/v1650866465/demos/cover_y20bzk.png", blog: "", video: "", - }, { + }, + { id: "pl-expanding-cards", name: "Expanding-Cards", description: @@ -173,7 +196,8 @@ export const plays = [ cover: "", blog: "", video: "", - }, { + }, + { id: "pl-analog-clock", name: "Analog-Clock", description: "A beautiful wall clock", @@ -187,30 +211,56 @@ export const plays = [ cover: "", blog: "", video: "", - }, { - id: 'pl-password-generator', - name: 'Password Generator', - description: 'Its a simple password generator built in react using what user can generate password and customize their requirements in choosing characters and number while generating a medium or strong level password.', - component: () => {return }, - path: '/plays/password-generator', - level: 'Beginner', - tags: 'PasswordGenerator', - github: 'Angryman18', - cover: 'https://securityintelligence.com/wp-content/uploads/2018/10/si-eight-character-password-feature.jpg', - blog: '', - video: '' - }, { - id: 'pl-why-typescript', - name: 'Why Typescript', - description: 'A simplistic way of understanding the existence of TypeScript', - component: () => {return }, - path: '/plays/why-typescript', - level: 'Intermediate', - tags: 'TSX,TypeScript,Learning,KnowWhat', - github: 'koustov', - cover: 'https://res.cloudinary.com/dgtdljyul/image/upload/v1651923177/ts_why_adazpf.png', - blog: '', - video: '', - language: 'ts' + }, + { + id: "pl-password-generator", + name: "Password Generator", + description: + "Its a simple password generator built in react using what user can generate password and customize their requirements in choosing characters and number while generating a medium or strong level password.", + component: () => { + return ; + }, + path: "/plays/password-generator", + level: "Beginner", + tags: "PasswordGenerator", + github: "Angryman18", + cover: + "https://securityintelligence.com/wp-content/uploads/2018/10/si-eight-character-password-feature.jpg", + blog: "", + video: "", + }, + { + id: "pl-why-typescript", + name: "Why Typescript", + description: + "A simplistic way of understanding the existence of TypeScript", + component: () => { + return ; + }, + path: "/plays/why-typescript", + level: "Intermediate", + tags: "TSX,TypeScript,Learning,KnowWhat", + github: "koustov", + cover: + "https://res.cloudinary.com/dgtdljyul/image/upload/v1651923177/ts_why_adazpf.png", + blog: "", + video: "", + language: "ts", + }, + { + id: "pl-registration-form", + name: "Registration-Form", + description: "Registration form with form validation without any liberary", + component: () => { + return ; + }, + path: "/plays/registration-form", + level: "Beginner", + tags: "JSX,useState,Objects,map", + github: "Deepak8717", + cover: "", + blog: "", + video: "", + language: "js", }, //replace new play item here ]; diff --git a/src/plays/index.js b/src/plays/index.js index 754a500644..743b5e50a6 100644 --- a/src/plays/index.js +++ b/src/plays/index.js @@ -16,4 +16,5 @@ export { default as AnalogClock } from 'plays/analog-clock/AnalogClock'; export { default as PasswordGenerator } from 'plays/password-generator/PasswordGenerator'; export { default as WhyTypescript } from 'plays/why-typescript/WhyTypescript'; +export { default as RegistrationForm } from 'plays/registration-form/RegistrationForm'; //add export here diff --git a/src/plays/registration-form/Readme.md b/src/plays/registration-form/Readme.md new file mode 100644 index 0000000000..9d51d09582 --- /dev/null +++ b/src/plays/registration-form/Readme.md @@ -0,0 +1,13 @@ +# registration-form + +A Simple registration form with validation without any libery + +## What will you learn ? + +- How to use `useState` hook +- working with objects and how to work `useState` with nested objects +- Learn validation in pure js + +The file `RegistrationForm.jsx` has all the code required to build this project! So, if you want to get a grasp of it, try implementing it on your own! + +Keep Learning diff --git a/src/plays/registration-form/Registration-form.css b/src/plays/registration-form/Registration-form.css new file mode 100644 index 0000000000..17f0d7fd4c --- /dev/null +++ b/src/plays/registration-form/Registration-form.css @@ -0,0 +1,46 @@ +.registration-form-container { + width: 90%; + margin: auto; + max-width: 700px; + text-align: center; +} +.registration-form { + max-width: 400px; + margin: auto; + text-align: left; + background: #fff; + padding: 30px; + box-shadow: 2px 2px 11px 1px #ccc, -2px -2px 16px 1px #ccc; + border-radius: 10px; +} +.user-input { + display: flex; + flex-direction: column; + margin: 10px auto; +} +.user-input .registration-input { + padding: 5px; +} +.user-btn { + text-align: center; + margin: 25px auto 0; +} +.user-btn .btn { + width: 100px; + background: blueviolet; + padding: 5px; + color: #fff; + font-size: 20px; + border: none; + font-weight: bold; + border-radius: 5px; +} +.hidden { + display: none; +} +.error { + color: red; +} +.input-error { + border: 1px solid red; +} diff --git a/src/plays/registration-form/RegistrationForm.jsx b/src/plays/registration-form/RegistrationForm.jsx new file mode 100644 index 0000000000..ee3e7ca3b8 --- /dev/null +++ b/src/plays/registration-form/RegistrationForm.jsx @@ -0,0 +1,263 @@ +import { getPlayById } from "meta/play-meta-util"; + +import PlayHeader from "common/playlists/PlayHeader"; +import "./Registration-form.css"; +import { useEffect, useState } from "react"; + +function RegistrationForm(props) { + // Do not remove the below lines. + // The following code is to fetch the current play from the URL + const { id } = props; + const play = getPlayById(id); + + // Your Code Start below. + const [field, setField] = useState({ + name: "", + email: "", + password: "", + confirmPassword: "", + }); + const [error, setError] = useState({ + name: { + isValidated: false, + error: "", + }, + email: { + isValidated: false, + error: "", + }, + password: { + isValidated: false, + error: "", + }, + confirmPassword: { + isValidated: false, + error: "", + }, + }); + //function checks for all validation + const isValidated = (field) => { + if (field.name.trim() === "") { + setError((prevState) => { + prevState.name.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.email.trim() === "") { + setError((prevState) => { + prevState.email.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.password.trim() === "") { + setError((prevState) => { + prevState.password.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.confirmPassword.trim() === "") { + setError((prevState) => { + prevState.confirmPassword.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.name.trim() !== "") { + setError((prevState) => { + prevState.name.isValidated = true; + prevState.name.error = ""; + return { + ...prevState, + }; + }); + } + if (field.email.trim() !== "") { + if (isValidEmail(field)) { + setError((prevState) => { + prevState.email.isValidated = true; + prevState.email.error = ""; + return { + ...prevState, + }; + }); + } else { + setError((prevState) => { + prevState.email.isValidated = false; + prevState.email.error = "not valid email"; + return { + ...prevState, + }; + }); + } + } + if (field.password.trim() !== "") { + setError((prevState) => { + prevState.password.isValidated = true; + prevState.password.error = ""; + return { + ...prevState, + }; + }); + } + if (field.confirmPassword.trim() !== "") { + if (field.password.trim() === field.confirmPassword.trim()) { + setError((prevState) => { + prevState.confirmPassword.isValidated = true; + prevState.confirmPassword.error = ""; + return { + ...prevState, + }; + }); + } else { + setError((prevState) => { + prevState.confirmPassword.isValidated = false; + prevState.confirmPassword.error = "passwords aren't matching"; + return { + ...prevState, + }; + }); + } + } + }; + + const isValidEmail = (field) => { + let regEmail = + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return regEmail.test(field.email); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + isValidated(field); + + if ( + error.name.isValidated === true && + error.email.isValidated === true && + error.password.isValidated === true && + error.confirmPassword.isValidated === true + ) { + setField({ name: "", email: "", password: "", confirmPassword: "" }); + } else { + console.log("sorry some field arent complete"); + console.log(error); + } + }; + const handleOnChange = (e) => { + setField({ ...field, [e.target.name]: e.target.value }); + }; + return ( + <> +
+ +
+ {/* Your Code Starts Here */} +
+

Registration Form

+

A Simple registration form with validation without any libery

+
+
+
+ + + + {error.name.error} + +
+
+ + + + {error.email.error} + +
+
+ + + + {error.password.error} + +
+
+ + + + {error.confirmPassword.error} + +
+
+ +
+
+
+
+ {/* Your Code Ends Here */} +
+
+ + ); +} + +export default RegistrationForm; diff --git a/src/plays/registration-form/cover.png b/src/plays/registration-form/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..e6be607a04a5c57891c4ed3a77ef7aa8afb0adfe GIT binary patch literal 42113 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�yKC+MKry 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 literal 0 HcmV?d00001 From 49584fe15c56dc4c744aec9f61e6d62718c6ec5e Mon Sep 17 00:00:00 2001 From: Deepak8717 Date: Mon, 16 May 2022 12:05:11 +0530 Subject: [PATCH 2/7] removed console.lo --- src/plays/registration-form/RegistrationForm.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plays/registration-form/RegistrationForm.jsx b/src/plays/registration-form/RegistrationForm.jsx index ee3e7ca3b8..43cf7d8a9b 100644 --- a/src/plays/registration-form/RegistrationForm.jsx +++ b/src/plays/registration-form/RegistrationForm.jsx @@ -144,9 +144,6 @@ function RegistrationForm(props) { error.confirmPassword.isValidated === true ) { setField({ name: "", email: "", password: "", confirmPassword: "" }); - } else { - console.log("sorry some field arent complete"); - console.log(error); } }; const handleOnChange = (e) => { From 3d5fef425937c15d366b23dc7d04f128088c65cc Mon Sep 17 00:00:00 2001 From: Deepak8717 Date: Thu, 19 May 2022 20:36:51 +0530 Subject: [PATCH 3/7] refactored the code --- src/meta/play-meta.js | 2 +- src/plays/registration-form/Readme.md | 2 +- .../registration-form/Registration-form.css | 59 ++- .../registration-form/RegistrationForm.jsx | 396 +++++++++--------- 4 files changed, 239 insertions(+), 220 deletions(-) diff --git a/src/meta/play-meta.js b/src/meta/play-meta.js index 678c9a3249..b8b939de88 100644 --- a/src/meta/play-meta.js +++ b/src/meta/play-meta.js @@ -272,7 +272,7 @@ export const plays = [ { id: "pl-registration-form", name: "Registration-Form", - description: "Registration form with form validation without any liberary", + description: "Registration form with form validation without any library", component: () => { return ; }, diff --git a/src/plays/registration-form/Readme.md b/src/plays/registration-form/Readme.md index 9d51d09582..1aab4e546a 100644 --- a/src/plays/registration-form/Readme.md +++ b/src/plays/registration-form/Readme.md @@ -1,6 +1,6 @@ # registration-form -A Simple registration form with validation without any libery +A Simple registration form with validation without any library ## What will you learn ? diff --git a/src/plays/registration-form/Registration-form.css b/src/plays/registration-form/Registration-form.css index 17f0d7fd4c..488821e9c2 100644 --- a/src/plays/registration-form/Registration-form.css +++ b/src/plays/registration-form/Registration-form.css @@ -1,10 +1,13 @@ -.registration-form-container { +.registration-form-heading { + text-align: center; +} +.registration-form .container { width: 90%; margin: auto; max-width: 700px; text-align: center; } -.registration-form { +.registration-form .form-inside { max-width: 400px; margin: auto; text-align: left; @@ -13,19 +16,23 @@ box-shadow: 2px 2px 11px 1px #ccc, -2px -2px 16px 1px #ccc; border-radius: 10px; } -.user-input { +.registration-form .user-input { display: flex; flex-direction: column; margin: 10px auto; } -.user-input .registration-input { +.registration-form .user-label { + text-transform: capitalize; + margin: 2px 0; +} +.registration-form .user-input .registration-input { padding: 5px; } -.user-btn { +.registration-form .user-btn { text-align: center; margin: 25px auto 0; } -.user-btn .btn { +.registration-form .user-btn .btn { width: 100px; background: blueviolet; padding: 5px; @@ -35,12 +42,46 @@ font-weight: bold; border-radius: 5px; } -.hidden { +.registration-form .hidden { display: none; } -.error { +.registration-form .error { color: red; } -.input-error { +.registration-form .input-error { border: 1px solid red; } +.registration-form .entered-value-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.registration-form .entered-value-container .success { + margin: 10px; + font-size: 1.5em; + color: rgb(43, 227, 43); +} +.registration-form .entered-value-container .entered-value-inner { + display: flex; + width: 80%; + max-width: 700px; + justify-content: center; +} +.entered-value-row { + width: 100%; + margin: 5px; + text-align: center; +} + +.registration-form .entered-value-row .heading { + font-weight: bold; + text-transform: capitalize; + font-size: 1em; +} +@media screen and (max-width: 768px) { + .registration-form .entered-value-container .entered-value-inner { + flex-direction: column; + width: 90%; + } +} diff --git a/src/plays/registration-form/RegistrationForm.jsx b/src/plays/registration-form/RegistrationForm.jsx index 43cf7d8a9b..7e26f67f17 100644 --- a/src/plays/registration-form/RegistrationForm.jsx +++ b/src/plays/registration-form/RegistrationForm.jsx @@ -2,7 +2,7 @@ import { getPlayById } from "meta/play-meta-util"; import PlayHeader from "common/playlists/PlayHeader"; import "./Registration-form.css"; -import { useEffect, useState } from "react"; +import { useState } from "react"; function RegistrationForm(props) { // Do not remove the below lines. @@ -11,243 +11,221 @@ function RegistrationForm(props) { const play = getPlayById(id); // Your Code Start below. - const [field, setField] = useState({ + + //for input values + const [values, setValues] = useState({ name: "", email: "", password: "", confirmPassword: "", - }); - const [error, setError] = useState({ - name: { - isValidated: false, - error: "", - }, - email: { - isValidated: false, - error: "", - }, - password: { - isValidated: false, - error: "", - }, - confirmPassword: { - isValidated: false, - error: "", + errors: { + name: "", + email: "", + password: "", + confirmPassword: "", }, }); - //function checks for all validation - const isValidated = (field) => { - if (field.name.trim() === "") { - setError((prevState) => { - prevState.name.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.email.trim() === "") { - setError((prevState) => { - prevState.email.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.password.trim() === "") { - setError((prevState) => { - prevState.password.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.confirmPassword.trim() === "") { - setError((prevState) => { - prevState.confirmPassword.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.name.trim() !== "") { - setError((prevState) => { - prevState.name.isValidated = true; - prevState.name.error = ""; - return { + + //input values after submit + const [storedValues, setStoredValues] = useState({ + name: "", + email: "", + password: "", + confirmPassword: "", + }); + + //self explanatory + const validateEmail = (emailvalue) => { + if (emailvalue[0] === "email") { + const regx = /\S+@\S+\.\S+/; + if (!regx.test(emailvalue[1])) { + //set error and return false + setValues((prevState) => ({ ...prevState, - }; - }); - } - if (field.email.trim() !== "") { - if (isValidEmail(field)) { - setError((prevState) => { - prevState.email.isValidated = true; - prevState.email.error = ""; - return { - ...prevState, - }; - }); + errors: { + ...prevState.errors, + email: `your email is not correct`, + }, + })); + return false; } else { - setError((prevState) => { - prevState.email.isValidated = false; - prevState.email.error = "not valid email"; - return { - ...prevState, - }; - }); - } - } - if (field.password.trim() !== "") { - setError((prevState) => { - prevState.password.isValidated = true; - prevState.password.error = ""; - return { + //if email is correct clear error msg and return true + setValues((prevState) => ({ ...prevState, - }; - }); + errors: { + ...prevState.errors, + email: ``, + }, + })); + return true; + } } - if (field.confirmPassword.trim() !== "") { - if (field.password.trim() === field.confirmPassword.trim()) { - setError((prevState) => { - prevState.confirmPassword.isValidated = true; - prevState.confirmPassword.error = ""; - return { + //if other than email just return true + return true; + }; + + //self explanatory + const conmparePassword = (pass, confirmPass) => { + // (pass and confirmPass) arrays containing name, value pair eg. ["password","xyz"] and ["confirmpassword","xyz"] + if (pass[0] == "password") { + if (values.confirmPassword !== "") { + if (pass[1] !== confirmPass[1]) { + //values don't match set error, return false + setValues((prevState) => ({ ...prevState, - }; - }); - } else { - setError((prevState) => { - prevState.confirmPassword.isValidated = false; - prevState.confirmPassword.error = "passwords aren't matching"; - return { + errors: { + ...prevState.errors, + password: "Password doesn't match", + confirmPassword: "Password doesn't match", + }, + })); + return false; + } else { + //if matches remove error msgs, return true + setValues((prevState) => ({ ...prevState, - }; - }); + errors: { + ...prevState.errors, + password: "", + confirmPassword: "", + }, + })); + return true; + } } + //return true in any other condition + return true; } + //return true in any other condition + return true; }; - const isValidEmail = (field) => { - let regEmail = - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - return regEmail.test(field.email); + //final validation + const validate = (value) => { + //value is an array ex. ["name","deepak"] + if (value[1] === "") { + //if empty set error msg return false + setValues((prevState) => ({ + ...prevState, + errors: { + ...prevState.errors, + [value[0]]: `Please fill the ${value[0]}`, + }, + })); + return false; + } else { + //if not empty remove message return (validate email && compare password) + setValues((prevState) => ({ + ...prevState, + errors: { + ...prevState.errors, + [value[0]]: ``, + }, + })); + return ( + validateEmail(value) && + conmparePassword(value, Object.entries(values)[3]) + ); + } }; - const handleSubmit = (e) => { + const submitHandler = (e) => { e.preventDefault(); - isValidated(field); + let counter = 0; + Object.entries(values).map((value, i) => { + //validate each field, increase counter if validation passed. + if (validate(value)) { + counter = counter + 1; + } + }); - if ( - error.name.isValidated === true && - error.email.isValidated === true && - error.password.isValidated === true && - error.confirmPassword.isValidated === true - ) { - setField({ name: "", email: "", password: "", confirmPassword: "" }); + //if all fields are validated succsfully store the values in new object and clear the input values + if (counter === 5) { + setStoredValues({ + ...storedValues, + name: values.name, + email: values.email, + password: values.password, + confirmPassword: values.confirmPassword, + }); + setValues({ + name: "", + email: "", + password: "", + confirmPassword: "", + errors: { name: "", email: "", password: "", confirmPassword: "" }, + }); } }; - const handleOnChange = (e) => { - setField({ ...field, [e.target.name]: e.target.value }); + + const onChangeHandler = (e) => { + const { name, value } = e.target; + setValues({ ...values, [name]: value }); }; + return ( <>
{/* Your Code Starts Here */} -
-

Registration Form

-

A Simple registration form with validation without any libery

-
-
-
- - - - {error.name.error} - -
-
- - - - {error.email.error} - -
-
- - - - {error.password.error} - -
-
- - - - {error.confirmPassword.error} - -
-
- -
-
+

+ A Registration form validation without any library +

+
+
+ {Object.entries(values).map((value, index) => { + return ( +
+ + + +
+ ); + })} +
+ +
+
+
+ Form Submitted ! +
+ {Object.entries(storedValues).map((storedValue) => { + return ( +
+
{storedValue[0]}
+
{storedValue[1]}
+
+ ); + })} +
{/* Your Code Ends Here */} From 6d69cc73dceedf378843290a1f5c7d0f72ba8575 Mon Sep 17 00:00:00 2001 From: Deepak Pundir Date: Tue, 10 May 2022 20:43:23 +0530 Subject: [PATCH 4/7] A Registration form with validation fixed conflicts --- src/meta/play-meta.js | 315 +++++++++++------- src/plays/index.js | 39 +-- src/plays/registration-form/Readme.md | 13 + .../registration-form/Registration-form.css | 46 +++ .../registration-form/RegistrationForm.jsx | 263 +++++++++++++++ src/plays/registration-form/cover.png | Bin 0 -> 42113 bytes 6 files changed, 530 insertions(+), 146 deletions(-) create mode 100644 src/plays/registration-form/Readme.md create mode 100644 src/plays/registration-form/Registration-form.css create mode 100644 src/plays/registration-form/RegistrationForm.jsx create mode 100644 src/plays/registration-form/cover.png diff --git a/src/meta/play-meta.js b/src/meta/play-meta.js index 5edc878dec..e9c9c9a704 100644 --- a/src/meta/play-meta.js +++ b/src/meta/play-meta.js @@ -10,13 +10,14 @@ import { RandomMemeGenerator, Keeper, ReactTodoApp, -QuoteGenerator, + QuoteGenerator, ExpandingCards, AnalogClock, PasswordGenerator, -WhyTypescript, -NetlifyCardGame, -//import play here + WhyTypescript, + NetlifyCardGame, + RegistrationForm, + //import play here } from "plays"; export const plays = [ @@ -86,89 +87,118 @@ export const plays = [ tags: "Recursion, Tree", github: "green-roots", featured: false, - }, { - id: 'pl-counter', - name: 'Counter', - description: 'A simple counter which increments the value upto a certain limit!', - component: () => {return }, - path: '/plays/counter', - level: 'Beginner', - tags: 'JSX, State, Props', - github: 'murtuzaalisurti', - featured: false - }, { - id: 'pl-states', - name: 'States', - description: 'States in Functional Components', - component: () => {return }, - path: '/plays/states', - level: 'Beginner', - tags: 'Hooks,State,JSX', - github: 'Abhishek-90', - cover: '', - blog: 'https://abhishek-90.github.io/My-Portfolio/' - }, { - id: 'pl-social-card', - name: 'Social Card', - description: 'The Social Card helps you telling who you are using photo, name, and other social footprints.', - component: () => {return }, - path: '/plays/social-card', - level: 'Intermediate', - tags: 'Form,Events,Complex State', - github: 'atapas', - cover: '', - blog: 'https://blog.greenroots.info/how-to-create-react-form-with-a-single-change-event-handler', - video: '' - }, { - id: 'pl-random-meme-generator', - name: 'Random Meme Generator', - description: 'A project to demonstrate the use of API to fetch random memes! It also demonstrates how you can do event handling!', - component: () => {return }, - path: '/plays/random-meme-generator', - level: 'Beginner', - tags: 'JSX,Hooks,API,EventHandling', - github: 'murtuzaalisurti', - cover: '', - blog: '', - video: '' - }, { - id: 'pl-react-todo-app', - name: 'React Todo App', - description: 'It is a simple Todo App which keeps track of your regular work', - component: () => { return }, - path: '/plays/react-todo-app', - level: 'Beginner', - tags: 'ReactHooks, JavaScript, Css, React State', - github: 'nirban256', - cover: 'https://res.cloudinary.com/atapas/image/upload/v1650866465/demos/cover_y20bzk.png', - blog: '', - video: '' - },{ - id: 'pl-quote-generator', - name: 'Random Quote Generator', - description: 'Randomly Generate quotes from 3rd Party API', - component: () => {return }, - path: '/plays/quote-generator', - level: 'Intermediate', - tags: 'Hooks,API,Async/Await', - github: 'Abhishek-90', - cover: 'https://i0.wp.com/dariusforoux.com/wp-content/uploads/2015/08/motivational-quotes.png?fit=2048%2C1536&ssl=1', - blog: '', - video: '' - }, - { - id: 'pl-keeper', - name: 'Keeper', - description: 'Keeper is the clone of google keep where we can save and delete our notes', - component: () => {return }, - path: '/plays/keeper', - level: 'Intermediate', - tags: 'JSX,Hooks,ReactDOM', - github: 'Shivam-Katare', - cover: 'https://res.cloudinary.com/dbjmy6wdu/image/upload/v1651678725/keepicon_jsn5bh.png', - blog: '', - video: '' - }, { + }, + { + id: "pl-counter", + name: "Counter", + description: + "A simple counter which increments the value upto a certain limit!", + component: () => { + return ; + }, + path: "/plays/counter", + level: "Beginner", + tags: "JSX, State, Props", + github: "murtuzaalisurti", + featured: false, + }, + { + id: "pl-states", + name: "States", + description: "States in Functional Components", + component: () => { + return ; + }, + path: "/plays/states", + level: "Beginner", + tags: "Hooks,State,JSX", + github: "Abhishek-90", + cover: "", + blog: "https://abhishek-90.github.io/My-Portfolio/", + }, + { + id: "pl-social-card", + name: "Social Card", + description: + "The Social Card helps you telling who you are using photo, name, and other social footprints.", + component: () => { + return ; + }, + path: "/plays/social-card", + level: "Intermediate", + tags: "Form,Events,Complex State", + github: "atapas", + cover: "", + blog: "https://blog.greenroots.info/how-to-create-react-form-with-a-single-change-event-handler", + video: "", + }, + { + id: "pl-random-meme-generator", + name: "Random Meme Generator", + description: + "A project to demonstrate the use of API to fetch random memes! It also demonstrates how you can do event handling!", + component: () => { + return ; + }, + path: "/plays/random-meme-generator", + level: "Beginner", + tags: "JSX,Hooks,API,EventHandling", + github: "murtuzaalisurti", + cover: "", + blog: "", + video: "", + }, + { + id: "pl-react-todo-app", + name: "React Todo App", + description: + "It is a simple Todo App which keeps track of your regular work", + component: () => { + return ; + }, + path: "/plays/react-todo-app", + level: "Beginner", + tags: "ReactHooks, JavaScript, Css, React State", + github: "nirban256", + cover: + "https://res.cloudinary.com/atapas/image/upload/v1650866465/demos/cover_y20bzk.png", + blog: "", + video: "", + }, + { + id: "pl-quote-generator", + name: "Random Quote Generator", + description: "Randomly Generate quotes from 3rd Party API", + component: () => { + return ; + }, + path: "/plays/quote-generator", + level: "Intermediate", + tags: "Hooks,API,Async/Await", + github: "Abhishek-90", + cover: + "https://i0.wp.com/dariusforoux.com/wp-content/uploads/2015/08/motivational-quotes.png?fit=2048%2C1536&ssl=1", + blog: "", + video: "", + }, + { + id: "pl-keeper", + name: "Keeper", + description: + "Keeper is the clone of google keep where we can save and delete our notes", + component: () => { + return ; + }, + path: "/plays/keeper", + level: "Intermediate", + tags: "JSX,Hooks,ReactDOM", + github: "Shivam-Katare", + cover: + "https://res.cloudinary.com/dbjmy6wdu/image/upload/v1651678725/keepicon_jsn5bh.png", + blog: "", + video: "", + }, + { id: "pl-expanding-cards", name: "Expanding-Cards", description: @@ -184,7 +214,8 @@ export const plays = [ cover: "", blog: "", video: "", - }, { + }, + { id: "pl-analog-clock", name: "Analog-Clock", description: "A beautiful wall clock", @@ -198,47 +229,77 @@ export const plays = [ cover: "", blog: "", video: "", - featured: true, - }, { - id: 'pl-password-generator', - name: 'Password Generator', - description: 'Its a simple password generator built in react using what user can generate password and customize their requirements in choosing characters and number while generating a medium or strong level password.', - component: () => {return }, - path: '/plays/password-generator', - level: 'Beginner', - tags: 'PasswordGenerator', - github: 'Angryman18', - cover: 'https://securityintelligence.com/wp-content/uploads/2018/10/si-eight-character-password-feature.jpg', - blog: '', - video: '', featured: true, - }, { - id: 'pl-why-typescript', - name: 'Why Typescript', - description: 'A simplistic way of understanding the existence of TypeScript', - component: () => {return }, - path: '/plays/why-typescript', - level: 'Intermediate', - tags: 'TSX,TypeScript,Learning,KnowWhat', - github: 'koustov', - cover: 'https://res.cloudinary.com/dgtdljyul/image/upload/v1651923177/ts_why_adazpf.png', - blog: '', - video: '', - language: 'ts', + }, + { + id: "pl-password-generator", + name: "Password Generator", + description: + "Its a simple password generator built in react using what user can generate password and customize their requirements in choosing characters and number while generating a medium or strong level password.", + component: () => { + return ; + }, + path: "/plays/password-generator", + level: "Beginner", + tags: "PasswordGenerator", + github: "Angryman18", + cover: + "https://securityintelligence.com/wp-content/uploads/2018/10/si-eight-character-password-feature.jpg", + blog: "", + video: "", featured: true, - }, { - id: 'pl-memory-game', - name: 'Memory Game', - description: 'simple memory game or memory testing game build with ReactJS', - component: () => {return }, - path: '/plays/memory-game', - level: 'Advanced', - tags: 'MemoryGame, CardGame, ReactJS', - github: 'Angryman18', - cover: 'https://cdn.pixabay.com/photo/2017/01/03/16/42/klee-1949946_960_720.jpg', - blog: '', - video: '', - language: 'js', + }, + { + id: "pl-why-typescript", + name: "Why Typescript", + description: + "A simplistic way of understanding the existence of TypeScript", + component: () => { + return ; + }, + path: "/plays/why-typescript", + level: "Intermediate", + tags: "TSX,TypeScript,Learning,KnowWhat", + github: "koustov", + cover: + "https://res.cloudinary.com/dgtdljyul/image/upload/v1651923177/ts_why_adazpf.png", + blog: "", + video: "", + language: "ts", + featured: true, + }, + { + id: "pl-memory-game", + name: "Memory Game", + description: "simple memory game or memory testing game build with ReactJS", + component: () => { + return ; + }, + path: "/plays/memory-game", + level: "Advanced", + tags: "MemoryGame, CardGame, ReactJS", + github: "Angryman18", + cover: + "https://cdn.pixabay.com/photo/2017/01/03/16/42/klee-1949946_960_720.jpg", + blog: "", + video: "", + language: "js", featured: true, + }, + { + id: "pl-registration-form", + name: "Registration-Form", + description: "Registration form with form validation without any liberary", + component: () => { + return ; + }, + path: "/plays/registration-form", + level: "Beginner", + tags: "JSX,useState,Objects,map", + github: "Deepak8717", + cover: "", + blog: "", + video: "", + language: "js", }, //replace new play item here ]; diff --git a/src/plays/index.js b/src/plays/index.js index 9d3cd7944d..e8d73e618e 100644 --- a/src/plays/index.js +++ b/src/plays/index.js @@ -1,21 +1,22 @@ -export { default as PageNotFound } from 'common/404/PageNotFound'; -export { default as Home } from 'common/home/Home'; -export { default as CurrentTimer } from 'plays/clock/CurrentTimer'; -export { default as CdTimerComp } from 'plays/date-time-counter/CdTimerComp'; -export { default as BasicTree } from 'plays/org-tree/BasicTree'; -export { default as MovieContainer } from 'plays/movies/MovieContainer'; -export { default as WhyReact } from 'plays/why-react/WhyReact'; -export { default as CounterApp } from 'plays/counter/CounterApp'; -export { default as States } from 'plays/states/States'; -export { default as SocialCard } from 'plays/social-card/SocialCard'; -export { default as RandomMemeGenerator } from 'plays/random-meme-generator/RandomMemeGenerator'; -export { default as Keeper } from 'plays/keeper/Keeper'; -export { default as ReactTodoApp } from 'plays/react-todo-app/ReactTodoApp'; -export { default as QuoteGenerator } from 'plays/quote-generator/QuoteGenerator'; -export { default as ExpandingCards } from 'plays/expanding-cards/ExpandingCards'; -export { default as AnalogClock } from 'plays/analog-clock/AnalogClock'; +export { default as PageNotFound } from "common/404/PageNotFound"; +export { default as Home } from "common/home/Home"; +export { default as CurrentTimer } from "plays/clock/CurrentTimer"; +export { default as CdTimerComp } from "plays/date-time-counter/CdTimerComp"; +export { default as BasicTree } from "plays/org-tree/BasicTree"; +export { default as MovieContainer } from "plays/movies/MovieContainer"; +export { default as WhyReact } from "plays/why-react/WhyReact"; +export { default as CounterApp } from "plays/counter/CounterApp"; +export { default as States } from "plays/states/States"; +export { default as SocialCard } from "plays/social-card/SocialCard"; +export { default as RandomMemeGenerator } from "plays/random-meme-generator/RandomMemeGenerator"; +export { default as Keeper } from "plays/keeper/Keeper"; +export { default as ReactTodoApp } from "plays/react-todo-app/ReactTodoApp"; +export { default as QuoteGenerator } from "plays/quote-generator/QuoteGenerator"; +export { default as ExpandingCards } from "plays/expanding-cards/ExpandingCards"; +export { default as AnalogClock } from "plays/analog-clock/AnalogClock"; -export { default as PasswordGenerator } from 'plays/password-generator/PasswordGenerator'; -export { default as WhyTypescript } from 'plays/why-typescript/WhyTypescript'; -export { default as NetlifyCardGame } from 'plays/memory-game/NetlifyCardGame'; +export { default as PasswordGenerator } from "plays/password-generator/PasswordGenerator"; +export { default as WhyTypescript } from "plays/why-typescript/WhyTypescript"; +export { default as NetlifyCardGame } from "plays/memory-game/NetlifyCardGame"; +export { default as RegistrationForm } from "plays/registration-form/RegistrationForm"; //add export here diff --git a/src/plays/registration-form/Readme.md b/src/plays/registration-form/Readme.md new file mode 100644 index 0000000000..9d51d09582 --- /dev/null +++ b/src/plays/registration-form/Readme.md @@ -0,0 +1,13 @@ +# registration-form + +A Simple registration form with validation without any libery + +## What will you learn ? + +- How to use `useState` hook +- working with objects and how to work `useState` with nested objects +- Learn validation in pure js + +The file `RegistrationForm.jsx` has all the code required to build this project! So, if you want to get a grasp of it, try implementing it on your own! + +Keep Learning diff --git a/src/plays/registration-form/Registration-form.css b/src/plays/registration-form/Registration-form.css new file mode 100644 index 0000000000..17f0d7fd4c --- /dev/null +++ b/src/plays/registration-form/Registration-form.css @@ -0,0 +1,46 @@ +.registration-form-container { + width: 90%; + margin: auto; + max-width: 700px; + text-align: center; +} +.registration-form { + max-width: 400px; + margin: auto; + text-align: left; + background: #fff; + padding: 30px; + box-shadow: 2px 2px 11px 1px #ccc, -2px -2px 16px 1px #ccc; + border-radius: 10px; +} +.user-input { + display: flex; + flex-direction: column; + margin: 10px auto; +} +.user-input .registration-input { + padding: 5px; +} +.user-btn { + text-align: center; + margin: 25px auto 0; +} +.user-btn .btn { + width: 100px; + background: blueviolet; + padding: 5px; + color: #fff; + font-size: 20px; + border: none; + font-weight: bold; + border-radius: 5px; +} +.hidden { + display: none; +} +.error { + color: red; +} +.input-error { + border: 1px solid red; +} diff --git a/src/plays/registration-form/RegistrationForm.jsx b/src/plays/registration-form/RegistrationForm.jsx new file mode 100644 index 0000000000..ee3e7ca3b8 --- /dev/null +++ b/src/plays/registration-form/RegistrationForm.jsx @@ -0,0 +1,263 @@ +import { getPlayById } from "meta/play-meta-util"; + +import PlayHeader from "common/playlists/PlayHeader"; +import "./Registration-form.css"; +import { useEffect, useState } from "react"; + +function RegistrationForm(props) { + // Do not remove the below lines. + // The following code is to fetch the current play from the URL + const { id } = props; + const play = getPlayById(id); + + // Your Code Start below. + const [field, setField] = useState({ + name: "", + email: "", + password: "", + confirmPassword: "", + }); + const [error, setError] = useState({ + name: { + isValidated: false, + error: "", + }, + email: { + isValidated: false, + error: "", + }, + password: { + isValidated: false, + error: "", + }, + confirmPassword: { + isValidated: false, + error: "", + }, + }); + //function checks for all validation + const isValidated = (field) => { + if (field.name.trim() === "") { + setError((prevState) => { + prevState.name.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.email.trim() === "") { + setError((prevState) => { + prevState.email.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.password.trim() === "") { + setError((prevState) => { + prevState.password.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.confirmPassword.trim() === "") { + setError((prevState) => { + prevState.confirmPassword.error = "Field can't be empty"; + return { + ...prevState, + }; + }); + } + if (field.name.trim() !== "") { + setError((prevState) => { + prevState.name.isValidated = true; + prevState.name.error = ""; + return { + ...prevState, + }; + }); + } + if (field.email.trim() !== "") { + if (isValidEmail(field)) { + setError((prevState) => { + prevState.email.isValidated = true; + prevState.email.error = ""; + return { + ...prevState, + }; + }); + } else { + setError((prevState) => { + prevState.email.isValidated = false; + prevState.email.error = "not valid email"; + return { + ...prevState, + }; + }); + } + } + if (field.password.trim() !== "") { + setError((prevState) => { + prevState.password.isValidated = true; + prevState.password.error = ""; + return { + ...prevState, + }; + }); + } + if (field.confirmPassword.trim() !== "") { + if (field.password.trim() === field.confirmPassword.trim()) { + setError((prevState) => { + prevState.confirmPassword.isValidated = true; + prevState.confirmPassword.error = ""; + return { + ...prevState, + }; + }); + } else { + setError((prevState) => { + prevState.confirmPassword.isValidated = false; + prevState.confirmPassword.error = "passwords aren't matching"; + return { + ...prevState, + }; + }); + } + } + }; + + const isValidEmail = (field) => { + let regEmail = + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return regEmail.test(field.email); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + isValidated(field); + + if ( + error.name.isValidated === true && + error.email.isValidated === true && + error.password.isValidated === true && + error.confirmPassword.isValidated === true + ) { + setField({ name: "", email: "", password: "", confirmPassword: "" }); + } else { + console.log("sorry some field arent complete"); + console.log(error); + } + }; + const handleOnChange = (e) => { + setField({ ...field, [e.target.name]: e.target.value }); + }; + return ( + <> +
+ +
+ {/* Your Code Starts Here */} +
+

Registration Form

+

A Simple registration form with validation without any libery

+
+
+
+ + + + {error.name.error} + +
+
+ + + + {error.email.error} + +
+
+ + + + {error.password.error} + +
+
+ + + + {error.confirmPassword.error} + +
+
+ +
+
+
+
+ {/* Your Code Ends Here */} +
+
+ + ); +} + +export default RegistrationForm; diff --git a/src/plays/registration-form/cover.png b/src/plays/registration-form/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..e6be607a04a5c57891c4ed3a77ef7aa8afb0adfe GIT binary patch literal 42113 zcmeFYcT`kO&?h{if)Z7N1OXL6a?V+jlEci9qa?{WGk_u>Su&Dy7;?^8L_l&510s^c zkkbJ3-FcpU_kH(#-}ld+-GBCMpE+}T?)1IgRb5?G{j2IwHI=snxRkgc5Qsqjos0$u zbT17Ax{Lb&8@SV1Z-@_E?zu?GLmmLd_kr0L;5UV!xH-AGpL22v z^KuFE2t8L*J_FlBK%nO!d6_p5&$L|xOdoQdevTFp)FD#8`(EHKU#PS)OS8OWDt0X* zAcgc*Xx3I(GQWaLZj-Dj<@>n!*i_jR5zUJgbS6nrF@{e!oy^ zTA};x+8Rqsnfn&^*J&TfWiXva^5oQ4biK=Q{nt075D(|C)RA+S?kH+hi5@@!Py*yx zS5{U6#W2hOioPUkPjC>y8Tr3I9q(j!Km4~^@X`_MpISgM(B!e;oqv9GibDRQ2Dzv5 zZ%fVude(@V$^UnQ|7=Qj#PDz1#+S`@~{Vp8Ip-%%0r6P$fzfACBT5QSsu*}}{WC!(|G zAW&lwFA`$^zJ4HGeDKGbbzg;IJiqg(9N&qPJ}|MvRG7Ks9QE^;tSiJyOc%^b=?Uac z!Nchz1%ZCIz5%9)98wqkdUISc#KXU75#DGM7hh#ujH|fkoJO;&o|#+aR84VbP;Qpj zULP%*2J401_PM;z*k!vp*0$K0n8mqhB%}$MULu)09#I}08G8xEkJ+FGf$(8~lm#3w zZ!ri-6ve@`io=kq6Y>34x=n*GW{jhEY$Nqbb1ZAjc9PfmxDDredv%SeC)EjH|I!z1 zUWo$&Ng6e&%+{SzSvki;N^G<3Dnnez@aY!~%6pEV!6laRejbKa%MzX?v)}vosr!IT z{l0!b8_!Fp&XtZ-V{b~Kayw~oy9ICQK7(t=6e=5)jsD3NHn)yYerSsA^XO?-_+ev| z>eL^q)n=oSo*mr?Ri5CWSURo$Mz?pxZG~{m zxU~q)gi)a|#l+tvdHMo%r|Iva5xhJ9TZ;H4bFUnc*2$Wta`{AlC!rc44$X0&Z0c^#d_R+-VQLc8GS7%CT?4eY~h!u2tTfM*NaROI}yX(mOkq} z69*SkLE6NPnreteE7}Ij!cvp7A{_n#`Zcf^EEV}#|HjxL)NptI$hZ7S^R-s4B7sAq zXGX)$YsRyqcLtQy#j_j?AH1humg#rY9G@aKR-ccI48e5dQ(W_*LV79Q?IXp)BO`X! zpZ=6bKwMq(-d8AV{P^Q*_u!OgVLUH*fKRvmxh%M%ZJ@?)@t$&E zTg;>?dT{7YSc2G#%GKHt1Hz>36(5?3g1|c~QG><79wn0p_6htqj%|shh|*rmj--## z@T*hBc)dy}!N=N#%QXPun+@=-nRLWB#@!*TEYvc;@esw>O1whfJ*dMvSP&(Pi1Sm$~2w)>Ymug>T>hso#3E*O5S@Qx7)_dT?f!ks1GH*_uHv4clxLmK|ddY>dCCa8-P0C}Z zAuT4C+i2o=x`_X|jVny;wGYar+Fd1EL7z~gdTr7kBvNqlWy(#!Swc3FL1+XUvDchpMRF8KVwbof&)ub$2&R7`WWsJD22 zYA$61KDx94Hh1?sJj@Us@+nauKJo^Oq^ItG8&Hs+v@D3K=14K) z_z4-_rsO;SQ)*XE1czLoQbEsm*%QQ)i^@&=-3#46=%~b{w1}nVC`JwVnj_XVrbcMN zQqfd>(~h!g~ewLHjvA>#f%!2x{1?i?E)2$F z2V-~cge#tXvMs~MPi0lFR+fiIDaGp#5l-FItEem!%@tZh8W~j&JLXH3mX9JQ+)4dP zvUV!_In8Pt|875E*C(9XN1`(BTP+oL7h-i6#PH`^P+@To<3)v($YNToMnKPYLC0k znsJ%^+#v7Izk=~0Y)49~Le@R4)RRo&9#iD6l)dQAAuEK_j!d_iE^BVJ(ro+aD{uSi zMljC(=>0j`=j{9YLk47%2BzL+wCXl(3@<&E!{N+qaNevvhyEa>| zbX@8*ueT`O=rvFt27^(@4|0^Aiqf+4WfBs`r<{{8vP^xQ*m6mIod5Ij__y_fEYq@e zN>Yhdxo;i5N{83?@j;Ruxgo?L<4wV4Flomr`ZvY51L&F%&_P-MOEY9=X3Dm;n zJ!jSlc5E|Ih&ti3KJSF3)LmN5v{`t*0V;nPEceG`y%$yF>uG^SeSJUTE4fJrNrkzaWBL zJn7(|Ij1^!x>*{aZLHKxb7R#sAk1##GF8&p^MrmO9+GdK$8s!}TDsRad}<$q+aQFc z$xkA&!Idx{y`3AKayo{#o32W6CPl=|h6fbU{#aU(DNdAtuF>-AASkH_4_9;;uPyD z;;&A!DW9_u=%O5BtnYR+?EErku0!k4!Zs)SOvF=c8+VU{gFEt z_%^Mv76mMJD$P&&&LAcv`JY9muf%9y+YBT~upDd*(ict;J5v%@LuzXbUrV@d|3y1( z=c2(C)ImDc_eJA(jEnhOrKJG}5*zCu8$GiNxhaPZ=%_t!LE@N&E92dYO>Nw5RXmH# zho9ew3W;l_8ggi^Uj(RT#2gOzwM)_C+4+T2FDO6}hvaO0^VbTI=o7(k$pYO5&ndRexdg51IN1 zDJYFlc~1v?ItpE`HaEX`)~>_8=hLJ_;P){!`?C*At%pr^wL@iprDvi}#h`{^zc^GZ zb$$c>s%EmIRc^{}s3JH1%B;@4VhFn37`1BiQ`r0?Zhd>%c)(1EO1#w`+1u!7Q`EY} z9_z41tE!sZ6i)dD~NtBF6m8}h^ zZizcqvn^(&(<{OWH4Xycn`nA@YP&DzQ0?Z|-2mF9eA-6dHghH&V&-j5@NihK#s?fUd2diC(cypSb- z#a6OqV#n0M?A0j4h-DezU*`+u8Ko)HUW0SXr@BA&FFsVSx?|2z*zOsn2&u+CUtYqec#>kgHR?`Q}Q7z-3oBZskTpYZ3_OQCak zcW9MVsnvTPqWN|*Rd97q$Gn>AzIUi^q%0detueo4ylNcaubWD71&&o7Vh^xy((*Gba*Z+_s*8$b=tFh_te*O zwZ?|dBSQ^CXYzsDw=@3gzVrI@u3C0{3B1#?S#>%Ks-G+G7rnZpx>vC2^w-w8MXQ^s2^%yck zKi3Rqc%`y?RmaP%9(pI?qwq}?mR=XIgE$`Jehj!%+Bs$@>t?dG^2zbb7jOm@p(*lh zKbUJl8;_TZizKnFV%m@UDnoehfATLe6z@NKYcdg=X`4vr6Els?yJ|0Pt#zs1GBES> z9i5%RfOeMbIij#vAbD0A9`|BlipyYmaWOCY?li53+sKQ+Q@q2l+Sx!Vk@Lb1J~)^0 z_OhU!Es@6&?@i*fCE3ih$$r&5_PDona1>J@9sUTfG|xFqD)EThHao;cwptFw{=o{e zS{x8CXaN=&seZ*|p&t=ExPc$R7U}Hnfz`a?R2{jue)ctR4^_n@=lb-{TPA1E&YX|? zN%ujWvSFPML5_YDaq#O6Bs7N-dUNAzcVss!_EO!8!*)9M@J8hG&&MA#)kGTerf*@k z64S1vH%DUm3Ad6|{7J=ESv;Q1qgEl-4P_d8XBu{TP0Hphamtw*Pfbqh$cmqy(n)V| ze0^jZxw(3EGjx&E#O&$*rb9E50*0uF>6w~R)kq2+-vPGouHj5>!1gKpaYekB&OllR zL{@d}LRHMV-Uiw=U5?s_sKSO=kt-OWEMZq$-^BG(p!K6X32e?v@n{^2BxwQyF=d!@ z|KZ16)s{uJaA>i|(~?~+|7jz%b_q3o??4Nk!Nci*581s;K4ZRY3)6NUFOKh1yCg-m z`{(tw2%$%RFO$HY`?AY%-2u-jN{fSZl7pAk}G!Yo_=z{utb7b>^g{%`v9ogwy6w+0+Uc6y67cDvK@7tdb*E`Rl&40r&~?tMp1s|}G`I=*sw z$e*v}->aBbjIMWn>vtf^wuuc&+2x&!a=3pBg)8mWFFygc(2W>?V%SuZ&Cj|iR_=-w zP>nkt;Seh3vdUM?c8Nm{>Mm>63D0(4&R=B7xU80jwTo8Yyoc`Y@-2aXMyo=tJ8`zx z1@LN1Cm(zJun{IyFsk(y(|DBPutPTrKWxv$3Uf?6jlaO5OJwY|WCiy(+>FexSquL0 zKjV^rL)`hRl(ib@CwRzz?ogxb*Ycb!C$Iy!5-ppbS!nG4UZwXWA%kqxXuEAnS7-i_ z_YGMgGYyfiI05~LJQ0kn?!~Lib$oOUPe#3soxoHe0mqt^vg84okW0D7TX!d5AMH3s z2RNK*%M5JbE`b|qteKT3VrRK(FFs~Zint{FP3=r8S6|tiV_w=otIxZ+mLx7`R9IWa z=@%O8J!SIpixQ?CiY<~2*SJCbsTG9Ac;s?x#{ay1<3kTtjCv!JC}jNo`hxYpy@^Vn!}y2z|ssoY$w;S>+JN?phhoP#^wdjpI9 z-mg(>PxF`pOVT3Wj&qWep^%c=vs+%}k%}V;9%F%DG(O`E`%t)pld57IT@lK@S>G|&xk2z+fRp{Lmr#9;-}P}2muYdL;RZTSsGfD~H@bN(!MX2tT8j+`e%v@F(vFvIV7(F@YN!E!(D`0Uti) z-gc-4o66kGMt{4wDkTMd&y?BK-1MKP?9h3lB<~U%-88siOb$~;AqyLmp}Mt3kBA81 z4f%hyXme_Qg0+NreXZE~61tJDy9rlcQ8pSMmM7*DmWp*N_dAHo50hBvz%AD+N5Wi6 z*4zIc=xoNW4nYTCE(vDj+<#+tSe;)^^oiRS`yFf&D*G?)BP_zfXB%Wz+t$)CrZ4kV z)2zj*|Fj1yhi4k)*WzWv`(le)ksMRQdecSi$6ikTRV9)_Ex2Yfx};WCi983k?y;|= z9}<;AZ{u%m)d@kMU}0v=+LqYCA{C`nvvP$i1l<>rKC$GEKQU|a<6I_l{K1}-5*2-ih~J+RjiX(3GI&a4Y*iO7`24$)a$D zOp6fL+ygkw`pizZk@{tEt}Ksi~Vy%B~w|YlnAXn zVanB0@0J@b_mc5xO&cU&@FTXo>`bK+aot>gAjs&srjNUj7jkpsyxY=(Me zZS*>~meGJnKllh(Fiu{;!k;0Yp^2K=2<`k@e_AShB?8RAGW*QR@*db~MZoIxmm4KN~rr3;^m+Z0AQB=$@LZ{4gYM?f;wI;W>GoBLe0ByVC`0XI zKox_6@x1}@8jbv%I&m|izX6|^-z7nu=Q2-;v~|VqKmy@f9OEaw`OX&^b;Gemy9;qR zwyhYT_%eV7z}j60i;wObsqeE}{?v=)(v*ek3>E6XDeI>1Pt?o4yEAT83j|35!f`RU zyz3x**R6ulK>_kp&!8~P+5IuUYyk`1~MmZU(3<6b12is4g||z&o$j zPH;t9>>&=5W980Jn?SpOV?yvYz_YtEhm=s;g>1NoHN?O64IyA2*n%T|lFu=GXSpn? zNoaDc8fQ3R_=X8Ruq*xd2m>kRVN5Y*#`K3N$ru;wpYmTK6&QyBQ~qzWf7lRE{68{e z*u&?DI0LHp zP-9K0RbfJF#;wD!vr1M#UnIfBE023xp@rahs~;CV-6FArJb zK$o_@@xCymN-C+QYYG$#!<)})C%gmd^oj-|O`TsKJtnUByz`_jN&c`pYPWGJKiKa6 zKze#s_%!YQCIl`$-W6W z91YC-SG;USM!6R9LnuYp<+6uiEutD#MoQz0r1@}%{r6dHZp^KIjqf|Epl?cAcZxss zBc`~@8Kx4~ZT4pvFj#f3VQS7|p$B}WjW30Ux_HsRKvb@%SP?+K4ZoIc&FGTCnxJtS zHPFVgH?$#*EjxkCq{|5fOinRjQEdv~nxonkgF@#0YUV4OlF8@&84_>ej%@x4w}FMm zdfc}1H4*0pNTQxB|HFa@gzg2U^jbMnYXF`FTUP8+tX>FNe zg??Vx#K#?#(IXgc^6gaCpNdHEK6{crAR-=Hjs}$J#m>t(H;M^iNQJRH7CKUDkvHIu zjEbY4kARYy9Z3`>ef^f%K1l3?);04FcebNvHc4PA`%}oCvR7+CN$zOLMrlJ|qnBR& zdydqswKrhyREX0IRD5CQjTU%QpKwkKg=R&Z)3v1CfjVIj)mC0*aQh}~sN6Sy7+I%= zc8$&HNG=TXP^`P2zSj$Dlkw-Zxdwrt>jeE6EzoXr4Uit?~o zM5NZ8&(zK9q?Pk5Br)#{kB@?DSVISfRVKd)4A#;a2hGnk449;s$kyb%;_J`IESU33 zog~jJ$;phjnHXpan@4|LM`)3qthAz})e8TVlB|_GsQtQzG9zkr?$7a0iHRu+afn>M z7K5q5(^9#i`ZkPvV+70#7t(B(&bj<%BV#GT$dvx`gp%DZnf`asu6@`%s>E6>#jN|# zpT}shq)hkd&w}v94ve{pPT{PNC*f58>Eo`X@q}CYBGfQ0Pu<$~nAwTEt>Q z#K+C`muo&w z&kI8H%N%%FywuD8py~w-*eoG z7pl9kFR{!XEH7)JG*3;+g-DP4(Cc1m1TwHzOfPktbvQXBr{=7&Y5eqkeXq}dt>gm1 z$aaf_c{^!BP~)!VBi~9FCuQMDWiXvM<_tfjsR0cuXj64xJ;!O7+@t@<1sMK0zL+Pf zjP_14R{!MYk+1|XQZhOGL^_$mT5UP=K}B2C~cE4D!4eC zQJPO<%{NFd-nxIO>+-fate^>E2+7(m%7>R4mP|(dcCbj)sCYLq*>_xLvLe2we8B47 zBo6M5>(HE&LN;DG0IR!`6%%L<1|{vXFkJ8wL_>zjRAoa~hY;|FJew^s>KBqCimi!@ z>E%CHq41+`N2afaram3wzV{WHLUn1ylH}**c~T_yD_mN~FE>wfs6tzxSv$INEjqdI zq2;9c*38o_on6}Mpd#sq!16we@ENhEuFJFTm+pVFYIyQnU&rT$Bb#Ba#3qla$@@bh zT9D8EVhfkD24!Orm^k??SEY#hU&qwrtB{I9VV z`7G=Hd)1j=UnN;DEtZVcIG?J?^7;8{EGc^CfC)d2F{muP<7V zz&g%_mr%XZiagtMV)9e5?-Zn8xW2ETnZApH4cvXJH1kR5_JsyIk{0llf-uhfJ#vLB z_aMT_Nq56A`?Jq1!#^09xaFoFzu0#RQm(qvR#}#li%}25H-vJ(^&7?hh5!7<1AS0lz>5} zdutp(|^^Lp!@H>uT6^D|_PH+r7XEs(ybH=Z@CQJ_Va6~i+1tv%V9 zE_UOz*r9cb*49_Qd}c5tFPi!P!>3>jT=t@Cf_IUuc9D{po=;%lGL$6wRnzUCQTg71 ztC73hG7>R0&b%H<_3rJ4g}yd{^_ng5M-UZD#z{oul&8ipSrGo$PqIwwF0qtUQ$@c~ zy!`wF`DZmKf@r919%RB(L*sWXT_L43fByDTz%ze3oh_yq-K%pvUg$f@Bxta%U)=VPh3aoEi$*B>B1z`r} z)hq}HUA4YOfsSXhtP90Q7}3h(CJw5&`njg z$xPjun9;{Enk?|Z+IKkoj9qU3gPXH&Sxw=G>sET({FPjSil1A(##?w>2RPpPEWX&= zD3D<}?J-IJg}pSHJlnXXLHR`860%VFP>V_!>?3*V*Ef_6LrDwBNlYN_o}UWs1OkT1 zJkn0>^2bZNrKO^H5od1-XZJ#RQVIQBZ**YZ)oBTI%oc2|`+h@Q$eKvrNZ~{TWu_!u z+q&rpIeNDU{vdewVU#!nWWgo52K5Mx=YN zM$OZoXBx$cVpFVib~XME-{c1&j!42GA7QYI>QiP89(AsAY$&?%9n}&oTS~mGot5slbSAA81-3?UxvOx4)bJfQ1{H&V4uF`)d&b%25kkwNSQ`Y z@_pt(-rTu*D6y_WLc;#&xI;b**S6^t)Lx@MQFyLhr@YVpU>`iMJQ(k$7?+3;(0XX9 z@4U+~L8OI@zlGIk^bt&BjJ-|~CZ6pS9E)25g~pa7=kA=&8q5u_F-|Da)zZ z+A>XK5*lbP*BJ(L4GhQ=ZL*m%p3YhCv8yC4c|wE)=&i1Drr=fVT657ZSED`hu`xxh zGiSvoQH)cfNo8BbOaoW@_DnuC^`az5bmOWsR2N!qu0=aGkDB0RbBm(!E7P&EVTL?% zWEM7^Rv=}I0K?P^xGgNVLq2|#NBQCZJd9S-($%O*8wyp(+#(>0$eUBB6PyyYuOFA< z4Lnb9HL5x)cPjc@&TGCH%Yk|gqmV?NPXI^}LQji%g=42qP)vTpVNffmO4}w8hxb{- z`lgSnh1Erd?@)Sr&LZv1eKB~RxR@m@fm7nGJXt@#gqGEd)YQ`$dd;on3eEnZ%wp@) zCu@tR$qIg^AI@q>=iB%ZB2-TL7zP292z+qyt6v`)(p=ezRPd{oYMHS(6@I`A!^kzS zNv5Co53$)mU|-eQX|q)KE;O8~cG9rqdI#Hw7bY;-M+E8&iohi31%$_fMGVU|jZ{Kd>hycilI<_qI)^uO?&JP*`0?{%7dvs}>H^>{@SIJWYan_zZ zyB8GXrqtnr16yAB9Xbk7{Rp7ixbuX;c6-nb`D1?GSK!(8bBN@f&P%37oyNaZ*q6&R z>rY>Lm4}qj>En`$2H_?>NC$fOXAm+YCUGq;LHmi9OViW0Q!Qn~HZKYgK)ga?X-SDD zqw?p1Lq9R$Wd)Lo%&qn5=OC|cM)bekdSbf$+KAZC+A+XU+CO71_`SAdcj1pjYp+L9 zgNzB$0sZLnx&{-^WYH<*?7J^jfBv0|a+v+wHsnw7-@3mtP_;~U3AvzT{(wu(?^WK= zzqc>$iYvtZi4jEp2sY^5?K_Qpkm8%<0paobRCM5oj`U$pZACs_S;;_oF44B`Xsq1> zZK?uOHCiDRqI?Tp{}lMDVS$+U{__4le)9ah=wR!@)@*@?SKsO#5VjWb?k#6#7(McQ zsa@G5y)AXoUUf>t#zuSN=-_~}39*vC@BlAve!lgimNA`^)N7EWKafom;5U(4Deq?j ze%m=YJ-vS3_WHw7h5Pnwus`Dz!t^d^*fN{yv&SOY`Z1rriAmYs3vi#Sh-!Y^M&@I? zy=9+*39s(LC^f*paKlK-tt22RcNqn3kAh`yP2v_dUe?vs^$U19w=76$%HHQELz?hf zAZb8ZdSW=jU6$E+$Hgi~XU<0ifOw?N&v(P5iVn^O7#c+HK(!?|Wf}qcjWG0cH18~s z%+?gQRQCIS6Y$jV*(8Bi#Gy^k>neccmFM@*jE>mx2-CV@iC!ETmHi7dOroOt8hR-A z?x{nX-w(en?m<=U_8Pp@0FH7}0f`j&50;BvGmv64i0ucVpLz=T>+0N2oUQlplY|p} z_IJ{~pDw;j69*Ov?`K@EZY-?Ar~!t{Amt20m5kB;g?FNyp12N1>*?=jrWt}lP$2+l zm>dcSwbE04#NQin&PTZA@10u^)^>I~rN&1~>jWvSQ_8nuX;>&JHxUJHKmgR*zV)vA zxHm^tv|Hxk;iq+Xi;^m4Jnu))aNoyP&8V=mTiLU$J%(_5NxgP}5<`I=cmNbYvI7r> zEu<=$clJpB2s!eX78rP4eZ|cBgkWpgaeI5@_nX2QHy#XRNUkP^qmo@XbE%ShOpq=L zRo*|lRa)6wiTS%VM#A1t%$V=DnCW{|e0zJ|;h|D^ zjIFsMzU+}!rs7AcLfrtK0%nl|qlkmiPIm)}u~OYb#Oc!gzx=gF&P>i|6i<}Lpzl;|1^m{iK(m8$fSA8-%O#U4x2UM- z<02^ll?}hI`f1&!-xGq4yFF`&CLvqbv?-ZK@w>Gyz)BL zNfSM{vTLmm@?h6tzgYd~cM)Pz3^mjPK2~&M;LD)x9@`VBD@+dGs z44>i0nWRf`%C2bki1V98iFrylppl2r723f{8i~x02(#Z{C9V-hcn% zN67;EErqEK6RUe(-LJpAr)+lzef{;5s_hDj6iD~z=@`0`m3g76^moW{O|?6n+Q`1yz1Ny^gUicYcewbsdNJZ+M9NAK;u#Ir+9)gU?Fbm^(Hf1nMrR6wt|F_5*;DxmxX3A}d zBn(q?f5;gJ8euHyrdIZC!1-SKO3frk#2+GmQ0E+;pZ{T5-rhyKOXQtr6rkVl|1pct zE64lK0|Q2M?}{=5z6718f`PGl+4B60VO<Uy?NSfA}9-}$C@=%bmXH3cNZ#P z^#821u_@X^*yU;l5s)S0@_3t;9FhJl>YN%B;Dxb3YK=Zc#($#yfcHEUSHF*B0|k7P z24?i8yinqxtpP{C`93I1qVBQG9ncjfh5IB|&A$gc2dp>$Y#)IjaS>*qA4~)rh%CH> zOkn++L&7pexCNVf<76PYy5W z&r)Vg)v_Qp%mJs$y(jMRt8W}U~lEl2!zR`~6wv)fi-qVxwzS7H8X??eH?I9E6Mn7zG^R9f0Ic1`Mfnl2gYS6vR^Fz3lnaV~-GQ~jU-V9yS z$d1}-iSFU(&UnX=S{jh7|6kg-SX96FuaY`PYmLOj?WiVrpGAF3A)(6tGFFumdl)c1 z#cPeC&Lureuym8rc)JGq-sWO%tjG2-JqnTz@LD6CU0-xRR@wTU6(yE)C=%d0u zMcSF#669nvI=R5qykgt_wMAC4LXwnGQ303MSK&935Xy(%@u2vYjb1#8SeNx`kM!AgYg&q)*h8NNli7>p z^lfeXar*iAD`Q{3`HVS%3+0{0OLB#1h0CZ z>qYV_zO6E&-K2u0;-DFn!%X9?J0fv&{I(6XruCf!-MA!t^vU9YgAC}?xDzvx-tI%V zcGttN+D_9^bzF|t={tEU8T=$qpFaH)<%HWb`$bI+-(2P$nRM=3Y<2;X7fF*Z1*naq?Z7>U0~D zNfn{pD<_Xq&4~ZRu*kQaS6tXgRW|FN7*QcsF5u^yDi@;N^Cb)n`Lc$22{s|1{{xn) zlqSPy#k1voXvgUEDBGYiKX}cr_2Q#i>s1o`k2}J51UNpdqLb(HMHF}}M!p{2-l3)t z(upI6vHy5e=5zAU?m9h`2nTrI@6vw=My8N@ue5+&OZSsUx*3Ojwkd{O>?Zdbmh#;s zM6&3RwBvgD(VOdOd(H+X`@Z$b4&u458E7Zz(C#%fIvoZMdoaZXBX22z<*NY08#Dv6 zsqm>X@b*q)j9NYE|BhocO8hZ9YEPxD`P@zHsJF-aHiIICn@^f3o{wp@SK#CqB#w%a zBChWJj9=T;5aS+t<)&F^)dFz|$>&Ag-&;myraYd#i#fX28Gwg6nc&&)qPYjsCtq}K zxv2m=gN_}0k5pZ~g}?3%#brZf)6<$wh%&&j1l!nz>+0!EO;5uU6ER+(^>|)rV50;m zAbb0~1Krl$6Jj-6X@W~c%Mjk{0-NPjM9rA&HH0v+vI36$3N8^*97#bXCll*07r@-q z$Oio{IDD4aMFTKil!T0bmJaZk0vE)9D`3X{(Wa}?Pe5r@-9A9zKLWrU|0$gRs}8dT zEZKM&nX8Jz(bscMbrr?8+ecr~%@<02Xv;#sTlYW}-Zc^}Ajq7>>YmU9r zHo0@9NJ8D!o;D7fo{SOKz1?T#y^-U~(X?u(B~w>L$|<`whT*F-!o2Kn&qZ(9WO;8? z99oZ343`|=jnS2l4Jl^E5B-_!qDJS>@W0(WGPk0nx{WzQpY+X7@GCd44vY(~@=*I% z=t^+FbkL0)syq@Bj&CvilAOWBp*CAqv~1SdX0~&UZuLWMX&m(w1J7DvQl=B_Ko;%~ zo865*X20#3)3V8`t_2D)orYggS|<`ZBu#eRC1(&9P*%ITz zvR~mjnt5vkb$VvhXR}Xjm15hXKgPAn>oqOlHaJCV<-eDS{eA>9h7&A|N~n4A*uTb} z0-ZU3C>Qu={2i8?Piv}#8>#9!v*y6Jd^v!l~S z6zFpJtS>CDP*z(t(P((I_+?zZD2f{0Ra;v`e~Yw!>|hJ@0wjoZ4Bi1*GD*!WrWJSq z3HGP7)mZj5o3Wjg^9PR{gnFdx1U%amg@;3*vg^n#X9b=A8r`_tfL2X9EWlXrwAUC` z3HrncFzyt5poY)p67PNcn$u@(`~4x`b(eoR!qVS%G_>Bur}0Zw=8U<�yKC+MKry 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 literal 0 HcmV?d00001 From 97af6430fbaf60c862ee564e51615afb2de2bd19 Mon Sep 17 00:00:00 2001 From: Deepak8717 Date: Mon, 16 May 2022 12:05:11 +0530 Subject: [PATCH 5/7] removed console.lo --- src/plays/registration-form/RegistrationForm.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plays/registration-form/RegistrationForm.jsx b/src/plays/registration-form/RegistrationForm.jsx index ee3e7ca3b8..43cf7d8a9b 100644 --- a/src/plays/registration-form/RegistrationForm.jsx +++ b/src/plays/registration-form/RegistrationForm.jsx @@ -144,9 +144,6 @@ function RegistrationForm(props) { error.confirmPassword.isValidated === true ) { setField({ name: "", email: "", password: "", confirmPassword: "" }); - } else { - console.log("sorry some field arent complete"); - console.log(error); } }; const handleOnChange = (e) => { From c5b483c0cf5956d497cc33c1c61483c635dd0d37 Mon Sep 17 00:00:00 2001 From: Deepak8717 Date: Thu, 19 May 2022 20:36:51 +0530 Subject: [PATCH 6/7] refactored the code --- src/meta/play-meta.js | 2 +- src/plays/registration-form/Readme.md | 2 +- .../registration-form/Registration-form.css | 59 ++- .../registration-form/RegistrationForm.jsx | 396 +++++++++--------- 4 files changed, 239 insertions(+), 220 deletions(-) diff --git a/src/meta/play-meta.js b/src/meta/play-meta.js index e9c9c9a704..6deb43a0a3 100644 --- a/src/meta/play-meta.js +++ b/src/meta/play-meta.js @@ -289,7 +289,7 @@ export const plays = [ { id: "pl-registration-form", name: "Registration-Form", - description: "Registration form with form validation without any liberary", + description: "Registration form with form validation without any library", component: () => { return ; }, diff --git a/src/plays/registration-form/Readme.md b/src/plays/registration-form/Readme.md index 9d51d09582..1aab4e546a 100644 --- a/src/plays/registration-form/Readme.md +++ b/src/plays/registration-form/Readme.md @@ -1,6 +1,6 @@ # registration-form -A Simple registration form with validation without any libery +A Simple registration form with validation without any library ## What will you learn ? diff --git a/src/plays/registration-form/Registration-form.css b/src/plays/registration-form/Registration-form.css index 17f0d7fd4c..488821e9c2 100644 --- a/src/plays/registration-form/Registration-form.css +++ b/src/plays/registration-form/Registration-form.css @@ -1,10 +1,13 @@ -.registration-form-container { +.registration-form-heading { + text-align: center; +} +.registration-form .container { width: 90%; margin: auto; max-width: 700px; text-align: center; } -.registration-form { +.registration-form .form-inside { max-width: 400px; margin: auto; text-align: left; @@ -13,19 +16,23 @@ box-shadow: 2px 2px 11px 1px #ccc, -2px -2px 16px 1px #ccc; border-radius: 10px; } -.user-input { +.registration-form .user-input { display: flex; flex-direction: column; margin: 10px auto; } -.user-input .registration-input { +.registration-form .user-label { + text-transform: capitalize; + margin: 2px 0; +} +.registration-form .user-input .registration-input { padding: 5px; } -.user-btn { +.registration-form .user-btn { text-align: center; margin: 25px auto 0; } -.user-btn .btn { +.registration-form .user-btn .btn { width: 100px; background: blueviolet; padding: 5px; @@ -35,12 +42,46 @@ font-weight: bold; border-radius: 5px; } -.hidden { +.registration-form .hidden { display: none; } -.error { +.registration-form .error { color: red; } -.input-error { +.registration-form .input-error { border: 1px solid red; } +.registration-form .entered-value-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +.registration-form .entered-value-container .success { + margin: 10px; + font-size: 1.5em; + color: rgb(43, 227, 43); +} +.registration-form .entered-value-container .entered-value-inner { + display: flex; + width: 80%; + max-width: 700px; + justify-content: center; +} +.entered-value-row { + width: 100%; + margin: 5px; + text-align: center; +} + +.registration-form .entered-value-row .heading { + font-weight: bold; + text-transform: capitalize; + font-size: 1em; +} +@media screen and (max-width: 768px) { + .registration-form .entered-value-container .entered-value-inner { + flex-direction: column; + width: 90%; + } +} diff --git a/src/plays/registration-form/RegistrationForm.jsx b/src/plays/registration-form/RegistrationForm.jsx index 43cf7d8a9b..7e26f67f17 100644 --- a/src/plays/registration-form/RegistrationForm.jsx +++ b/src/plays/registration-form/RegistrationForm.jsx @@ -2,7 +2,7 @@ import { getPlayById } from "meta/play-meta-util"; import PlayHeader from "common/playlists/PlayHeader"; import "./Registration-form.css"; -import { useEffect, useState } from "react"; +import { useState } from "react"; function RegistrationForm(props) { // Do not remove the below lines. @@ -11,243 +11,221 @@ function RegistrationForm(props) { const play = getPlayById(id); // Your Code Start below. - const [field, setField] = useState({ + + //for input values + const [values, setValues] = useState({ name: "", email: "", password: "", confirmPassword: "", - }); - const [error, setError] = useState({ - name: { - isValidated: false, - error: "", - }, - email: { - isValidated: false, - error: "", - }, - password: { - isValidated: false, - error: "", - }, - confirmPassword: { - isValidated: false, - error: "", + errors: { + name: "", + email: "", + password: "", + confirmPassword: "", }, }); - //function checks for all validation - const isValidated = (field) => { - if (field.name.trim() === "") { - setError((prevState) => { - prevState.name.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.email.trim() === "") { - setError((prevState) => { - prevState.email.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.password.trim() === "") { - setError((prevState) => { - prevState.password.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.confirmPassword.trim() === "") { - setError((prevState) => { - prevState.confirmPassword.error = "Field can't be empty"; - return { - ...prevState, - }; - }); - } - if (field.name.trim() !== "") { - setError((prevState) => { - prevState.name.isValidated = true; - prevState.name.error = ""; - return { + + //input values after submit + const [storedValues, setStoredValues] = useState({ + name: "", + email: "", + password: "", + confirmPassword: "", + }); + + //self explanatory + const validateEmail = (emailvalue) => { + if (emailvalue[0] === "email") { + const regx = /\S+@\S+\.\S+/; + if (!regx.test(emailvalue[1])) { + //set error and return false + setValues((prevState) => ({ ...prevState, - }; - }); - } - if (field.email.trim() !== "") { - if (isValidEmail(field)) { - setError((prevState) => { - prevState.email.isValidated = true; - prevState.email.error = ""; - return { - ...prevState, - }; - }); + errors: { + ...prevState.errors, + email: `your email is not correct`, + }, + })); + return false; } else { - setError((prevState) => { - prevState.email.isValidated = false; - prevState.email.error = "not valid email"; - return { - ...prevState, - }; - }); - } - } - if (field.password.trim() !== "") { - setError((prevState) => { - prevState.password.isValidated = true; - prevState.password.error = ""; - return { + //if email is correct clear error msg and return true + setValues((prevState) => ({ ...prevState, - }; - }); + errors: { + ...prevState.errors, + email: ``, + }, + })); + return true; + } } - if (field.confirmPassword.trim() !== "") { - if (field.password.trim() === field.confirmPassword.trim()) { - setError((prevState) => { - prevState.confirmPassword.isValidated = true; - prevState.confirmPassword.error = ""; - return { + //if other than email just return true + return true; + }; + + //self explanatory + const conmparePassword = (pass, confirmPass) => { + // (pass and confirmPass) arrays containing name, value pair eg. ["password","xyz"] and ["confirmpassword","xyz"] + if (pass[0] == "password") { + if (values.confirmPassword !== "") { + if (pass[1] !== confirmPass[1]) { + //values don't match set error, return false + setValues((prevState) => ({ ...prevState, - }; - }); - } else { - setError((prevState) => { - prevState.confirmPassword.isValidated = false; - prevState.confirmPassword.error = "passwords aren't matching"; - return { + errors: { + ...prevState.errors, + password: "Password doesn't match", + confirmPassword: "Password doesn't match", + }, + })); + return false; + } else { + //if matches remove error msgs, return true + setValues((prevState) => ({ ...prevState, - }; - }); + errors: { + ...prevState.errors, + password: "", + confirmPassword: "", + }, + })); + return true; + } } + //return true in any other condition + return true; } + //return true in any other condition + return true; }; - const isValidEmail = (field) => { - let regEmail = - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - return regEmail.test(field.email); + //final validation + const validate = (value) => { + //value is an array ex. ["name","deepak"] + if (value[1] === "") { + //if empty set error msg return false + setValues((prevState) => ({ + ...prevState, + errors: { + ...prevState.errors, + [value[0]]: `Please fill the ${value[0]}`, + }, + })); + return false; + } else { + //if not empty remove message return (validate email && compare password) + setValues((prevState) => ({ + ...prevState, + errors: { + ...prevState.errors, + [value[0]]: ``, + }, + })); + return ( + validateEmail(value) && + conmparePassword(value, Object.entries(values)[3]) + ); + } }; - const handleSubmit = (e) => { + const submitHandler = (e) => { e.preventDefault(); - isValidated(field); + let counter = 0; + Object.entries(values).map((value, i) => { + //validate each field, increase counter if validation passed. + if (validate(value)) { + counter = counter + 1; + } + }); - if ( - error.name.isValidated === true && - error.email.isValidated === true && - error.password.isValidated === true && - error.confirmPassword.isValidated === true - ) { - setField({ name: "", email: "", password: "", confirmPassword: "" }); + //if all fields are validated succsfully store the values in new object and clear the input values + if (counter === 5) { + setStoredValues({ + ...storedValues, + name: values.name, + email: values.email, + password: values.password, + confirmPassword: values.confirmPassword, + }); + setValues({ + name: "", + email: "", + password: "", + confirmPassword: "", + errors: { name: "", email: "", password: "", confirmPassword: "" }, + }); } }; - const handleOnChange = (e) => { - setField({ ...field, [e.target.name]: e.target.value }); + + const onChangeHandler = (e) => { + const { name, value } = e.target; + setValues({ ...values, [name]: value }); }; + return ( <>
{/* Your Code Starts Here */} -
-

Registration Form

-

A Simple registration form with validation without any libery

-
-
-
- - - - {error.name.error} - -
-
- - - - {error.email.error} - -
-
- - - - {error.password.error} - -
-
- - - - {error.confirmPassword.error} - -
-
- -
-
+

+ A Registration form validation without any library +

+
+
+ {Object.entries(values).map((value, index) => { + return ( +
+ + + +
+ ); + })} +
+ +
+
+
+ Form Submitted ! +
+ {Object.entries(storedValues).map((storedValue) => { + return ( +
+
{storedValue[0]}
+
{storedValue[1]}
+
+ ); + })} +
{/* Your Code Ends Here */} From 78430c5fb14d90856c14feebc14ea4b26e3f02ae Mon Sep 17 00:00:00 2001 From: Deepak8717 Date: Thu, 19 May 2022 21:43:05 +0530 Subject: [PATCH 7/7] removed the warnings --- src/meta/play-meta.js | 20 ------------------- .../registration-form/Registration-form.css | 5 ++++- .../registration-form/RegistrationForm.jsx | 10 +++++----- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/src/meta/play-meta.js b/src/meta/play-meta.js index c4887b720c..6deb43a0a3 100644 --- a/src/meta/play-meta.js +++ b/src/meta/play-meta.js @@ -149,26 +149,6 @@ export const plays = [ video: "", }, { -<<<<<<< HEAD -======= - id: "pl-keeper", - name: "Keeper", - description: - "Keeper is the clone of google keep where we can save and delete our notes", - component: () => { - return ; - }, - path: "/plays/keeper", - level: "Intermediate", - tags: "JSX,Hooks,ReactDOM", - github: "Shivam-Katare", - cover: - "https://res.cloudinary.com/dbjmy6wdu/image/upload/v1651678725/keepicon_jsn5bh.png", - blog: "", - video: "", - }, - { ->>>>>>> 3d5fef425937c15d366b23dc7d04f128088c65cc id: "pl-react-todo-app", name: "React Todo App", description: diff --git a/src/plays/registration-form/Registration-form.css b/src/plays/registration-form/Registration-form.css index 488821e9c2..e9030c30a7 100644 --- a/src/plays/registration-form/Registration-form.css +++ b/src/plays/registration-form/Registration-form.css @@ -58,7 +58,7 @@ align-items: center; } .registration-form .entered-value-container .success { - margin: 10px; + margin: 50px auto 10px; font-size: 1.5em; color: rgb(43, 227, 43); } @@ -84,4 +84,7 @@ flex-direction: column; width: 90%; } + .registration-form .entered-value-container .success { + margin: 10px auto; + } } diff --git a/src/plays/registration-form/RegistrationForm.jsx b/src/plays/registration-form/RegistrationForm.jsx index 7e26f67f17..d55cec4f33 100644 --- a/src/plays/registration-form/RegistrationForm.jsx +++ b/src/plays/registration-form/RegistrationForm.jsx @@ -67,7 +67,7 @@ function RegistrationForm(props) { //self explanatory const conmparePassword = (pass, confirmPass) => { // (pass and confirmPass) arrays containing name, value pair eg. ["password","xyz"] and ["confirmpassword","xyz"] - if (pass[0] == "password") { + if (pass[0] === "password") { if (values.confirmPassword !== "") { if (pass[1] !== confirmPass[1]) { //values don't match set error, return false @@ -132,7 +132,7 @@ function RegistrationForm(props) { const submitHandler = (e) => { e.preventDefault(); let counter = 0; - Object.entries(values).map((value, i) => { + Object.entries(values).forEach((value, i) => { //validate each field, increase counter if validation passed. if (validate(value)) { counter = counter + 1; @@ -176,7 +176,7 @@ function RegistrationForm(props) {
{Object.entries(values).map((value, index) => { return ( -
+