A UI for transferring money from 2 accounts(or more). Recreated this section from my internet banking home page with VueJS and CSS Flexbox.
A Pen by Vashon Gonzales on CodePen.
A UI for transferring money from 2 accounts(or more). Recreated this section from my internet banking home page with VueJS and CSS Flexbox.
A Pen by Vashon Gonzales on CodePen.
<div id="app"> | |
<header> | |
<div class="header"> | |
<h1>{{ headerTitle }}</h1> | |
<transition name="fade"> | |
<div id="message" v-if="showMsg" :style="{backgroundColor: msgColor}">{{ msg }}</div> | |
</transition> | |
<button @click="revealClass = 'slide-down'">Quick Transfer</button> | |
</div> | |
</header> | |
<section> | |
<a href="#0" class="close-btn" @click="revealClass = 'slide-up'">🗙</a> | |
<form class="transferForm"> | |
<div class="input-box"> | |
<label for="Account-1">From:</label> | |
<select v-model="gBal" @change="autoSelect(gBal)"> | |
<option value="0">Select an account</option> | |
<option value="1">Credit</option> | |
<option value="2">Classic Account</option> | |
</select> | |
</div> | |
<div class="input-box"> | |
<label for="Account-2">To:</label> | |
<select v-model="cBal"> | |
<option value="0">Select an account</option> | |
<option value="1" id="opt1">Classic Account</option> | |
<option value="2" id="opt2">Credit Facility Account</option> | |
</select> | |
</div> | |
<div class="input-box"> | |
<label for="transferAmount">Amount: ${{ transferAmount }}</label> | |
<input type="text" v-model="transferAmount" /> | |
</div> | |
<div class="input-box"> | |
<button @click.prevent="makeTransfer">Transfer</button> | |
</div> | |
</form> | |
</section> | |
<section :class="revealClass"> | |
<div class="accounts"> | |
<ul> | |
<li> | |
<p> | |
<strong>Credit</strong> | |
</p> | |
<p :class="balance1">{{ goBalance }}</p> | |
</li> | |
<li> | |
<p> | |
<strong>Classic Account</strong> | |
</p> | |
<p :class="balance2">{{ classicBalance }}</p> | |
</li> | |
</ul> | |
</div> | |
</section> | |
</div> |
new Vue ({ | |
// ELEMENT | |
el: '#app', | |
// DATA | |
data: { | |
headerTitle: 'Credit Facility', | |
goBalance: '284.90', | |
classicBalance: '1800.00', | |
gBal: 0, | |
cBal: 0, | |
transferAmount: 0, | |
msg: '', | |
showMsg: false, | |
msgColor: '', | |
revealClass: 'slide', | |
balance1: '', | |
balance2: '' | |
}, | |
// WATCH | |
watch: { | |
transferAmount: function() { | |
var goAmount = parseFloat(this.goBalance); | |
var classicAmount = parseFloat(this.classicBalance); | |
var transAmt = parseFloat(this.transferAmount); | |
if(transAmt > goAmount && this.cBal == 1) { | |
this.showMessage('You have insufficient funds in your Facility to transfer. Try a lesser amount', 'red'); | |
} | |
if(transAmt > classicAmount && this.cBal == 2) { | |
this.showMessage('You have insufficient funds in your Classic Account to transfer. Try a lesser amount', 'red'); | |
} | |
} | |
}, | |
//METHODS | |
methods: { | |
makeTransfer: function() { | |
var num = 0; | |
if(this.transferAmount != 0) { | |
if(this.cBal == '1' && this.gBal == '1') { | |
this.goBalance = this.addSum(this.goBalance, this.transferAmount, 'minus'); | |
this.classicBalance = this.addSum(this.classicBalance, this.transferAmount, 'add'); | |
num = 2; | |
} | |
if(this.cBal == '2' && this.gBal == '2') { | |
this.goBalance = this.addSum(this.goBalance, this.transferAmount, 'add'); | |
this.classicBalance = this.addSum(this.classicBalance, this.transferAmount, 'minus'); | |
num = 1; | |
} | |
this.resetForm(num); | |
} else { | |
this.showMessage('You must enter a transfer amount', 'red'); | |
} | |
}, | |
addSum(bal, amt, mode) { | |
var b = parseFloat(bal); | |
var a = parseFloat(amt); | |
var sum; | |
if(mode == 'minus') { | |
sum = (b - a).toFixed(2); | |
} | |
if(mode == 'add') { | |
sum = (b + a).toFixed(2); | |
} | |
return sum; | |
}, | |
resetForm: function(num) { | |
this.cBal = 0; | |
this.gBal = 0; | |
this.transferAmount = 0; | |
this.showMessage('Transfer Successful', 'green') | |
this['balance' + num] = 'transfer-ani' | |
document.getElementById('opt1').disabled = false; | |
document.getElementById('opt2').disabled = false; | |
}, | |
showMessage(msg, color) { | |
this.showMsg = true; | |
this.msg = msg; | |
this.msgColor = color; | |
var vm = this; | |
setTimeout(function() { | |
vm.showMsg = false; | |
}, 2000); | |
}, | |
autoSelect(num) { | |
var opt1 = document.getElementById('opt1'); | |
var opt2 = document.getElementById('opt2'); | |
this.cBal = num; | |
if(num == 1 || opt1.disabled == false) { | |
opt2.disabled = true; | |
opt1.disabled = false; | |
} | |
if(num == 2 || opt2.disabled == false) { | |
opt1.disabled = true; | |
opt2.disabled = false; | |
} | |
} | |
} | |
}); |
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.6/vue.min.js"></script> |
body { | |
font-family: sans-serif; | |
margin: 0; | |
padding: 0; | |
} | |
input[type=text] { | |
height: 23px; | |
padding-left: 5px; | |
border: 1px solid silver; | |
border-radius: 3px; | |
} | |
select { | |
border: 1px solid silver; | |
border-radius: 3px; | |
} | |
.header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
padding: 30px; | |
} | |
.header h1 { | |
font-size: 20px; | |
font-weight: 200; | |
color: #4CA5FF; | |
} | |
.header button { | |
background-color: #FFFFFF; | |
border: 1px solid #4CA5FF; | |
color: #4CA5FF; | |
padding: 10px 20px; | |
text-align: center; | |
text-decoration: none; | |
display: inline-block; | |
font-size: 12px; | |
border-radius: 5px; | |
} | |
.transferForm { | |
display: flex; | |
justify-content: space-between; | |
align-items: flex-end; | |
padding: 50px 30px; | |
background-color: #EFEFEF; | |
} | |
.header h1 { | |
font-size: 20px; | |
font-weight: 200; | |
color: #4CA5FF; | |
} | |
.transferForm button { | |
background-color: #4CA5FF; | |
border: none; | |
color: #FFFFFF ; | |
padding: 8px 16px; | |
text-align: center; | |
text-decoration: none; | |
display: inline-block; | |
font-size: 12px; | |
border-radius: 5px; | |
} | |
.input-box { | |
display: flex; | |
flex-direction: column; | |
font-size: 14px; | |
} | |
.input-box label { | |
font-size: 12px; | |
margin-bottom: 10px; | |
} | |
.input-box select { | |
background-color: none; | |
width: 300px; | |
padding: 5px; | |
border: 1px solid silver; | |
} | |
.accounts-header { | |
padding: 30px; | |
} | |
.accounts { | |
padding: 20px 30px; | |
border-top: 1px dotted silver; | |
background-color: #FFF; | |
} | |
.accounts ul { | |
list-style: none; | |
padding: 0; | |
margin: 0; | |
display: flex; | |
flex-direction: column; | |
} | |
.accounts ul li { | |
padding: 10px; | |
border-bottom: 1px dotted silver; | |
display: flex; | |
justify-content: space-between; | |
color: #4CA5FF; | |
font-size: 1.5em; | |
color: orange; | |
} | |
.accounts ul li strong { | |
color: #4CA5FF; | |
font-size: 16px; | |
} | |
.slide { | |
transform: translateY(-153px); | |
} | |
.slide-down { | |
animation: slide-down .7s forwards; | |
} | |
.slide-up { | |
animation: slide-up .7s forwards; | |
} | |
@keyframes slide-down { | |
from { | |
transform: translateY(-153px); | |
} | |
to { | |
transform: translateY(0); | |
} | |
} | |
@keyframes slide-up { | |
from { | |
transform: translateY(0); | |
} | |
to { | |
transform: translateY(-153px); | |
} | |
} | |
.close-btn { | |
display: block; | |
width: 20px; | |
height: 20px; | |
font-size: 20px; | |
text-decoration: none; | |
text-align: center; | |
color: #4CA5FF; | |
position: relative; | |
top: 30px; | |
margin: 0 30px 0 auto; | |
} | |
#message { | |
border: 1px solid silver; | |
border-radius: 4px; | |
padding: 10px 30px; | |
font-size: 14px; | |
color: #FFFFFF; | |
position: relative; | |
} | |
.fade-enter-active { | |
animation: fade-in 1s forwards; | |
} | |
.fade-leave-active { | |
animation: fade-out 1s; | |
} | |
@keyframes fade-in { | |
from { | |
opacity: 0; | |
top: -20px; | |
} | |
to { | |
opacity: 1; | |
top: 0; | |
} | |
} | |
@keyframes fade-out { | |
from { | |
opacity: 1; | |
top: 0; | |
} | |
to { | |
opacity: 0; | |
top: -20px; | |
} | |
} | |
.transfer-ani { | |
animation: hilite 3s forwards; | |
} | |
@keyframes hilite { | |
0%, 100% { | |
color: orange; | |
} | |
50% { | |
color: green; | |
} | |
} |