Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

253 lines
5.7 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. <section class="form inputs">
  19. <h3>Loan</h3>
  20. <label>Name</label>
  21. <input :value="loans[sel].title"
  22. @input="(e) => loans[sel].title = stripLetters(e)">
  23. <button @click="del">Delete</button>
  24. </section>
  25. <section class="form inputs">
  26. <div class="hint">
  27. <img class="icon" src="/assets/image/icon/question-circle.svg" alt="">
  28. <div class="tooltip">
  29. <p>Assumes borrower is not self employed, not bankrupt in the past 7
  30. years, a citizen, and intends to occupy the property.</p>
  31. </div>
  32. </div>
  33. <h3>Borrower</h3>
  34. <label>Number of Borrowers</label>
  35. <input :value="estimate.borrowers"
  36. @input="(e) => estimate.borrowers = strip(e)">
  37. <label>Credit Score</label>
  38. <input :value="estimate.creditScore"
  39. @input="(e) => estimate.creditScore = strip(e)">
  40. <label>Monthly Income ($)</label>
  41. <input :value="estimate.mIncome"
  42. @input="(e) => estimate.mIncome = strip(e)">
  43. </section>
  44. <section class="radios form">
  45. <h3>Transaction Type</h3>
  46. <input type="radio" name="transaction_type" value="transaction"
  47. @input="e => estimate.transaction = 0"
  48. selected="estimate.transaction == 0">
  49. <label>Purchase</label>
  50. <input type="radio" name="transaction_type" value="refinance"
  51. @input="e => estimate.transaction = 1"
  52. selected="estimate.transaction == 1">
  53. <label>Refinance</label>
  54. </section>
  55. <section class="form inputs">
  56. <h3>Property Details</h3>
  57. <label>Price ($)</label>
  58. <input :value="estimate.price" @input="setPrice">
  59. <label>Type</label>
  60. <select id="" name="" v-model="estimate.property">
  61. <option value="attched">Single Family Attached</option>
  62. <option value="detached">Single Family Detached</option>
  63. <option value="lorise">Lo-rise (4 stories or less)</option>
  64. <option value="hirise">Hi-rise (over 4 stories)</option>
  65. </select>
  66. </section>
  67. <section class="radios form">
  68. <h3>Loan Type</h3>
  69. <input type="radio" name="loan_type" value="conv" v-model="loans[sel].type"
  70. >
  71. <label>Conventional</label>
  72. <input type="radio" name="loan_type" value="fha" v-model="loans[sel].type">
  73. <label>FHA</label>
  74. <input type="radio" name="loan_type" value="va" v-model="loans[sel].type">
  75. <label>VA</label>
  76. <input type="radio" name="loan_type" value="usda" v-model="loans[sel].type">
  77. <label>USDA</label>
  78. </section>
  79. <section class="form inputs">
  80. <h3>Loan Details</h3>
  81. <label>Loan Term (years)</label>
  82. <input :value="loans[sel].term"
  83. @input="(e) => loans[sel].term = parseInt(e.target.value.replace(/[^0-9]/g, ''))">
  84. <label>Loan Program</label>
  85. <select id="" name="" v-model="loans[sel].program">
  86. <option value="none">None</option>
  87. </select>
  88. <label>Loan to Value (%)</label>
  89. <input :value="loans[sel].ltv" @input="setLtv">
  90. <label>Loan Amount ($)</label>
  91. <input :value="loans[sel].amount"
  92. @input="setAmount">
  93. <label>Housing Expense DTI (%) - Optional</label>
  94. <input :value="loans[sel].housingDti" @input="setHousingDti">
  95. <label>Total DTI (%) - Optional</label>
  96. <input :value="loans[sel].dti" @input="setDti">
  97. </section>
  98. </div>
  99. </template>
  100. <script>
  101. const loans = [
  102. {
  103. title: "Loan Example",
  104. type: "",
  105. term: 0,
  106. ltv: 0,
  107. dti: 0,
  108. housingDti: 0,
  109. amount: 0,
  110. program: "",
  111. pud: false,
  112. zip: ''
  113. },
  114. {
  115. title: "Another One",
  116. type: "",
  117. term: 0,
  118. ltv: 0,
  119. dti: 0,
  120. housingDti: 0,
  121. amount: 0,
  122. program: "",
  123. pud: true,
  124. zip: ''
  125. }
  126. ]
  127. const estimate = {
  128. property: "",
  129. transaction: 0,
  130. price: 0,
  131. borrowers: 0,
  132. creditScore: 0,
  133. mIncome: 0,
  134. loans: loans
  135. }
  136. // Clone loan from initial example as a new loan
  137. function create() {
  138. this.estimate.loans.push(Object.assign({}, loans[0]))
  139. }
  140. // Strips non-digits from an input box event and returns it's rounded integer
  141. function strip(e) {
  142. let value = parseInt(e.target.value.replace(/\D/g, '') || 0)
  143. e.target.value = value
  144. return value
  145. }
  146. function stripLetters(e) {
  147. let value = (e.target.value.replace(/[^\w\s]/g, '').slice(0, 20) || '')
  148. e.target.value = value
  149. return value
  150. }
  151. function del() {
  152. if (this.loans.length > 1) {
  153. let x = this.sel
  154. this.sel = 0
  155. this.loans.splice(x, 1)
  156. }
  157. }
  158. function setLtv(e) {
  159. let ltv = strip(e)
  160. let loan = this.loans[this.sel]
  161. if (!this.estimate.price) return
  162. if (ltv > 100) ltv = 100
  163. if (ltv < 0) ltv = 0
  164. loan.ltv = ltv
  165. e.target.value = ltv
  166. loan.amount = Math.round(ltv / 100 * this.estimate.price)
  167. }
  168. function setAmount(e) {
  169. let amount = strip(e)
  170. let loan = this.loans[this.sel]
  171. if (!this.estimate.price) return
  172. if (amount > loan.price) amount = loan.price
  173. if (amount < 0) amount = 0
  174. loan.amount = amount
  175. e.target.value = amount
  176. loan.ltv = Math.round(amount / this.estimate.price * 100)
  177. }
  178. // Updates the property price for all loans
  179. function setPrice(e) {
  180. let value = strip(e)
  181. this.estimate.price = value
  182. e.target.value = value
  183. }
  184. function setDti(e) {
  185. let dti = strip(e)
  186. let loan = this.loans[this.sel]
  187. if (!loan.price) return
  188. if (dti > 100) dti = 100
  189. if (dti < 0) dti = 0
  190. e.target.value = dti
  191. loan.dti = dti
  192. }
  193. function setHousingDti(e) {
  194. let housingDti = strip(e)
  195. let loan = this.loans[this.sel]
  196. if (!loan.price) return
  197. if (housingDti > 100) housingDti = 100
  198. if (housingDti < 0) housingDti = 0
  199. e.target.value = housingDti
  200. loan.housingDti = housingDti
  201. }
  202. export default {
  203. methods: {
  204. setPrice, setLtv, setAmount, setDti, setHousingDti,
  205. strip, stripLetters, del, create
  206. },
  207. props: ['user'],
  208. data() {
  209. return {
  210. estimate: estimate,
  211. loans: estimate.loans,
  212. sel: 0,
  213. }
  214. }
  215. }
  216. </script>