Skip to content

Instantly share code, notes, and snippets.

@hanxue
Created February 22, 2018 19:22
Show Gist options
  • Save hanxue/47b7d555ce3aa7335cb68b5364c129f9 to your computer and use it in GitHub Desktop.
Save hanxue/47b7d555ce3aa7335cb68b5364c129f9 to your computer and use it in GitHub Desktop.
Webpack 4 Vue.js error
<template>
<form novalidate class="md-layout-row md-gutter" @submit.prevent="validateUser">
<md-card class="md-flex-50 md-flex-small-100">
<md-card-header>
<div class="md-title">PMI Calculator</div>
</md-card-header>
<md-card-content>
<div class="md-layout-row md-layout-wrap md-gutter">
<div class="md-flex md-flex-small-100">
<md-field :class="getValidationClass('houseValue')">
<label for="purchase-price">Purchase Price/Estimated Property Value</label>
<md-input name="purchase-price" id="purchase-price" autocomplete="given-name" v-model="houseValue" :disabled="sending" />
<span class="md-error" v-if="!$v.houseValue.required">The purchase price is required</span>
<span class="md-error" v-else-if="!$v.houseValue.between">Invalid purchase price</span>
</md-field>
</div>
<div class="md-flex md-flex-small-100">
<md-field :class="getValidationClass('loanAmount')">
<label for="last-name">Loan Amount</label>
<md-input name="last-name" id="loan-amount" autocomplete="loan-amount" v-model="loanAmount" :disabled="sending" />
<span class="md-error" v-if="!$v.loanAmount.required">The loan amount is required</span>
<span class="md-error" v-else-if="!$v.loanAmount.between">Invalid loan amount</span>
<span class="md-error" v-else-if="!$v.loanAmount.maxLength">Loan amount cannot be more than purchase price</span>
</md-field>
</div>
</div>
<div class="md-layout-row md-gutter md-layout-wrap">
<div class="md-flex md-flex-small-100">
<md-field :class="getValidationClass('selectedFicoScore')">
<label for="fico-score">Fico Score</label>
<md-select v-model="selectedFicoScore" md-dense>
<md-option v-for="score in ficoScores" :key='score'>{{score}}</md-option>
</md-select>
<!-- <select class="form-control" v-model="selectedFicoScore">
<option v-for="score in ficoScores" :key='score'>{{score}}</option>
</select> -->
<span class="md-error">FICO score is required</span>
</md-field>
</div>
</div>
Your LTV (Loan to Value) is <strong>{{ltv}}%</strong> <br />
You have <strong>{{equityPercentage}}%</strong> equity which is <strong>{{equity}}</strong><br />
Selected FICO score is <b>{{selectedFicoScore}}</b> <br />
<span v-if="ltv > 80">
Your will pay approximatley <strong>{{pmi}}</strong> in Private Mortgage Insurance per month.
</span>
<span v-if="ltv < 80">
YAY no PMI for you!
</span>
</md-card-content>
<md-progress-bar md-mode="indeterminate" v-if="sending" />
</md-card>
<md-snackbar :md-active.sync="userSaved">The user {{ lastUser }} was saved with success!</md-snackbar>
</form>
</template>
<script>
import accounting from 'accounting'
import { validationMixin } from 'vuelidate'
import {
required,
email,
minLength,
maxLength,
between
} from 'vuelidate/lib/validators'
export default {
name: 'PMI',
mixins: [validationMixin],
data: () => ({
menuVisible: false,
ficoScores: [ '760+', '740-759','720-739', '700-719', '680-699',
'660-679', '640-659', '620-639'],
selectedFicoScore: '660-679',
houseValue: accounting.formatMoney(300000,'$', 0),
loanAmount: accounting.formatMoney(285000,'$', 0),
basisPoints: 0,
userSaved: false,
sending: false,
lastUser: null,
}),
validations: {
// form: {
houseValue: {
required,
between: between(0, 100000000)
},
loanAmount: {
required,
between: between(0, 100000000),
// maxLength: maxLength(this.houseValue)
},
selectedFicoScore: {
required
},
email: {
required,
email
},
// }
},
computed: {
ltv: function() {
var ltv = (accounting.unformat(this.loanAmount) /
accounting.unformat(this.houseValue) * 100).toFixed(2);
switch(this.selectedFicoScore) {
case '760+':
if ( ltv <= 85 )
this.basisPoints = .0019;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0030;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0041;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0055;
break;
case '740-759':
if ( ltv <= 85 )
this.basisPoints = .0020;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0041;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0059;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0075;
break;
case '720-739':
if ( ltv <= 85 )
this.basisPoints = .0023;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0050;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0073;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0095;
break;
case '700-719':
if ( ltv <= 85 )
this.basisPoints = .0027;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0060;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0087;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0115;
break;
case '680-699':
if ( ltv <= 85 )
this.basisPoints = .0032;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0073;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0108;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0140;
break;
case '660-979':
if ( ltv <= 85 )
this.basisPoints = .0041;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0100;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0142;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0190;
break;
case '640-659':
if ( ltv <= 85 )
this.basisPoints = .0043;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0105;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0150;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0205;
break;
case '620-639':
if ( ltv <= 85 )
this.basisPoints = .0045;
else if ( ltv >= 85.01 && ltv <= 90 )
this.basisPoints = .0110;
else if ( ltv >= 90.01 && ltv <= 95 )
this.basisPoints = .0161;
else if ( ltv >= 95.01 && ltv <= 97 )
this.basisPoints = .0225;
break;
}
return ltv;
},
equityPercentage: function() {
return (100 - this.ltv).toFixed(2);
},
equity: function() {
return accounting.formatMoney(accounting.unformat(this.houseValue) -
accounting.unformat(this.loanAmount), '$', 0);
},
pmi: function() {
if(this.ltv <= 80) {
return 0
}
else {
return accounting.formatMoney(
(this.basisPoints * accounting.unformat(this.loanAmount)) / 12);
}
}
},
methods: {
getValidationClass (fieldName) {
const field = this.$v[fieldName]
if (field) {
return {
'md-invalid': field.$invalid && field.$dirty
}
}
},
clearForm () {
this.$v.$reset()
this.houseValue = null
this.loanAmount = null
this.selectedFicoScore = null
},
saveUser () {
this.sending = true
// Instead of this timeout, here you can call your API
window.setTimeout(() => {
this.lastUser = `${this.loanAmount} ${this.houseValue}`
this.userSaved = true
this.sending = false
this.clearForm()
}, 1500)
},
validateUser () {
this.$v.$touch()
if (!this.$v.$invalid) {
this.saveUser()
}
}
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment