Skip to content

Instantly share code, notes, and snippets.

@jet2018
Created August 6, 2019 07:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jet2018/b4169bc24dd1f3008487fb02013ef3f7 to your computer and use it in GitHub Desktop.
Save jet2018/b4169bc24dd1f3008487fb02013ef3f7 to your computer and use it in GitHub Desktop.
<!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;
background-color:#fff;
padding: 1em;
}
[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 */
[data-cart-info] span{
display:inline-block;
vertical-align:middle;
}
.material-icons{
font-size:150px;
}
[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:#fff;
font-size:2em;
line-height:2em;
border:none;
background:none;
margin-right:0.5em;
}
[data-cc-info]{
margin-top:1em;
}
[data-cc-info] input{
color:#fff;
font-size:1.2em;
border:none;
background:none;
}
[data-cc-info] input:nth-child(2){
padding-right:10px;
float:right;
}
[data-pay-btn]{
position:fixed;
width:90%;
border:solid 1px;
bottom:20px;
}
</style>
<!--mystyles end here-->
</head>
<body>
<!--html begins here -->
<div data-cart-info>
<h1 class="mdc-typography--headline4">
<span class="material-icons">shopping_cart</span>
<span data-bill></span>
</h1>
</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 size="20" type="text" placeholder="Name Surname">
<input size="6" type="text" placeholder="MM/YY">
</div>
</div>
</div>
<button class="mdc-button" data-pay-btn="">Pay Now</button>
<!--and ends here -->
<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)
);
}
});
};
//myscripts start here
const appState ={};
const smartCursor =(event,fieldIndex, fields) => {
if(event.target.value.length === event.target.size && fieldIndex < fields.length -1){
fields[fieldIndex +1].focus();
}
}
const smartInput = (event, index) =>
{
if(event.target.parentElement.hasAttribute("data-cc-digits")){
if(/\d{d}$/.test(event.key) || event.key === "Backspace"){
if(/\d/.test(event.key)){
if(event.target.selectionStart < event,target.value.length){
appState.cardDigits[index].splice(event.target.selectionStart,0,event.key);
}
else{
appState.cardDigits[index].push(event.key)
}
setTimeout(() =>{
event.target.value = "#".repeat(event.target.value.length);
if(event.target.value.length === 4){
detectCardType(appState.cardDigits[0])
}
}, 500);
}
else{
appState.cardDigits[index].splice(event.target.selectionStart-1, 1)
}
}
else{
event.preventDefault();
}
}
}
const enableSmartTyping = () =>{
const digitsNodeList = document.querySelectorAll("div[data-cc-digits] input");
const infoNodeList = document.querySelectorAll("div[data-cc-info] input");
const inputArray = [];
digitsNodeList.forEach(_Node => inputArray.push(_Node));
infoNodeList.forEach(_Node => inputArray(_Node));
inputArray.forEach((field,index, fields) => {
field.addEventListener("keyup", (event) =>{
smartCursor(event, index, fields)
})
field.addEventListener("keydown", (event) =>{
smartInput(event, index)
})
})
}
const formatAsMoney = (amount, buyerCountry) => {
const findCountry = countries.find(value => value.country === buyerCountry);
if(findCountry){
return amount.toLocaleString(`en-${findCountry.code}`,{
style:"currency",
currency:findCountry.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 = (field) =>{
const reg = /^(((1|)[0-9])|((1)[0-9]))(\/)\d{2}$/;
const result = reg.test(field.value)
return result
};
const detectCardType = (first4Digits) => {
}
const validateCardExpiryDate = () =>{
const field = document.querySelector('[data-cc-info] input:last-child')
const month = field.value.split('/')[0]
const validDate = expiryDateFormatIsValid(field)
const year = `20${field.value.split('/')[1]}`
const expDate = new Date(`${year}/${month}`)
const results = validDate && expDate >= new Date() ? (console.log('valid date'), true) : (console.log('invalid date'), false)
flagIfInvalid(field, results);
return results
};
const validateCardHolderName = () =>{
const target = document.querySelector('[data-cc-info] input:first-child')
const isMatch = /^[a-zA-Z]{3,}\s[a-zA-Z]{3,}$/.test(target.value.trim());
if(isMatch){
flagIfInvalid(target, true)
console.log('valid Names')
return true
}else{
flagIfInvalid(target, false)
console.log('Invalid Name: Require atleast three letters')
return false
}
};
const validateCardNumber = () =>{
}
const validatePayment =() =>{
validateCardNumber();
console.log(validateCardHolderName());
validateCardExpiryDate();
}
const acceptCardNumbers =(event, fieldIndex) =>{
}
const uiCanInteract = () =>{
document.querySelectorAll("div[data-cc-digits] input")[0].focus();
const payBtn = document.querySelector('[data-pay-btn]');
payBtn.addEventListener('click',validatePayment);
billHype();
enableSmartTyping();
};
const displayCartTotal = ({results}) =>{
const [data] = results;
const {itemsInCart, buyerCountry} = data;
appState.items = itemsInCart;
appState.country = buyerCountry;
appState.bill = itemsInCart.reduce((acc, curr) => acc + (curr.price * curr.qty), 0);
appState.billFormatted = formatAsMoney(appState.bill,appState.country);
const dataBill = document.querySelector('[data-bill]');
dataBill.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((data) => displayCartTotal(data))
.catch((err) => {return 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