@@ -157,7 +157,6 @@ function start() { | |||
} | |||
export default { | |||
components: { | |||
SideBar, | |||
@@ -102,9 +102,9 @@ | |||
</select> | |||
<label>Loan to Value (%)</label> | |||
<input :value="loans[sel].ltv" @input="(e) => $emit('update:ltv', e)"> | |||
<input :value="loan.ltv" @input="(e) => $emit('update:ltv', e)"> | |||
<label>Loan Amount ($)</label> | |||
<input :value="loans[sel].amount" | |||
<input :value="loan.amount" | |||
@input="(e) => $emit('update:amount', e)"> | |||
<label>Housing Expense DTI (%) - Optional</label> | |||
<input :value="loans[sel].housingDti" | |||
@@ -165,12 +165,12 @@ | |||
<h3>Mortgage Insurance</h3> | |||
<div class="row"> | |||
<input checked type="radio" name="mi"/><label>Manual %</label> | |||
<input type="checkbox" :value="loans[sel].mi.rate" | |||
<input type="checkbox" :checked="loans[sel].mi.monthly" | |||
@change="e => $emit('toggle:manualMIMonthly')" /> | |||
<label>monthly</label> | |||
</div> | |||
<div class="row"> | |||
<input @input="e => $emit('update:manualMI', stripPerc(e))" /> | |||
<input :value="loans[sel].mi.rate" @input="e => $emit('update:manualMI', stripPerc(e))" /> | |||
</div> | |||
</section> | |||
@@ -270,7 +270,7 @@ export default { | |||
strip, stripInt, stripLetters, stripPerc, createFee, addFee, validate, | |||
generate | |||
}, | |||
props: ['estimate', 'loans', 'sel'], | |||
props: ['estimate', 'loans', 'sel', 'loan'], | |||
// Loan updates assume the currently selected loan is being modified, and | |||
// $emit has no need to clarify. | |||
emits: [ | |||
@@ -24,6 +24,7 @@ class="bi bi-plus" viewBox="0 0 16 16"> <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 | |||
:estimate="estimate" | |||
:loans="estimate.loans" | |||
:sel="sel" | |||
:loan="loan" | |||
@update:name="(name) => loans[sel].title = name" | |||
@del="del" | |||
@@ -31,7 +32,7 @@ class="bi bi-plus" viewBox="0 0 16 16"> <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 | |||
@update:creditScore="(c) => estimate.creditScore = c" | |||
@update:mIncome="(m) => estimate.mIncome = m" | |||
@update:transaction="(t) => estimate.transaction = t" | |||
@update:price="(p) => estimate.price = p" | |||
@update:price="setPrice" | |||
@update:property="(p) => estimate.property = p" | |||
@update:loanType="(lt) => loans[sel].type = lt" | |||
@@ -54,9 +55,7 @@ class="bi bi-plus" viewBox="0 0 16 16"> <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 | |||
@continue="generate" | |||
/> | |||
<loan-summary v-if="hash == '#new/summary'" | |||
:estimate="estimate" | |||
:loans="estimate.loans" | |||
:sel="sel" /> | |||
:loan="loan" :downpayment="estimate.price - loan.amount"/> | |||
</div> | |||
</template> | |||
@@ -94,7 +93,7 @@ const loans = [ | |||
Object.assign({}, example,), | |||
Object.assign( | |||
Object.assign({}, example), | |||
{title: "Another One",} | |||
{title: "Another One", mi: {}} | |||
), | |||
] | |||
@@ -109,6 +108,10 @@ const estimate = { | |||
loans: loans, | |||
} | |||
function loan() { | |||
return this.estimate.loans[this.sel] | |||
} | |||
// Clone loan from initial example as a new loan | |||
function create() { | |||
this.estimate.loans.push( | |||
@@ -202,6 +205,7 @@ export default { | |||
generate, createFees, del, create, setPrice, setLtv, setAmount, | |||
setDti, setHousingDti | |||
}, | |||
computed: { loan }, | |||
props: ['user', 'fees'], | |||
data() { | |||
return { | |||
@@ -3,8 +3,10 @@ | |||
<section class="form inputs"> | |||
<h3>Monthly Payment - ${{totalMonthly}}</h3> | |||
<label>Loan payment: ${{loanPayment}}</label> | |||
<label>Mortgage insurance: $0</label> | |||
<label>Loan payment: ${{loanPayment.toFixed(2)}}</label> | |||
<label v-if="loan.mi.monthly"> | |||
Mortgage insurance: ${{(loanPayment*loan.mi.rate/100).toFixed(2)}} | |||
</label> | |||
<label>Property taxes: ${{loan.tax}}</label> | |||
</section> | |||
@@ -12,7 +14,10 @@ | |||
<h3>Cash to Close - ${{totalMonthly}}</h3> | |||
<label>Closing costs: ${{fees}}</label> | |||
<label>Credits: ${{credits}}</label> | |||
<label>Downpayment: ${{downpayment}}</label> | |||
<label>Downpayment: ${{downpayment.toFixed(2)}}</label> | |||
<label v-if="!loan.mi.monthly"> | |||
Mortgage insurance: ${{(loanPayment*loan.mi.rate).toFixed(2)}} | |||
</label> | |||
</section> | |||
<section class="form inputs"> | |||
@@ -24,26 +29,42 @@ | |||
</template> | |||
<script setup> | |||
import { ref } from 'vue' | |||
const props = defineProps(['estimate', 'loans', 'sel']) | |||
const loan = props.loans[props.sel] | |||
const rate = loan.interest / 100 / 12 | |||
const term = loan.term*12 | |||
const loanPayment = loan.amount * | |||
rate*(1+rate)**(term) / | |||
((1+rate)**(term) - 1) | |||
import { ref, computed } from 'vue' | |||
const props = defineProps(['downpayment', 'loan']) | |||
function amortize(principle, rate, periods) { | |||
return principle * rate*(1+rate)**periods / ((1+rate)**periods - 1) | |||
} | |||
const loanPayment = computed(() => amortize(props.loan.amount, | |||
props.loan.interest / 100 / 12, | |||
props.loan.term*12) | |||
) | |||
const totalMonthly = (loanPayment + loan.tax + loan.hoa + loan.hazard).toFixed(2) | |||
const totalMonthly = computed ( | |||
() => (loanPayment.value + | |||
props.loan.tax + | |||
props.loan.hoa + | |||
props.loan.hazard).toFixed(2) | |||
) | |||
// Closing costs | |||
const downpayment = (props.estimate.price - loan.amount).toFixed(2) | |||
const fees = loan.fees.reduce((total, x) => { | |||
return x.amount > 0 ? total + x.amount : 0 | |||
}, 0 | |||
).toFixed(2) | |||
const credits = loan.fees.reduce((total, x) => { | |||
return x.amount < 0 ? total + x.amount : 0 | |||
}, 0 | |||
).toFixed(2) | |||
const fees = computed(() => { | |||
return props.loan.fees.reduce((total, x) => { | |||
return x.amount > 0 ? total + x.amount : 0 | |||
}, 0 | |||
).toFixed(2) | |||
}) | |||
const credits = computed(() => { | |||
return props.loan.fees.reduce((total, x) => { | |||
return x.amount < 0 ? total + x.amount : 0 | |||
}, 0 | |||
).toFixed(2) | |||
}) | |||
const cashToClose = computed(() => { | |||
return fees + credits + downpayment | |||
}) | |||
</script> |