Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
 
 
 
 
 
 

190 行
4.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 xmlns="http://www.w3.org/2000/svg" width="16" height="16"
  13. fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16"> <path d="M8 4a.5.5 0
  14. 0 1 .5.5v3h3a.5.5 0 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
  15. 0 1 8 4z"/> </svg>
  16. </div>
  17. </section>
  18. <section class="radios form">
  19. <h3>Transaction Type</h3>
  20. <input type="radio" name="transaction_type" value="transaction"
  21. @input="e => loans[sel].transaction = 0"
  22. selected="loans[sel].transaction == 0">
  23. <label>Purchase</label>
  24. <input type="radio" name="transaction_type" value="refinance"
  25. @input="e => loans[sel].transaction = 1"
  26. selected="loans[sel].transaction == 1">
  27. <label>Refinance</label>
  28. </section>
  29. <section class="form">
  30. <h3>Property Details</h3>
  31. <label>Price ($)</label>
  32. <input :value="loans[sel].price" @input="setPrice">
  33. <label>Type</label>
  34. <select id="" name="" v-model="loans[sel].property">
  35. <option value="attched">Single Family Attached</option>
  36. <option value="detached">Single Family Detached</option>
  37. <option value="lorise">Lo-rise (4 stories or less)</option>
  38. <option value="hirise">Hi-rise (over 4 stories)</option>
  39. </select>
  40. <label></label>
  41. </section>
  42. <section class="radios form">
  43. <h3>Loan Type</h3>
  44. <input type="radio" name="loan_type" value="conv" v-model="loans[sel].type"
  45. >
  46. <label>Conventional</label>
  47. <input type="radio" name="loan_type" value="fha" v-model="loans[sel].type">
  48. <label>FHA</label>
  49. <input type="radio" name="loan_type" value="va" v-model="loans[sel].type">
  50. <label>VA</label>
  51. <input type="radio" name="loan_type" value="usda" v-model="loans[sel].type">
  52. <label>USDA</label>
  53. </section>
  54. <section class="form">
  55. <h3>Loan Details</h3>
  56. <label>Loan Term (years)</label>
  57. <input :value="loans[sel].term"
  58. @input="(e) => loans[sel].term = parseInt(e.target.value.replace(/[^0-9]/g, ''))">
  59. <label>Loan Program</label>
  60. <select id="" name="" v-model="loans[sel].program">
  61. <option value="none">None</option>
  62. </select>
  63. <label>Loan to Value (%)</label>
  64. <input :value="loans[sel].ltv" @input="setLtv">
  65. <label>Loan Amount ($)</label>
  66. <input :value="loans[sel].amount"
  67. @input="setAmount">
  68. <label>Housing Expense DTI (%)</label>
  69. <input :value="loans[sel].housingDti" @input="setHousingDti">
  70. <label>Total DTI (%)</label>
  71. <input :value="loans[sel].dti" @input="setDti">
  72. </section>
  73. </div>
  74. </template>
  75. <script>
  76. function setLtv(e) {
  77. let ltv = parseInt(e.target.value.replace(/[^0-9]/g, '') || 0)
  78. let loan = this.loans[this.sel]
  79. if (!loan.price) return
  80. if (ltv > 100) ltv = 100
  81. if (ltv < 0) ltv = 0
  82. loan.ltv = ltv
  83. loan.amount = Math.round(ltv / 100 * loan.price)
  84. }
  85. function setAmount(e) {
  86. let amount = parseInt(e.target.value.replace(/[^0-9]/g, '') || 0)
  87. let loan = this.loans[this.sel]
  88. if (!loan.price) return
  89. if (amount > loan.price) amount = loan.price
  90. if (amount < 0) amount = 0
  91. loan.amount = amount
  92. loan.ltv = Math.round(amount / loan.price * 100)
  93. }
  94. function setPrice(e) {
  95. let loan = this.loans[this.sel]
  96. let value =
  97. parseInt(e.target.value.replace(/[^0-9]/g, ''))
  98. // Should check for NaN after backspace
  99. loan.price = value
  100. loan.amount = Math.round(loan.ltv / 100 * value)
  101. }
  102. function setDti(e) {
  103. let dti = parseInt(e.target.value.replace(/[^0-9]/g, '') || 0)
  104. let loan = this.loans[this.sel]
  105. if (!loan.price) return
  106. if (dti > 100) dti = 100
  107. if (dti < 0) dti = 0
  108. loan.dti = dti
  109. }
  110. function setHousingDti(e) {
  111. let housingDti = parseInt(e.target.value.replace(/[^0-9]/g, '') || 0)
  112. let loan = this.loans[this.sel]
  113. if (!loan.price) return
  114. if (housingDti > 100) housingDti = 100
  115. if (housingDti < 0) housingDti = 0
  116. loan.housingDti = housingDti
  117. }
  118. const loans = [
  119. {
  120. title: "Loan Example",
  121. property: "",
  122. transaction: 0,
  123. type: "",
  124. price: 0,
  125. term: 0,
  126. ltv: 0,
  127. dti: 0,
  128. housingDti: 0,
  129. amount: 0,
  130. program: "",
  131. pud: false,
  132. zip: ''
  133. },
  134. {
  135. title: "Another One",
  136. property: "",
  137. transaction: 0,
  138. type: "",
  139. price: 0,
  140. term: 0,
  141. ltv: 0,
  142. dti: 0,
  143. housingDti: 0,
  144. program: "",
  145. pud: true,
  146. zip: ''
  147. }
  148. ]
  149. const propertyTypes = [
  150. ]
  151. export default {
  152. methods: {
  153. setPrice, setLtv, setAmount, setDti, setHousingDti
  154. },
  155. props: ['user'],
  156. data() {
  157. return {
  158. loans: loans, sel: 0, loan: loans[0],
  159. }
  160. }
  161. }
  162. </script>