Table of contents
The challenge
The challenge is part of frontend challenge where you have to build out a age calculator app and get it looking as close to the design as possible.
Users should be able to:
View an age in years, months, and days after submitting a valid date through the form
Receive validation errors if:
Any field is empty when the form is submitted
The day number is not between 1-31
The month number is not between 1-12
The date is in the future
View the optimal layout for the interface depending on their device's screen size
See hover and focus states for all interactive elements on the page.
HTML Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;1,900&display=swap" rel="stylesheet">
<script src="index.js"></script>
<title>Document</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="div-main">
<div class="div-date" id="div-date">
<div class="day">
<p id="text-day">Day</p>
<input type="text" class="input-date" id="input-date" placeholder="DD" >
<p id="error-date" class="error-text"></p>
</div>
<div class="day">
<p id="text-mon">Month</p>
<input type="text" class="input-date" id="input-mon" placeholder="MM">
<p id="error-mon" class="error-text"></p>
</div>
<div class="day">
<p id="text-year">Year</p>
<input type="text" class="input-date" id="input-year" placeholder="YYYY" >
<p id="error-year" class="error-text"></p>
</div>
</div><br/>
<div class="line">
</div>
<div class="circle">
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="44" style="margin-left: 7%;margin-top: 5%;" viewBox="0 0 46 44" onclick="cal()"><g fill="none" stroke="#FFF" stroke-width="2"><path d="M1 22.019C8.333 21.686 23 25.616 23 44M23 44V0M45 22.019C37.667 21.686 23 25.616 23 44"/></g></svg>
</div>
<div class="cal">
<p><span id="year">- - </span> years<br/>
<span id="month">- - </span> Months<br/>
<span id="date">- - </span> Days</p>
</div>
</div>
</body>
</html>
CSS CODE
body{
background-color: hsl(0, 0%, 86%);
}
.div-main{
background-color: white;
width: 45%;
margin-left:25%;
margin-top: 5%;
border-radius: 15px;
border-bottom-right-radius:160px;
}
.div-date{
display: flex;
margin-top: 16%;
width: 100%;
}
.div-date p{
font-size: 14px;
text-transform: uppercase;
color: rgb(127, 125, 125);
font-family: 'Poppins', sans-serif;
font-weight: bolder;
}
.day{
width: 20%;
gap:-6px;
margin-left: 4%;
margin-right: 2px;
margin-top: 5%;
}
.input-date{
width: 60%;
height: 2rem;
border: 2px solid rgb(233, 233, 233);
border-radius: 5px;
margin-top: -5%;
font-weight: bold;
font-size: 20px;
font-family: 'Poppins', sans-serif;
cursor: pointer;
}
.line{
border: 1px solid rgb(239, 239, 239);
width:80%;
margin-left: 4%;
}
.circle{
background-color: rgb(128, 61, 253);
width:60px;
height: 60px;
border-radius: 50px;
margin-left: 85%;
margin-top: -3%;
cursor: pointer;
}
.arrow{
margin-left: 5%;
color: black;
}
.cal{
width:80%;
margin-top: -10%;
margin-left: 4%;
margin-bottom: 10px;
}
.cal p{
font-size: 55px;
font-style: italic;
margin-left: 10%;
font-family: 'Poppins', sans-serif;
text-transform: lowercase;
font-weight: 900;
}
p span{
color:rgb(128, 61, 253);
}
.error{
border-color: hsl(0, 100%, 67%);
}
.error-text{
color:red
}
@media screen and (min-width: 280px) and (max-width:760px){
.div-main{
width: 95%;
margin-left:2%;
border-bottom-right-radius:100px;
}
.day{
width: 26%;
}
.cal p{
font-size: 40px;
}
.cal{
width:80%;
margin-top: -10%;
margin-left: 4%;
margin-bottom: 10px;
}
p span{
color:rgb(128, 61, 253)
}
.circle{
margin-left: 35%;
margin-top: -8%;
}
.line{
margin-top: 4%;
}
}
@media screen and (min-width: 760px) and (max-width:1000px){
.div-main{
width: 95%;
margin-left:2%;
}
}
JAVASCRIPT CODE
Step 1 - Getting the Present date using JS date module.
const d = new Date()
let yearCurr=d.getFullYear();
let monCurr=d.getMonth()+1
let dateCurr=d.getDate()
Explanation -
Date objects are created with
new Date()
by using
getFullYear()
we can get the present year.by using
getMonth
we can get the month ( but month starts with 0 we add +1 ).by using
getDate()
we can get the date .
Step 2 - Validation
let checkDate=(userDate=='' || userDate==0|| userDate>31)
let checkMon=(userMonth=='' || userMonth==0||userMonth>12)
let checkYear=(userYear==''||userYear>yearCurr)
let checkTotal=checkDate || checkMon || checkYear
Explanation -
checks if the user data is valid (between ranges ) and not null .
adding CSS for validation using DOM elements
if(checkTotal){ if(userDate==''){ document.getElementById('input-date').classList.add('error') document.getElementById('error-date').innerText='The field is required' document.getElementById('error-date').style.color='hsl(0, 100%, 67%)' document.getElementById('text-day').style.color='hsl(0, 100%, 67%)' }else if(userDate==0 || userDate>31){ document.getElementById('input-date').classList.add('error') document.getElementById('error-date').innerText='Must be a valid day' document.getElementById('error-date').style.color='hsl(0, 100%, 67%)' document.getElementById('text-day').style.color='hsl(0, 100%, 67%)' } if(userMonth==''){ document.getElementById('input-mon').classList.add('error') document.getElementById('error-mon').innerText='The field is required' document.getElementById('error-mon').style.color='hsl(0, 100%, 67%)' document.getElementById('text-mon').style.color='hsl(0, 100%, 67%)' }else if(userMonth==0 || userMonth>12){ document.getElementById('input-mon').classList.add('error') document.getElementById('error-mon').innerText='Must be a valid month' document.getElementById('error-mon').style.color='hsl(0, 100%, 67%)' document.getElementById('text-mon').style.color='hsl(0, 100%, 67%)' } if(userYear==''){ document.getElementById('input-year').classList.add('error') document.getElementById('error-year').innerText='The field is required' document.getElementById('error-year').style.color='hsl(0, 100%, 67%)' document.getElementById('text-year').style.color='hsl(0, 100%, 67%)' }else if(userYear==0 || userYear>yearCurr){ document.getElementById('input-year').classList.add('error') document.getElementById('error-year').innerText='Must be in the past' document.getElementById('error-year').style.color='hsl(0, 100%, 67%)' document.getElementById('text-year').style.color='hsl(0, 100%, 67%)' }
Step 3 - Logic
Step 1: First, calculate the number of years by subtracting the birth year from the current year. ( Current Year-Birth Year )
totalYear=yearCurr-userYear
Step 2: Second calculate the number of years by subtracting birth month from the current year. If (current Month<birth month) then subtract the full years by 1 and add 12 to current months .
if(monCurr<userMonth){ totalYear-- monCurr+=12 monTotal=monCurr-userMonth }else{ monTotal=monCurr-userMonth }
Step 3: Last calculate the number of days by subtracting birth date from current date. if(current date<birth date) then subtract the month by 1 and adding number of days the previous month of current month has .
if(dateCurr<userDate){ monTotal-- let previousMonth=monCurr-1 if(previousMonth===1||previousMonth===3||previousMonth===5||previousMonth===7||previousMonth===8||previousMonth===10|| previousMonth===12){ dateTotal=date+31 }else if(previousMonth===2){ dateTotal=date+28 }else{ dateTotal=date+30 } }else{ dateTotal=dateCurr-userDate }
const d = new Date()
let yearCurr=d.getFullYear();
let monCurr=d.getMonth()+1
let dateCurr=d.getDate()
let yearText
let totalYear
let monTotal
let monText
let dateTotal
let dateText
let userDate
function cal(){
let userDate=document.getElementById('input-date').value
let userMonth=document.getElementById('input-mon').value
let userYear =document.getElementById('input-year').value
yearText=document.getElementById('year')
monText=document.getElementById('month')
dateText=document.getElementById('date')
//validation
let checkDate=(userDate=='' || userDate==0|| userDate>31)
let checkMon=(userMonth=='' || userMonth==0||userMonth>12)
let checkYear=(userYear==''||userYear>yearCurr)
let checkTotal=checkDate || checkMon || checkYear
if(checkTotal){
if(userDate==''){
document.getElementById('input-date').classList.add('error')
document.getElementById('error-date').innerText='The field is required'
document.getElementById('error-date').style.color='hsl(0, 100%, 67%)'
document.getElementById('text-day').style.color='hsl(0, 100%, 67%)'
}else if(userDate==0 || userDate>31){
document.getElementById('input-date').classList.add('error')
document.getElementById('error-date').innerText='Must be a valid day'
document.getElementById('error-date').style.color='hsl(0, 100%, 67%)'
document.getElementById('text-day').style.color='hsl(0, 100%, 67%)'
}
if(userMonth==''){
document.getElementById('input-mon').classList.add('error')
document.getElementById('error-mon').innerText='The field is required'
document.getElementById('error-mon').style.color='hsl(0, 100%, 67%)'
document.getElementById('text-mon').style.color='hsl(0, 100%, 67%)'
}else if(userMonth==0 || userMonth>12){
document.getElementById('input-mon').classList.add('error')
document.getElementById('error-mon').innerText='Must be a valid month'
document.getElementById('error-mon').style.color='hsl(0, 100%, 67%)'
document.getElementById('text-mon').style.color='hsl(0, 100%, 67%)'
}
if(userYear==''){
document.getElementById('input-year').classList.add('error')
document.getElementById('error-year').innerText='The field is required'
document.getElementById('error-year').style.color='hsl(0, 100%, 67%)'
document.getElementById('text-year').style.color='hsl(0, 100%, 67%)'
}else if(userYear==0 || userYear>yearCurr){
document.getElementById('input-year').classList.add('error')
document.getElementById('error-year').innerText='Must be in the past'
document.getElementById('error-year').style.color='hsl(0, 100%, 67%)'
document.getElementById('text-year').style.color='hsl(0, 100%, 67%)'
}
}else{
document.getElementById('input-date').classList.remove('error')
document.getElementById('input-mon').classList.remove('error')
document.getElementById('input-year').classList.remove('error')
document.getElementById('error-year').innerText=''
document.getElementById('error-mon').innerText=''
document.getElementById('error-date').innerText=''
document.getElementById('text-year').style.color='rgb(127, 125, 125)'
document.getElementById('text-mon').style.color='rgb(127, 125, 125)'
document.getElementById('text-day').style.color='rgb(127, 125, 125)'
userDate=parseInt(userDate)
userMonth=parseInt(userMonth)
userYear=parseInt(userYear)
//step1
totalYear=yearCurr-userYear
//step2
if(monCurr<userMonth){
totalYear--
monCurr+=12
monTotal=monCurr-userMonth
}else{
monTotal=monCurr-userMonth
}
//step 3
if(dateCurr<userDate){
monTotal--
let previousMonth=monCurr-1
if(previousMonth===1||previousMonth===3||previousMonth===5||previousMonth===7||previousMonth===8||previousMonth===10||
previousMonth===12){
dateTotal=date+31
}else if(previousMonth===2){
dateTotal=date+28
}else{
dateTotal=date+30
}
}else{
dateTotal=dateCurr-userDate
}
yearText.innerText=totalYear
monText.innerText=monTotal
dateText.innerText=dateTotal
}
date=0
document.getElementById('input-date').value=''
document.getElementById('input-mon').value=''
document.getElementById('input-year').value=''
}