Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

228 rindas
5.5 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:borrowerNum="(b) => estimate.borrower.num = b"
  27. @update:borrowerCredit="(c) => estimate.borrower.credit = c"
  28. @update:borrowerIncome="(m) => estimate.borrower.income = 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}, type: {}}
  87. ),
  88. ]
  89. // Default estimate fields
  90. const estimate = {
  91. property: "",
  92. transaction: 0,
  93. price: 0,
  94. borrower: {num: 0, credit: 0, income: 0},
  95. loans: loans,
  96. }
  97. function loan() {
  98. return this.estimate.loans[this.sel]
  99. }
  100. // Clone loan from initial example as a new loan
  101. function create() {
  102. this.estimate.loans.push(
  103. Object.assign(
  104. {},
  105. example, {fees: this.createFees()}
  106. )
  107. )
  108. }
  109. function createFees() {
  110. return this.fees.map(f => Object.assign({}, f))
  111. }
  112. function del() {
  113. if (this.loans.length > 1) {
  114. let x = this.sel
  115. this.sel = 0
  116. this.loans.splice(x, 1)
  117. }
  118. }
  119. // Updates the property price for all loans and their fee amounts.
  120. function setPrice(value) {
  121. this.estimate.price = value
  122. this.estimate.loans[this.sel].fees.forEach(fee => {
  123. if (fee.perc) fee.amount = (fee.perc / 100 * value).toFixed(2)
  124. })
  125. this.estimate.loans.forEach(l => {l.ltv = 0; l.amount = 0})
  126. }
  127. // Changes loan.ltv's <input> and data() values, then syncs with data.amount
  128. function setLtv(e) {
  129. let ltv = strip(e)
  130. if (!this.estimate.price) return
  131. if (ltv > 100) ltv = 100
  132. if (ltv < 0) ltv = 0
  133. this.loan.ltv = ltv
  134. let num = ltv / 100 * this.estimate.price
  135. this.loan.amount = Math.round(num*100) / 100
  136. }
  137. // Changes loan.amount\'s <input> and data() values, then syncs with data.ltv
  138. function setAmount(e) {
  139. let amount = strip(e)
  140. if (!this.estimate.price) return
  141. if (amount > this.loan.price) amount = this.loan.price
  142. if (amount < 0) amount = 0
  143. this.loan.amount = amount
  144. let num = amount / this.estimate.price * 100
  145. this.loan.ltv = Math.round(num*100) / 100
  146. }
  147. function setDti(e) {
  148. let dti = strip(e)
  149. let loan = this.loans[this.sel]
  150. if (!loan.price) return
  151. if (dti > 100) dti = 100
  152. if (dti < 0) dti = 0
  153. e.target.value = dti
  154. loan.dti = dti
  155. }
  156. function setHousingDti(e) {
  157. let housingDti = strip(e)
  158. let loan = this.loans[this.sel]
  159. if (!loan.price) return
  160. if (housingDti > 100) housingDti = 100
  161. if (housingDti < 0) housingDti = 0
  162. e.target.value = housingDti
  163. loan.housingDti = housingDti
  164. }
  165. function generate() {
  166. window.location.hash = 'new/summary'
  167. }
  168. // Percentage values of fees always take precedent over amounts. The conversion
  169. // happens in setPrice()
  170. export default {
  171. components: { LoanSummary, LoanDetails },
  172. methods: {
  173. generate, createFees, del, create, setPrice, setLtv, setAmount,
  174. setDti, setHousingDti
  175. },
  176. computed: { loan },
  177. props: ['user', 'fees', 'token'],
  178. data() {
  179. return {
  180. estimate: estimate,
  181. loans: estimate.loans,
  182. sel: 0,
  183. errors: [],
  184. hash: window.location.hash
  185. }
  186. },
  187. created() {
  188. this.estimate.loans.forEach(l => l.fees = this.createFees())
  189. window.addEventListener("hashchange",
  190. () => this.hash = window.location.hash)
  191. }
  192. }
  193. </script>