Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

225 líneas
5.4 KiB

  1. <template>
  2. <div id="new" class="page">
  3. <h2>New Loan</h2>
  4. <section class="loans-list">
  5. <h3 v-for="(l, indx) in loans"
  6. :class="sel == indx ? 'sel' : ''"
  7. @click="() => sel = indx"
  8. >
  9. {{l.title}}
  10. </h3>
  11. <div class="add">
  12. <svg @click="create"
  13. xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
  14. class="bi bi-plus" viewBox="0 0 16 16"> <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0
  15. 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/> </svg>
  16. </div>
  17. </section>
  18. <loan-details v-if="hash == '#new'"
  19. :estimate="estimate"
  20. :loans="estimate.loans"
  21. :sel="sel"
  22. :loan="loan"
  23. :token="token"
  24. @update:name="(name) => loans[sel].title = name"
  25. @del="del"
  26. @update:borrowers="(b) => estimate.borrowers = b"
  27. @update:creditScore="(c) => estimate.creditScore = c"
  28. @update:mIncome="(m) => estimate.mIncome = m"
  29. @update:transaction="(t) => estimate.transaction = t"
  30. @update:price="setPrice"
  31. @update:property="(p) => estimate.property = p"
  32. @update:loanType="(lt) => loans[sel].type = lt"
  33. @update:term="(lt) => loans[sel].term = lt"
  34. @update:program="(p) => loans[sel].program = p"
  35. @update:ltv="setLtv"
  36. @update:amount="setAmount"
  37. @update:housingDti="setHousingDti"
  38. @update:dti="setDti"
  39. @update:hoa="(hoa) => loans[sel].hoa = hoa"
  40. @update:interest="(i) => loans[sel].interest = i"
  41. @update:interestDays="(d) => loans[sel].interestDays = d"
  42. @update:hazardEscrow="(h) => loans[sel].hazardEscrow = h"
  43. @update:hazard="(h) => loans[sel].hazard = h"
  44. @update:taxEscrow="(t) => loans[sel].taxEscrow = t"
  45. @update:tax="(t) => loans[sel].tax = t"
  46. @update:manualMI="perc => loans[sel].mi.rate = perc"
  47. @toggle:manualMIMonthly=
  48. "() => loans[sel].mi.monthly = !loans[sel].mi.monthly"
  49. @continue="generate"
  50. />
  51. <loan-summary v-if="hash == '#new/summary'"
  52. :loan="loan" :downpayment="estimate.price - loan.amount"/>
  53. </div>
  54. </template>
  55. <script>
  56. import { stripLetters, strip, stripInt, stripPerc } from "../../helpers.js"
  57. import LoanDetails from "./details.vue"
  58. import LoanSummary from "./summary.vue"
  59. // The default values of a new estimate
  60. const example = {
  61. title: "Example",
  62. type: "",
  63. term: 0,
  64. ltv: 0, // Loan to home value ratio
  65. dti: 0,
  66. housingDti: 0,
  67. amount: 0,
  68. interest: 0,
  69. interestDays: 0,
  70. hazard: 0, // Hazard insurance monthly payment
  71. hazardEscrow: 0, // Hazard insurance escrow in months (0 is none)
  72. tax: 0, // Real Estate taxes monthly payment
  73. taxEscrow: 0, // Months to escrow (0 is none)
  74. hoa: 100, // Home owner's association monthly fee
  75. program: "",
  76. pud: true, // Property under development
  77. zip: '',
  78. fees: [],
  79. mi: { monthly: false, rate: 0 }
  80. }
  81. // The default loans on a new estimate
  82. const loans = [
  83. Object.assign({}, example,),
  84. Object.assign(
  85. Object.assign({}, example),
  86. {title: "Another One", mi: {rate: 0}}
  87. ),
  88. ]
  89. // Default estimate fields
  90. const estimate = {
  91. property: "",
  92. transaction: 0,
  93. price: 0,
  94. borrowers: 0,
  95. creditScore: 0,
  96. mIncome: 0,
  97. loans: loans,
  98. }
  99. function loan() {
  100. return this.estimate.loans[this.sel]
  101. }
  102. // Clone loan from initial example as a new loan
  103. function create() {
  104. this.estimate.loans.push(
  105. Object.assign({}, example, {fees: this.createFees()})
  106. )
  107. }
  108. function createFees() {
  109. return this.fees.map(f => Object.assign({}, f))
  110. }
  111. function del() {
  112. if (this.loans.length > 1) {
  113. let x = this.sel
  114. this.sel = 0
  115. this.loans.splice(x, 1)
  116. }
  117. }
  118. // Updates the property price for all loans and their fee amounts.
  119. function setPrice(value) {
  120. this.estimate.price = value
  121. this.estimate.loans[this.sel].fees.forEach(fee => {
  122. if (fee.perc) fee.amount = (fee.perc / 100 * value).toFixed(2)
  123. })
  124. this.estimate.loans.forEach(l => {l.ltv = 0; l.amount = 0})
  125. }
  126. // Changes loan.ltv's <input> and data() values, then syncs with data.amount
  127. function setLtv(e) {
  128. let ltv = strip(e)
  129. if (!this.estimate.price) return
  130. if (ltv > 100) ltv = 100
  131. if (ltv < 0) ltv = 0
  132. this.loan.ltv = ltv
  133. this.loan.amount = (ltv / 100 * this.estimate.price).toFixed(2)
  134. }
  135. // Changes loan.amount\'s <input> and data() values, then syncs with data.ltv
  136. function setAmount(e) {
  137. let amount = strip(e)
  138. if (!this.estimate.price) return
  139. if (amount > this.loan.price) amount = this.loan.price
  140. if (amount < 0) amount = 0
  141. this.loan.amount = amount
  142. this.loan.ltv = (amount / this.estimate.price * 100).toFixed(2)
  143. }
  144. function setDti(e) {
  145. let dti = strip(e)
  146. let loan = this.loans[this.sel]
  147. if (!loan.price) return
  148. if (dti > 100) dti = 100
  149. if (dti < 0) dti = 0
  150. e.target.value = dti
  151. loan.dti = dti
  152. }
  153. function setHousingDti(e) {
  154. let housingDti = strip(e)
  155. let loan = this.loans[this.sel]
  156. if (!loan.price) return
  157. if (housingDti > 100) housingDti = 100
  158. if (housingDti < 0) housingDti = 0
  159. e.target.value = housingDti
  160. loan.housingDti = housingDti
  161. }
  162. function generate() {
  163. window.location.hash = 'new/summary'
  164. }
  165. // Percentage values of fees always take precedent over amounts. The conversion
  166. // happens in setPrice()
  167. export default {
  168. components: { LoanSummary, LoanDetails },
  169. methods: {
  170. generate, createFees, del, create, setPrice, setLtv, setAmount,
  171. setDti, setHousingDti
  172. },
  173. computed: { loan },
  174. props: ['user', 'fees', 'token'],
  175. data() {
  176. return {
  177. estimate: estimate,
  178. loans: estimate.loans,
  179. sel: 0,
  180. errors: [],
  181. hash: window.location.hash
  182. }
  183. },
  184. created() {
  185. this.estimate.loans.forEach(l => l.fees = this.createFees())
  186. window.addEventListener("hashchange",
  187. () => this.hash = window.location.hash)
  188. }
  189. }
  190. </script>