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