Skip to content

Instantly share code, notes, and snippets.

@sharbel93
Last active May 15, 2020 06:26
Show Gist options
  • Save sharbel93/146df2bd1072eacf34773b2ac1491fb7 to your computer and use it in GitHub Desktop.
Save sharbel93/146df2bd1072eacf34773b2ac1491fb7 to your computer and use it in GitHub Desktop.
Gradr
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Mini App</title>
<style>
body {
margin: 0;
padding: 1em;
background-color: white;
}
[data-cart-info] span{
display: inline-block;
vertical-align: middle;
}
.material-icons{
font-size: 150px;
}
[data-cart-info],
[data-credit-card] {
transform: scale(0.78);
margin-left: -3.4em;
}
[data-credit-card]{
width: 435px;
min-height: 240px;
border-radius: 10px;
background-color: #5d6874;
}
[data-card-type]{
display: block;
width:120px;
height: 60px;
}
[data-cc-digits]{
margin-top: 2em;
}
[data-cc-digits] input{
color:white;
font-size: 2em;
line-height: 2em;
border-style: none;
background: none;
margin-right: 0.5em;
}
[data-cc-info]{
margin-top: 1em;
}
[data-cc-info] input{
color:white;
font-size: 1.2em;
border-style:none;
background:none;
}
[data-cc-info] input:nth-child(2){
padding-right: 10px;
float: right;
}
[data-pay-btn]{
position:fixed;
width: 90%;
border: 1px solid;
bottom: 20px;
}
[data-cc-info] input:focus,
[data-cc-digits] input:focus {
outline: none;
}
.mdc-card__primary-action,
.mdc-card__primary-action:hover {
cursor: auto;
padding: 20px;
min-height: inherit;
}
[data-credit-card] [data-card-type] {
transition: width 1.5s;
margin-left: calc(100% - 130px);
}
[data-credit-card].is-visa {
background: linear-gradient(135deg, #622774 0%, #c53364 100%);
}
[data-credit-card].is-mastercard {
background: linear-gradient(135deg, #65799b 0%, #5e2563 100%);
}
.is-visa [data-card-type],
.is-mastercard [data-card-type] {
width: auto;
}
input.is-invalid,
.is-invalid input {
text-decoration: line-through;
}
::placeholder {
color: #fff;
}
</style>
</head>
<body>
<div data-cart-info>
<h4 class="mdc-typography--headline4">
<span class="material-icons">shopping_cart</span>
<span data-bill></span>
</h4>
</div>
<div data-credit-card class="mdc-card mdc-card--outlined">
<div class="mdc-card__primary-action">
<img alt="image" src="http://placehold.it/120x60.png?text=Card" data-card-type>
<div data-cc-digits>
<input type="text" maxlength="4" size="4" placeholder="----">
<input type="text" maxlength="4" size="4" placeholder="----">
<input type="text" maxlength="4" size="4" placeholder="----">
<input type="text" maxlength="4" size="4" placeholder="----">
</div>
<div data-cc-info>
<input type="text" size="20" placeholder="Name Surname">
<input type="text" size="6" placeholder="MM/YY">
</div>
</div>
</div>
<button class="mdc-button" data-pay-btn>Pay & Checkout Now</button>
<script>
const supportedCards = {
visa, mastercard
};
const countries = [
{
code: "US",
currency: "USD",
country: 'United States'
},
{
code: "NG",
currency: "NGN",
country: 'Nigeria'
},
{
code: 'KE',
currency: 'KES',
country: 'Kenya'
},
{
code: 'UG',
currency: 'UGX',
country: 'Uganda'
},
{
code: 'RW',
currency: 'RWF',
country: 'Rwanda'
},
{
code: 'TZ',
currency: 'TZS',
country: 'Tanzania'
},
{
code: 'ZA',
currency: 'ZAR',
country: 'South Africa'
},
{
code: 'CM',
currency: 'XAF',
country: 'Cameroon'
},
{
code: 'GH',
currency: 'GHS',
country: 'Ghana'
}
];
const appState = {};
const formatAsMoney = (amount, buyerCountry) => {
const _money = countries.find(val => val.country === buyerCountry);
if(_money){
return amount.toLocaleString(
'en-'+_money.code,
{style:"currency",
currency: _money.currency});
} else {
return amount.toLocaleString('en-US',
{
style: "currency",
currency: "USD"
});
}
};
const flagIfInvalid = (field, isValid) => {
if(isValid){
field.classList.remove('is-invalid');
}else {
field.classList.add('is-invalid');
}
};
const expiryDateFormatIsValid = (target) => {
return /^\d{2}\/\d{2}$/.test(target.value.trim());
// if(DateTime.ParseExact('MM/YY', target)){
// return true;
// } else {
// return false;
// }
};
const detectCardType = ({target}) => {
const _visa = target.value.startsWith(4);
const _master = target.value.startsWith(5);
const card = document.querySelector('[data-credit-card]');
const cardType = document.querySelector('[data-card-type]');
if(_visa){
card.classList.add('is-visa');
card.classList.remove('is-mastercard');
cardType.src = supportedCards.visa;
return 'is-visa';
}else if(_master){
card.classList.remove('is-visa');
card.classList.add('is-mastercard');
cardType.src = supportedCards.mastercard;
return 'is-mastercard';
}
};
const validateCardExpiryDate = ({target}) => {
// const value = target;
// const validate = expiryDateFormatIsValid(value);
// const today = new Date();
// const ds = value.split('/');
// const expiryDate = new Date(Number(ds[1]), (Number(ds[0]) - 1));
// if(validate) {
// if(expiryDate > today){
// flagIfInvalid(target, true);
// }
// return true;
if(expiryDateFormatIsValid(target)){
const [month, year] = target.value.split('/');
const expiryDate = new Date(`20${year}/${month}`);
const now = new Date();
if(expiryDate > now){
flagIfInvalid(target, true);
return true;
} else {
flagIfInvalid(target, false);
return false;
}
}else {
flagIfInvalid(target, false);
return false;
}
}
const validateCardHolderName = ({target}) => {
const value = target.value;
const result = /^[a-zA-Z]{3,}\s[a-zA-Z]{3,}$/.test(value.trim());
if(result){
flagIfInvalid(target,true);
return true;
}else {
flagIfInvalid(target, false);
return false;
}
// return result && flagIfInvalid(target, result);
};
const validateWithLuhn = (digits) => {
const arr = [];
for(var i = digits.length-1; i >=0; i--){
if((digits.length - i) % 2 === 0 ){
let x = digits[i] * 2;
if(x > 9){
x -= 9;
arr.push(x);
} else {
arr.push(x);
}
} else {
arr.push(digits[i]);
}
}
const sum = arr.reduce((prev,cur,index) => prev + cur, 0);
if(sum%10 === 0){
return true;
} else {
return false;
}
};
const validateCardNumber = () => {
//document.querySelector("[data-cc-digits]").classList.remove("is-invalid");
const v1 = document.querySelector("[data-cc-digits] input:nth-child(1)").value;
const v2 = document.querySelector("[data-cc-digits] input:nth-child(2)").value;
const v3 = document.querySelector("[data-cc-digits] input:nth-child(3)").value;
const v4 = document.querySelector("[data-cc-digits] input:nth-child(4)").value;
const getStr = (v1+v2+v3+v4);
let creditStringArray = [];
for(let i=0; i < getStr.length; i++){
creditStringArray.push(parseInt(getStr.charAt(i)));
}
const isValid = validateWithLuhn(creditStringArray);
if(!isValid){
document.querySelector("[data-cc-digits]").classList.add("is-invalid");
} else {
document.querySelector("[data-cc-digits]").classList.remove("is-invalid");
}
return isValid;
};
const uiCanInteract = () => {
const var1 = document.querySelector('[data-cc-digits] input:nth-child(1)');
var1.addEventListener('blur', detectCardType);
var1.focus();
const var2 = document.querySelector('[data-cc-info] input:nth-child(1)');
var2.addEventListener('blur', validateCardHolderName);
const var3 = document.querySelector('[data-cc-info] input:nth-child(2)');
var3.addEventListener('blur', validateCardExpiryDate);
const var4 = document.querySelector('[data-pay-btn]');
var4.addEventListener('click', validateCardNumber);
};
const displayCartTotal = ({results}) => {
let [data] = results;
let { itemsInCart, buyerCountry } = data;
appState.items = itemsInCart;
appState.country = buyerCountry;
appState.bill = itemsInCart.reduce((a,b) => (a["price"] * a["qty"]) + (b["price"] * b["qty"]));
appState.billFormatted = formatAsMoney(appState.bill, appState.country);
document.querySelector('[data-bill]').textContent = appState.billFormatted;
uiCanInteract();
};
const fetchBill = () => {
const api = "https://randomapi.com/api/006b08a801d82d0c9824dcfdfdfa3b3c";
fetch(api)
.then(response => response.json())
.then(data => {
displayCartTotal(data);
}).catch(err => {
console.log(err);
});
};
const startApp = () => {
fetchBill();
}
startApp();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment