Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

221 lignes
5.3 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. @update:name="(name) => loans[sel].title = name"
  23. @del="del"
  24. @update:borrowers="(b) => estimate.borrowers = b"
  25. @update:creditScore="(c) => estimate.creditScore = c"
  26. @update:mIncome="(m) => estimate.mIncome = m"
  27. @update:transaction="(t) => estimate.transaction = t"
  28. @update:price="(p) => estimate.price = p"
  29. @update:property="(p) => estimate.property = p"
  30. @update:loanType="(lt) => loans[sel].type = lt"
  31. @update:term="(lt) => loans[sel].term = lt"
  32. @update:program="(p) => loans[sel].program = p"
  33. @update:ltv="setLtv"
  34. @update:amount="setAmount"
  35. @update:housingDti="setHousingDti"
  36. @update:dti="setDti"
  37. @update:hoa="(hoa) => loans[sel].hoa = hoa"
  38. @update:interest="(i) => loans[sel].interest = i"
  39. @update:interestDays="(d) => loans[sel].interestDays = d"
  40. @update:hazardEscrow="(h) => loans[sel].hazardEscrow = h"
  41. @update:hazard="(h) => loans[sel].hazard = h"
  42. @update:taxEscrow="(t) => loans[sel].taxEscrow = t"
  43. @update:tax="(t) => loans[sel].tax = t"
  44. @update:manualMI="perc => loans[sel].mi.rate = perc"
  45. @toggle:manualMIMonthly=
  46. "() => loans[sel].mi.monthly = !loans[sel].mi.monthly"
  47. @continue="generate"
  48. />
  49. <loan-summary v-if="hash == '#new/summary'"
  50. :estimate="estimate"
  51. :loans="estimate.loans"
  52. :sel="sel" />
  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",}
  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. // Clone loan from initial example as a new loan
  100. function create() {
  101. this.estimate.loans.push(
  102. Object.assign({}, example, {fees: this.createFees()})
  103. )
  104. }
  105. function createFees() {
  106. return this.fees.map(f => Object.assign({}, f))
  107. }
  108. function del() {
  109. if (this.loans.length > 1) {
  110. let x = this.sel
  111. this.sel = 0
  112. this.loans.splice(x, 1)
  113. }
  114. }
  115. // Updates the property price for all loans and their fee amounts.
  116. function setPrice(value) {
  117. this.estimate.price = value
  118. this.estimate.loans[this.sel].fees.forEach(fee => {
  119. if (fee.perc) fee.amount = (fee.perc / 100 * value).toFixed(2)
  120. })
  121. this.estimate.loans.forEach(l => {l.ltv = 0; l.amount = 0})
  122. }
  123. // Changes loan.ltv's <input> and data() values, then syncs with data.amount
  124. function setLtv(e) {
  125. let ltv = strip(e)
  126. let loan = this.loans[this.sel]
  127. if (!this.estimate.price) return
  128. if (ltv > 100) ltv = 100
  129. if (ltv < 0) ltv = 0
  130. loan.ltv = ltv
  131. loan.amount = (ltv / 100 * this.estimate.price).toFixed(2)
  132. }
  133. // Changes loan.amount\'s <input> and data() values, then syncs with data.ltv
  134. function setAmount(e) {
  135. let amount = strip(e)
  136. let loan = this.loans[this.sel]
  137. if (!this.estimate.price) return
  138. if (amount > loan.price) amount = loan.price
  139. if (amount < 0) amount = 0
  140. loan.amount = amount
  141. loan.ltv = (amount / this.estimate.price * 100).toFixed(2)
  142. }
  143. function setDti(e) {
  144. let dti = strip(e)
  145. let loan = this.loans[this.sel]
  146. if (!loan.price) return
  147. if (dti > 100) dti = 100
  148. if (dti < 0) dti = 0
  149. e.target.value = dti
  150. loan.dti = dti
  151. }
  152. function setHousingDti(e) {
  153. let housingDti = strip(e)
  154. let loan = this.loans[this.sel]
  155. if (!loan.price) return
  156. if (housingDti > 100) housingDti = 100
  157. if (housingDti < 0) housingDti = 0
  158. e.target.value = housingDti
  159. loan.housingDti = housingDti
  160. }
  161. function generate() {
  162. window.location.hash = 'new/summary'
  163. }
  164. // Percentage values of fees always takek precedent over amounts. The conversion
  165. // happens in setPrice()
  166. export default {
  167. components: { LoanSummary, LoanDetails },
  168. methods: {
  169. generate, createFees, del, create, setPrice, setLtv, setAmount,
  170. setDti, setHousingDti
  171. },
  172. props: ['user', 'fees'],
  173. data() {
  174. return {
  175. estimate: estimate,
  176. loans: estimate.loans,
  177. sel: 0,
  178. errors: [],
  179. hash: window.location.hash
  180. }
  181. },
  182. created() {
  183. this.estimate.loans.forEach(l => l.fees = this.createFees())
  184. window.addEventListener("hashchange", () => this.hash = window.location.hash)
  185. }
  186. }
  187. </script>