<!-- Josh Channin -->
<body>
<div class="container">
<div class="wallet">
<aside class="left-wallet">
<div class="wallet-head">
<h1> My Wallets </h1>
<div class="modal-open">+
</div>
</div>
<div class="cc-select">
</div>
</aside>
<content class="right-trans">
<h1> Current Balance </h1>
<h4 id="balance"></h4>
<div class="trans-list">
</div>
</content>
</div>
</div>
<div class="modal">
<div class="modal-body">
<h3>Add a New Card</h3>
<h5>Select a card on the left and enter the information</h5>
<div class="modal-close">x</div>
<div class="modal-cards">
<div class="md-cc visa">
<div class="cc-img visa"></div>
</div>
<div class="md-cc amex">
<div class="cc-img amex"></div>
</div>
<div class="md-cc mc">
<div class="cc-img mc"></div>
</div>
</div>
<form>
<input type="text" id="ccnum" disabled>
<select name="month" id="month" required disabled>
<option value="">Month</option>
<option value="01">Janaury</option>
<option value="02">February</option>
<option value="03">March</option>
<option value="04">April</option>
<option value="05">May</option>
<option value="06">June</option>
<option value="07">July</option>
<option value="08">August</option>
<option value="09">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
<select name="year" id="year" required disabled>
<option value="">Year</option>
<option value="16">2016</option>
<option value="17">2017</option>
<option value="18">2018</option>
<option value="19">2019</option>
<option value="20">2020</option>
<option value="21">2021</option>
<option value="22">2022</option>
<option value="23">2023</option>
<option value="24">2024</option>
</select>
</form>
<button class="modal-add-cc"> Add </button>
</div>
</body>
/* Josh Channin
*/
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400,600|Roboto:300,400');
body {
font-family: 'Open Sans', sans-serif;
background-color: rgb(255, 204, 102);
}
.container {
width: 100%;
padding: 40px 0px 40px 0px;
}
.wallet {
margin: 0 auto;
border-radius: 5px;
background-color: #FFFFFF;
box-shadow: 0px 8px 20px 6px rgb(255, 178, 22);
-webkit-box-shadow: 0px 8px 20px 6px rgb(255, 178, 22);
-moz-box-shadow: 0px 8px 20px 6px rgb(255, 178, 22);
height: 680px;
max-width: 900px;
min-width: 800px;
display: flex;
}
.left-wallet {
background-color: #f2f2f2;
width: 300px;
height: initial;
padding: 40px;
border-radius: 5px;
}
.right-trans {
background-color: #FFFFFF;
width: 600px;
height: initial;
padding: 40px;
border-radius: 5px;
}
h1 {
color: #7d818e;
margin: 0;
font-weight: 400;
font-size: 25px;
font-family: 'Open Sans', sans-serif;
}
h4 {
margin: 0;
font-size: 30px;
font-weight: bold;
font-family: 'Open Sans', sans-serif;
}
.left-wallet h1,
.left-wallet modal-open,
.right-trans h1,
.right-trans #balance {
font-family: 'Open Sans', sans-serif;
display: inline-block;
}
#balance {
float: right;
line-height: 34px;
font-size: 30px;
font-weight: bold;
color: #464646;
}
.modal-open {
display: inline-block;
float: right;
padding: 0;
font-size: 42px;
line-height: 36px;
color: #b7b7b7;
cursor: pointer;
}
.modal-open:hover {
display: inline-block;
float: right;
padding: 0;
font-size: 42px;
line-height: 36px;
color: #868686;
cursor: pointer;
}
.trans-list {
display: none;
border-top: 1px solid #f2f2f2;
margin-top: 40px;
overflow-y: scroll;
max-height: 550px;
}
.trans {
margin-top: 15px;
}
.trans-plus {
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/384009/plus-icon.png);
background-repeat: no-repeat;
width: 40px;
height: 50px;
display: block;
float: left;
position: relative;
top: 15px;
}
.trans-minus {
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/384009/minus-icon.png);
background-repeat: no-repeat;
width: 40px;
height: 50px;
display: block;
float: left;
position: relative;
top: 15px;
}
.trans-details {
margin-top: 20px;
display: inline-block;
width: 80%;
}
.trans-name,
.trans-type-date {
margin: 3px;
}
.trans-name {
display: inline-block;
}
.trans-type-date {
color: #888;
padding-left: 40px;
}
.trans-amt {
float: right;
line-height: 55px;
font-size: 18px;
margin-top: 10px
}
.amt-green {
color: rgb(113, 207, 66);
}
.amt-blue {
color: rgb(166, 178, 216);
}
.cc-select {
margin-top: 34px;
overflow-y: scroll;
max-height: 540px;
padding: 5px;
}
.cc {
cursor: pointer;
background-color: #fff;
padding: 20px;
border-radius: 5px;
margin-bottom: 30px;
border: 1px solid #e1e1e1;
transition: .1s ease-in-out;
}
.cc:hover {
transform: scale(1.03);
border: 1px solid gray;
}
.cc-active:hover {
transform: scale(1);
border: 4px solid rgb(132, 148, 202);
}
.cc-active {
border: 4px solid rgb(132, 148, 202);
}
.cc-img {
width: 60px;
height: 40px;
background-repeat: no-repeat;
background-size: cover;
border-radius: 4px;
margin-bottom: 15px
}
.cc-img-main {
width: 60px;
height: 40px;
background-repeat: no-repeat;
background-size: cover;
border-radius: 4px;
margin-bottom: 15px
}
.cc-num {
font-family: 'Roboto', sans-serif;
font-size: 15px;
}
.cc-date {
margin-top: 8px;
font-family: 'Roboto', sans-serif;
color: #888;
}
.visa .cc-img,
.visa .cc-img-main {
background-image: url("http://i.imgur.com/xYX6Tsy.png")
}
.amex .cc-img,
.amex .cc-img-main {
background-image: url("http://i.imgur.com/47221vA.png")
}
.mc .cc-img,
.mc .cc-img-main {
background-image: url("http://i.imgur.com/2fWTLRZ.png")
}
.modal {
text-align: center;
display: none;
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.6);
z-index: 1;
}
.modal-body {
z-index: 2;
background-color: #fff;
border-radius: 5px;
padding: 40px;
padding-top: 10px;
padding-bottom: 50px;
display: inline-block;
margin-top: 100px;
width: 100%;
max-width: 400px;
position: relative;
}
.modal-close {
position: absolute;
top: 5px;
right: 10px;
font-size: 20px;
cursor: pointer;
font-weight: bold;
color: #888;
}
.modal-close:hover {
transform: scale(1.2);
cursor: pointer;
}
.md-cc .cc-img {
cursor: pointer;
}
.md-cc .cc-img:hover {
cursor: pointer;
transform: scale(1.25);
transition: .1s ease-in-out;
}
.cc-md-active {
transform: scale(1.25);
}
.cc-md-small {
transform: scale(.80);
}
.modal-cards {
width: 15%;
display: inline-block;
float: left;
}
.modal-add-cc {
position: absolute;
bottom: 15px;
left: 190px;
color: #fff;
background-color: #0275d8;
border-color: #0275d8;
font-weight: 400;
text-align: center;
padding: .25rem 2rem;
font-size: 1rem;
border-radius: .25rem;
-webkit-transition: all .2s ease-in-out;
-o-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
}
::-webkit-scrollbar {
display: none;
}
form {
width: 75%;
float: right;
}
form>input,
form select {
display: block;
width: initial;
border: 1px solid #e1e1e1;
padding: 5px;
margin: 5px
}
.modal-body>h3,
.modal-body>h5 {
color: #777;
}
textarea:focus,
input:focus {
outline: none;
}
.modal-body>h5 {
border-top: 1px solid #e1e1e1;
padding-top: 20px;
}
.no-trans {
color: #888;
text-align: center;
}
.valid-green {
border: 2px solid green;
}
.valid-red {
border: 2px solid darkred;
}
/* Josh Channin
Fake data from generatedata.com
*/
var data = [
{
type: "visa",
number: "**** **** **** 2562",
month: "12",
year: "17",
id: 1,
transactions: [
{
title: "Apple Iphone 6, 6g GB",
vendor: "Electronics #343223",
date: "12 July, 2015",
amount: "650.00",
currency: "$",
action: "debit"
},
{
title: "Funds Added",
vendor: "Payment #343212",
date: "11 July, 2015",
amount: "900.00",
currency: "$",
action: "credit"
},
{
title: "Energy Bill",
vendor: "#343566",
date: "11 July, 2015",
amount: "84.96",
currency: "$",
action: "debit"
},
{
title: "Mega Image SRL",
vendor: "Food&Health #34365",
date: "11 July, 2015",
amount: "112.75",
currency: "$",
action: "debit"
},
{
title: "ATM DV24",
vendor: "#343253",
date: "09 July, 2015",
amount: "200.00",
currency: "$",
action: "debit"
},
{
title: "Lukoil Station",
vendor: "Gas #343279",
date: "09 July, 2015",
amount: "190.00",
currency: "$",
action: "debit"
}
]
},
{
type: "amex",
number: "**** ****** 14525",
month: "07",
year: "19",
id: 2,
transactions: [
{"title": "Sales and Marketing", "vendor": "Borland", "date": "23 Nov, 2016", "amount": "65.76", "currency": "$", "action": "debit"},
{"title": "Tech Support", "vendor": "Microsoft", "date": "1 Aug, 2017", "amount": "64.62", "currency": "$", "action": "debit"},
{"title": "Media Relations", "vendor": "Chami", "date": "8 Jun, 2017", "amount": "98.82", "currency": "$", "action": "debit"},
{"title": "Accounting", "vendor": "Chami", "date": "21 Jan, 2017", "amount": "7889.84", "currency": "$", "action": "credit"},
{"title": "Sales and Marketing", "vendor": "Lavasoft", "date": "24 Jul, 2017", "amount": "77.68", "currency": "$", "action": "debit"},
{"title": "Asset Management", "vendor": "Cakewalk", "date": "11 Oct, 2016", "amount": "52.40", "currency": "$", "action": "credit"},
{"title": "Finances", "vendor": "Sibelius", "date": "19 Aug, 2016", "amount": "32.20", "currency": "$", "action": "debit"},
{"title": "Sales and Marketing", "vendor": "Chami", "date": "4 Jun, 2017", "amount": "72.62", "currency": "$", "action": "debit"},
{"title": "Customer Relations", "vendor": "Finale", "date": "22 Aug, 2017", "amount": "77.77", "currency": "$", "action": "debit"},
{"title": "Sales and Marketing", "vendor": "Apple Systems", "date": "19 May, 2017", "amount": "84.50", "currency": "$", "action": "credit"},
{"title": "Quality Assurance", "vendor": "Cakewalk", "date": "29 Jul, 2017", "amount": "80.03", "currency": "$", "action": "debit"},
{"title": "Public Relations", "vendor": "Altavista", "date": "10 Oct, 2017", "amount": "6.60", "currency": "$", "action": "credit"}
]
},
{
type: "mc",
number: "**** **** **** 8866",
month: "02",
year: "22",
id: 3,
transactions: [
{"title": "Borland", "vendor": "Cursus Diam PC", "date": "30 Apr, 2017", "amount": "9647.17", "currency": "$", "action": "debit"},
{"title": "Sibelius", "vendor": "Ridiculus Corporation", "date": "17 Apr, 2017", "amount": "1058.02", "currency": "$", "action": "credit"},
{"title": "Altavista", "vendor": "Molestie Orci Tincidunt Company", "date": "9 Mar, 2018", "amount": "6622.94", "currency": "$", "action": "credit"},
{"title": "Sibelius", "vendor": "Eu Industries", "date": "20 Mar, 2017", "amount": "2649.70", "currency": "$", "action": "credit"},
{"title": "Yahoo", "vendor": "Mollis Nec Cursus Associates", "date": "20 Sep, 2016", "amount": "9343.63", "currency": "$", "action": "credit"},
{"title": "Sibelius", "vendor": "Eget Metus Eu Incorporated", "date": "27 Jun, 2016", "amount": "6516.49", "currency": "$", "action": "credit"},
{"title": "Google", "vendor": "Tempus Company", "date": "26 May, 2017", "amount": "8504.32", "currency": "$", "action": "debit"},
{"title": "Chami", "vendor": "Id Ante Incorporated", "date": "13 Aug, 2017", "amount": "3592.96", "currency": "$", "action": "credit"},
{"title": "Finale", "vendor": "Iaculis Quis Incorporated", "date": "2 Jan, 2017", "amount": "8743.26", "currency": "$", "action": "debit"},
{"title": "Chami", "vendor": "Eu Nulla At Institute", "date": "5 Sep, 2017", "amount": "3112.89", "currency": "$", "action": "credit"},
{"title": "Adobe", "vendor": "Arcu Nunc Inc.", "date": "22 Aug, 2017", "amount": "2239.85", "currency": "$", "action": "credit"},
{"title": "Macromedia", "vendor": "Eros LLP", "date": "17 Feb, 2018", "amount": "3641.58", "currency": "$", "action": "debit"},
{"title": "Macromedia", "vendor": "Diam Dictum Associates", "date": "24 Dec, 2016", "amount": "3592.79", "currency": "$", "action": "credit"},
{"title": "Yahoo", "vendor": "Eget Odio Aliquam Corporation", "date": "30 Oct, 2016", "amount": "9453.17", "currency": "$", "action": "credit"},
{"title": "Sibelius", "vendor": "Eros Non Enim Company", "date": "15 Feb, 2018", "amount": "5283.54", "currency": "$", "action": "debit"}
]
}
];
// vars
var balance = 0;
// append cc to modal
var ccModalAppend= function(ccType, ccNum, month, year) {
if(ccType == 'amex') {
$(".cc-select").prepend(
'<div class="cc ' +
ccType +
' cc-active">\
<div class="cc-img-main"></div>\
<div class="cc-num">**** ******* ' +
ccNum +
'</div>\
<div class="cc-date">Valid Thru: ' +
month +
"/" +
year +
"</div>\
</div>"
);
} else {
$(".cc-select").prepend(
'<div class="cc ' +
ccType +
' cc-active">\
<div class="cc-img-main"></div>\
<div class="cc-num">**** **** **** ' +
ccNum +
'</div>\
<div class="cc-date">Valid Thru: ' +
month +
"/" +
year +
"</div>\
</div>"
);
}
}
// append credit cards
var ccAppend = function(data) {
$(".cc-select").append(
'<div id="'+data.id+'" class="cc ' +
data.type +
'">\
<div class="cc-img-main"></div>\
<div class="cc-num">' +
data.number +
'</div>\
<div class="cc-date">Valid Thru: ' +
data.month +
"/" +
data.year +
"</div>\
</div>"
)
}
// load trams data
var load = function(id, data) {
clearTrans();
balance = 0;
data.forEach(function(e) {
if (e.id == id) {
startAppend(e);
}
});
balanceCalc(balance);
noTrans();
};
// count valid cc numbers
var countValid = function(ccType) {
if(ccType == 'amex') {
if($('#ccnum').val().length != 15) {
$('#ccnum').removeClass('valid-green')
$('#ccnum').addClass('valid-red')
return false;
} else {
$('#ccnum').addClass('valid-green')
$('#ccnum').removeClass('valid-red')
return true;
}
} else {
if($('#ccnum').val().length != 16) {
$('#ccnum').addClass('valid-red')
$('#ccnum').removeClass('valid-green')
return false;
} else {
$('#ccnum').addClass('valid-green')
$('#ccnum').removeClass('valid-red')
return true;
}
}
}
// append trans data
var startAppend = function(e) {
for (var i = 0; i < e.transactions.length; i++) {
if (e.transactions[i].action == "credit") {
var action = "trans-plus";
var color = "green";
balance = balance + parseFloat(e.transactions[i].amount,10);
} else {
var action = "trans-minus";
var color = "blue";
balance = balance - parseFloat(e.transactions[i].amount,10);
}
$(".trans-list").append(
' <div class="trans trans-' +
e.type +
'">\
<div class="trans-details">\
<span class="' +
action +
'"></span>\
<h3 class="trans-name">' +
e.transactions[i].title +
'</h3>\
<h5 class="trans-type-date">' +
e.transactions[i].vendor +
" - " +
e.transactions[i].date +
'</h5>\
</div>\
<div class="trans-amt">\
<h4 class="trans-amt amt-' +
color +
'">' +
e.transactions[i].currency +
" " +
e.transactions[i].amount +
"</h4>\
</div>\
</div>"
).show('fast');
noTrans();
}
}
// calc balance and format
var balanceCalc = function balanceCalc(balance) {
return balance < 0 ? $("#balance").html("$(" + Math.abs(balance).toLocaleString() + ")") : $("#balance").html("$" + balance.toLocaleString() + "");
}
// clear trans list
var clearTrans = function(){
$(".trans-list").empty().hide();
}
// clear modal
var clearModal = function() {
$('.cc-img').removeClass('cc-md-active')
$('#ccnum, #year, #month').val('')
$('#ccnum').css('border','1px solid #e1e1e1;')
$('#ccnum').removeClass('valid-red').removeClass('valid-green')
}
// no trans
var noTrans = function() {
$('.trans-list').children().length == 0 ? $(".trans-list").append('<h5 class="no-trans"> No transactions for this card</h5>').show('fast') :"";
}
// load inital data
$(document).ready(function() {
data.forEach(function(e){
ccAppend(e)
})
$(".cc:eq(0)").addClass("cc-active")
load($(".cc-active").attr("id"),data)
});
// click listener for active card
$(document).on("click", ".cc", function(e) {
$(".cc").removeClass("cc-active");
$(this).addClass("cc-active");
load($(".cc-active").attr("id"),data)
});
// click listener for active card in modal selector
$(document).on("click", ".cc-img", function(e) {
$(".cc-img").removeClass("cc-md-active");
$(this).addClass("cc-md-active");
($(".md-cc > .cc-md-active").attr("class").split(" ")[1] == 'amex') ? $('#ccnum').attr('placeholder','**** ****** *****') : $('#ccnum').attr('placeholder','**** **** **** ****')
$('#ccnum, #year, #month').removeAttr('disabled');
});
// close modal
$(document).on("click", ".modal-close", function(e) {
$(".modal").hide();
clearModal();
});
// open modal
$(".modal-open").on("click", function(e) {
$(".modal").show();
});
// add new card logic
// TODO: Add numbous checks, sanitize, error catching
$(document).on("click", ".modal-add-cc", function(e) {
var ccType = null;
if ($(".md-cc > .cc-md-active").attr("class")) {
ccType = $(".md-cc > .cc-md-active").attr("class").split(" ")[1];
}
var ccNum = $("#ccnum").val().substr($("#ccnum").val().length - 4);
var month = $("#month").val();
var year = $("#year").val();
if (ccNum && month && year && ccType) {
$(".modal").hide();
$(".cc").removeClass("cc-active");
ccModalAppend(ccType,ccNum,month,year)
var p = data[data.length-1].id + 1
data.push({
type: ccType,
number: (ccType == 'amex') ? "**** ****** "+ccNum : "**** **** **** "+ccNum ,
month: month,
year: year,
id: p,
transactions: []
})
clearTrans()
clearModal();
load(ccType,data)
} else {
alert("Sorry, missing required fields"); // will do for now
}
});
// keypress cc count
$('#ccnum').on('keyup', function(){
var ccType = $(".md-cc > .cc-md-active").attr("class").split(" ")[1];
countValid(ccType);
})
This Pen doesn't use any external CSS resources.