Created
August 8, 2019 10:20
-
-
Save winni4eva/175e771e5f4afeffed619b178c88f174 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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: white; | |
} | |
[data-cart-info], | |
[data-credit-card] { | |
transform: scale(0.78); | |
margin-left: -3.4em; | |
} | |
[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; | |
} | |
/* Add Your CSS From Here */ | |
div[data-cart-info] span { | |
display: inline-block; | |
vertical-align: middle; | |
} | |
div[data-cart-info] h3 span.material-icons { | |
font-size: 150px; | |
} | |
div[data-credit-card] { | |
width: 435px; | |
min-height: 240px; | |
border-radius: 10px; | |
background-color: #5d6874; | |
} | |
img[data-card-type] { | |
display: block; | |
width: 120px; | |
height: 60px; | |
} | |
div[data-cc-digits] { | |
margin-top: 2em; | |
} | |
div[data-cc-digits] input { | |
color: white; | |
font-size: 2em; | |
line-height: 2em; | |
border: none; | |
background: transparent; | |
margin-right: 0.5em; | |
} | |
div[data-cc-info] { | |
margin-top: 1em; | |
} | |
div[data-cc-info] input { | |
color: white; | |
font-size: 1.2em; | |
border: none; | |
background: none; | |
} | |
div[data-cc-info] input:nth-child(2) { | |
padding-right: 10px; | |
float: right; | |
} | |
button[data-pay-btn] { | |
position: fixed; | |
width: 90%; | |
border: 1px solid; | |
bottom: 20px; | |
} | |
</style> | |
</head> | |
<body> | |
<!-- your HTML goes here --> | |
<div data-cart-info> | |
<h3 class="mdc-typography--headline4"> | |
<span class="material-icons"> | |
shopping_cart | |
</span> | |
<span data-bill></span> | |
</h3> | |
</div> | |
<div data-credit-card class="mdc-card mdc-card--outlined"> | |
<div class="mdc-card__primary-action"> | |
<img data-card-type src="https://placehold.it/120x60.png?text=card"> | |
<div data-cc-digits> | |
<input type="text" size="4" placeholder="----"> | |
<input type="text" size="4" placeholder="----"> | |
<input type="text" size="4" placeholder="----"> | |
<input type="text" 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 Now</button> | |
<script> | |
const supportedCards = { | |
visa, mastercard | |
}; | |
const countries = [ | |
{ | |
code: "US", | |
currency: "USD", | |
currencyName: '', | |
country: 'United States' | |
}, | |
{ | |
code: "NG", | |
currency: "NGN", | |
currencyName: '', | |
country: 'Nigeria' | |
}, | |
{ | |
code: 'KE', | |
currency: 'KES', | |
currencyName: '', | |
country: 'Kenya' | |
}, | |
{ | |
code: 'UG', | |
currency: 'UGX', | |
currencyName: '', | |
country: 'Uganda' | |
}, | |
{ | |
code: 'RW', | |
currency: 'RWF', | |
currencyName: '', | |
country: 'Rwanda' | |
}, | |
{ | |
code: 'TZ', | |
currency: 'TZS', | |
currencyName: '', | |
country: 'Tanzania' | |
}, | |
{ | |
code: 'ZA', | |
currency: 'ZAR', | |
currencyName: '', | |
country: 'South Africa' | |
}, | |
{ | |
code: 'CM', | |
currency: 'XAF', | |
currencyName: '', | |
country: 'Cameroon' | |
}, | |
{ | |
code: 'GH', | |
currency: 'GHS', | |
currencyName: '', | |
country: 'Ghana' | |
} | |
]; | |
const billHype = () => { | |
const billDisplay = document.querySelector('.mdc-typography--headline4'); | |
if (!billDisplay) return; | |
billDisplay.addEventListener('click', () => { | |
const billSpan = document.querySelector("[data-bill]"); | |
if (billSpan && | |
appState.bill && | |
appState.billFormatted && | |
appState.billFormatted === billSpan.textContent) { | |
window.speechSynthesis.speak( | |
new SpeechSynthesisUtterance(appState.billFormatted) | |
); | |
} | |
}); | |
}; | |
const appState = {}; | |
const formatAsMoney = (amount, buyerCountry) => { | |
const selectedCountry = countries.filter(country => { | |
return country.country === buyerCountry; | |
}); | |
const selectedCountryCode = selectedCountry[0].code || countries[0].code; | |
const selectedCountryCurrency = selectedCountry[0].currency || countries[0].currency; | |
return amount.toLocaleString( | |
`en-${selectedCountryCode}`, | |
{style:"currency", currency: selectedCountryCurrency} | |
); | |
}; | |
const flagIfInvalid = (field, isValid) => { | |
if (isValid) | |
field.classList.remove("is-invalid"); | |
field.classList.add("is-invalid"); | |
} | |
const expiryDateFormatIsValid = (field) => { | |
const regEx = new RegExp(/^(0?[1-9]|1[012])[//]\d{2}$/); | |
return regEx.test(field); | |
} | |
const detectCardType = first4Digits => {}; | |
const validateCardExpiryDate = () => { | |
const dateInput = document.querySelector("div[data-cc-info] input:nth-child(2)"); | |
if (expiryDateFormatIsValid(dateInput.value)) { | |
const dateArr = dateInput.value.split("/"), | |
cardMonth = dateArr[0], | |
cardYear = `20${dateArr[1]}`, | |
expiry = new Date(`${cardYear}-${cardMonth}-01`); | |
if(expiry > new Date()) { | |
flagIfInvalid(dateInput, true); | |
return true; | |
} | |
} | |
flagIfInvalid(dateInput, false); | |
return false; | |
}; | |
const validateCardHolderName = () => { | |
const cardNameInput = document.querySelector('div[data-cc-info] input:nth-child(1)'); | |
const names = cardNameInput.value.split(" "); | |
if (names.length !== 2 || names[0].length < 3 || names[1].length < 3) { | |
flagIfInvalid(cardNameInput, false); | |
return false; | |
} | |
flagIfInvalid(cardNameInput, true); | |
return true; | |
}; | |
const validateCardNumber = () => {}; | |
const validatePayment = () => { | |
validateCardNumber(); | |
validateCardHolderName(); | |
validateCardExpiryDate(); | |
}; | |
const acceptCardNumbers = (event, fieldIndex) => {}; | |
const smartInput = (event, fieldIndex, fields) => { | |
const allowedkeysCodes = [9,8,16,46,37,38,39,40]; | |
if((fieldIndex >= 0 && fieldIndex < 4) || fieldIndex === 5) { | |
if(~allowedkeysCodes.indexOf(event.keyCode) || !isNaN(event.key)) { | |
if(fieldIndex !== 5 && fields[fieldIndex].value.length === 4) { | |
console.log(fields[fieldIndex++]); | |
fields[fieldIndex++].focus(); | |
} | |
return true; | |
} | |
event.preventDefault(); | |
return false; | |
} | |
if(fieldIndex === 4) { | |
if(~allowedkeysCodes.indexOf(event.keyCode) || isNaN(event.key)) { | |
return true; | |
} | |
event.preventDefault(); | |
return false; | |
} | |
}; | |
const smartCursor = (event, fieldIndex, fields) => { | |
// | |
}; | |
const enableSmartTyping = () => { | |
const fields = document.querySelectorAll("input"); | |
[].forEach.call(fields, (field, index) => { | |
//field.addEventListener("keyup", (event) => { | |
//smartInput(event, index, fields); | |
//}); | |
field.addEventListener("keydown", (event) => { | |
return smartInput(event, index, fields); | |
}); | |
}); | |
}; | |
const uiCanInteract = () => { | |
document.querySelector("div[data-cc-digits] input:nth-child(1)").focus(); | |
document.querySelector("button[data-pay-btn]").addEventListener("click", validatePayment); | |
billHype(); | |
enableSmartTyping(); | |
}; | |
const displayCartTotal = ({results}) => { | |
const [data] = results; | |
const {itemsInCart, buyerCountry} = data; | |
appState.items = itemsInCart; | |
appState.country = buyerCountry; | |
const initialValue = 0; | |
appState.bill = itemsInCart.reduce( | |
(totalPrice, cartItem) => { | |
return totalPrice + (cartItem.price * cartItem.qty) | |
}, | |
initialValue | |
); | |
appState.billFormatted = formatAsMoney(appState.bill, appState.country); | |
document.querySelector("[data-bill]").textContent = appState.billFormatted; | |
appState.cardDigits = []; | |
uiCanInteract(); | |
}; | |
const fetchBill = () => { | |
const apiHost = 'https://randomapi.com/api'; | |
const apiKey = '006b08a801d82d0c9824dcfdfdfa3b3c'; | |
const apiEndpoint = `${apiHost}/${apiKey}`; | |
fetch(apiEndpoint) | |
.then(response => response.json()) | |
.then(displayCartTotal) | |
.catch(error => console.warn(error)); | |
}; | |
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