Skip to content

Instantly share code, notes, and snippets.

@jet2018
Created August 6, 2019 07:48
Show Gist options
  • Select an option

  • Save jet2018/b4169bc24dd1f3008487fb02013ef3f7 to your computer and use it in GitHub Desktop.

Select an option

Save jet2018/b4169bc24dd1f3008487fb02013ef3f7 to your computer and use it in GitHub Desktop.

Revisions

  1. jet2018 created this gist Aug 6, 2019.
    417 changes: 417 additions & 0 deletions challenge2.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,417 @@
    <!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>