├── design ├── active-states.jpg ├── mobile-design.jpg ├── desktop-design.jpg ├── desktop-preview.jpg ├── complete-state-mobile.jpg └── complete-state-desktop.jpg ├── images ├── bg-card-back.png ├── bg-card-front.png ├── favicon-32x32.png ├── bg-main-desktop.png ├── bg-main-mobile.png ├── card-logo.svg └── icon-complete.svg ├── .gitignore ├── style-guide.md ├── LICENSE ├── script.js ├── index.html ├── style.css └── README.md /design/active-states.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/design/active-states.jpg -------------------------------------------------------------------------------- /design/mobile-design.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/design/mobile-design.jpg -------------------------------------------------------------------------------- /images/bg-card-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/images/bg-card-back.png -------------------------------------------------------------------------------- /images/bg-card-front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/images/bg-card-front.png -------------------------------------------------------------------------------- /images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/images/favicon-32x32.png -------------------------------------------------------------------------------- /design/desktop-design.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/design/desktop-design.jpg -------------------------------------------------------------------------------- /design/desktop-preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/design/desktop-preview.jpg -------------------------------------------------------------------------------- /images/bg-main-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/images/bg-main-desktop.png -------------------------------------------------------------------------------- /images/bg-main-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/images/bg-main-mobile.png -------------------------------------------------------------------------------- /design/complete-state-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/design/complete-state-mobile.jpg -------------------------------------------------------------------------------- /design/complete-state-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/all-my-frontend-mini-projects/interactive-card-form_frontend_project/HEAD/design/complete-state-desktop.jpg -------------------------------------------------------------------------------- /images/card-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/icon-complete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Avoid accidental upload of the Sketch and Figma design files 2 | ##################################################### 3 | ## Please do not remove lines 5 and 6 - thanks! 🙂 ## 4 | ##################################################### 5 | *.sketch 6 | *.fig 7 | 8 | # Avoid accidental XD upload if you convert the design file 9 | ############################################### 10 | ## Please do not remove line 12 - thanks! 🙂 ## 11 | ############################################### 12 | *.xd 13 | 14 | # Avoid your project being littered with annoying .DS_Store files! 15 | .DS_Store 16 | .prettierignore -------------------------------------------------------------------------------- /style-guide.md: -------------------------------------------------------------------------------- 1 | # Front-end Style Guide 2 | 3 | ## Layout 4 | 5 | The designs were created to the following widths: 6 | 7 | - Mobile: 375px 8 | - Desktop: 1440px 9 | 10 | ## Colors 11 | 12 | ### Primary 13 | 14 | - Linear gradient (active input border): hsl(249, 99%, 64%) to hsl(278, 94%, 30%) 15 | - Red (input errors): hsl(0, 100%, 66%) 16 | 17 | ### Neutral 18 | 19 | - White: hsl(0, 0%, 100%) 20 | - Light grayish violet: hsl(270, 3%, 87%) 21 | - Dark grayish violet: hsl(279, 6%, 55%) 22 | - Very dark violet: hsl(278, 68%, 11%) 23 | 24 | ## Typography 25 | 26 | ### Body Copy 27 | 28 | - Font size: 18px 29 | 30 | ### Font 31 | 32 | - Family: [Space Grotesk](https://fonts.google.com/specimen/Space+Grotesk) 33 | - Weights: 500 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, Sarthak Sachdev 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | const cardNumberText = document.getElementById("card-number"); 2 | const holderNameText = document.getElementById("holder-name-text"); 3 | const expirationDate = document.getElementById("exp-date"); 4 | const cvcText = document.getElementById("cvc-text"); 5 | const cardForm = document.getElementById("card-form"); 6 | const holderNameInput = document.getElementById("holder-name-input"); 7 | const holderError = document.getElementById("holder-error"); 8 | const holderCardNumberInput = document.getElementById("card-number-input"); 9 | const cardNumberError = document.getElementById("number-error"); 10 | const monthInput = document.getElementById("month"); 11 | const yearInput = document.getElementById("year"); 12 | const dateError = document.getElementById("date-error"); 13 | const cvcInput = document.getElementById("cvc"); 14 | const cvcError = document.getElementById("cvc-error"); 15 | const successDialog = document.getElementById("success-dialog"); 16 | const continueBtn = document.getElementById("continue-btn"); 17 | 18 | const nameValidation = () => { 19 | let isNameValid = true; 20 | let isNumberValid = true; 21 | let isDateValid = true; 22 | let isCvcValid = true; 23 | let isFormValid; 24 | 25 | const holderName = holderNameInput.value; 26 | const cvc = cvcInput.value; 27 | const holderNumber = holderCardNumberInput.value; 28 | 29 | const nameRegex = /[0-9]+/i; 30 | const numberRegex = /[0-9]+/i; 31 | 32 | if (nameRegex.test(holderName)) { 33 | holderError.innerText = "Wrong format, text only"; 34 | isNameValid = false; 35 | } if (!holderName) { 36 | holderError.innerText = "Can't be blank"; 37 | isNameValid = false; 38 | } 39 | 40 | 41 | if (!numberRegex.test(holderNumber)) { 42 | cardNumberError.innerText = "Wrong format, numbers only"; 43 | isNumberValid = false; 44 | } 45 | if (!holderNumber) { 46 | cardNumberError.innerText = "Can't be blank"; 47 | isNumberValid = false; 48 | } 49 | 50 | if (!numberRegex.test(month.value) || !numberRegex.test(year.value)) { 51 | dateError.innerText = "Wrong format, numbers only"; 52 | } 53 | if (!month.value || !year.value) { 54 | dateError.innerText = "Can't be blank"; 55 | isDateValid = false; 56 | } 57 | 58 | if (!cvc) { 59 | cvcError.innerText = "Can't be blank"; 60 | isCvcValid = false; 61 | } 62 | 63 | if (isCvcValid && isDateValid && isNameValid && isNumberValid) { 64 | isFormValid = true; 65 | } else { 66 | isFormValid = false; 67 | } 68 | return isFormValid; 69 | } 70 | 71 | cardForm.addEventListener("submit", (e) => { 72 | e.preventDefault(); 73 | if (nameValidation()) { 74 | holderNameText.innerText = holderNameInput.value; 75 | expirationDate.innerText = `${monthInput.value}/${yearInput.value}`; 76 | cvcText.innerText = cvcInput.value; 77 | const holderCardNumber = holderCardNumberInput.value.replace(" ", "").match(/.{1,4}/g).join(" "); 78 | cardNumberText.innerText = holderCardNumber; 79 | cardForm.classList.add("hidden"); 80 | successDialog.classList.remove("hidden"); 81 | } else { 82 | alert("Please fill the form properly."); 83 | return; 84 | } 85 | }) 86 | 87 | continueBtn.addEventListener("click", () => { 88 | successDialog.classList.add("hidden"); 89 | cardForm.classList.remove("hidden"); 90 | }) 91 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 13 | 14 |