Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

294 linhas
7.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. <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 = strip(e)">
  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. <label>Interest Rate (%)</label>
  98. <input :value="loans[sel].interest" @input="setInterest">
  99. <label>Days of Interest</label>
  100. <input :value="loans[sel].interestDays" @input="setInterestDays">
  101. <label>Hazard Insurance Escrowed?</label>
  102. <input type="checkbox" :value="loans[sel].hazardEscrowed" @input="">
  103. <label>Months to Escrow Hazard Insurance</label>
  104. <input :value="loans[sel].hazardMonths" @input="">
  105. <label>Hazard Insurance ($/monthly)</label>
  106. <input :value="loans[sel].hazard" @input="setHazard">
  107. <label>Taxes Escrowed?</label>
  108. <input type="checkbox" :value="loans[sel].taxEscrowed" @input="">
  109. <label>Months to Escrow Real Estate Tax</label>
  110. <input :value="loans[sel].taxEscrow" @input="">
  111. <label>Real Estate Tax ($/monthly)</label>
  112. <input :value="loans[sel].tax" @input="setTax">
  113. </section>
  114. <section class="form inputs">
  115. <h3>Interest Rates</h3>
  116. <label>Loan Term (years)</label>
  117. <input :value="loans[sel].term"
  118. @input="(e) => loans[sel].term = strip(e)">
  119. <label>Loan Program</label>
  120. <select id="" name="" v-model="loans[sel].program">
  121. <option value="none">None</option>
  122. </select>
  123. <label>Loan to Value (%)</label>
  124. <input :value="loans[sel].ltv" @input="setLtv">
  125. <label>Loan Amount ($)</label>
  126. <input :value="loans[sel].amount"
  127. @input="setAmount">
  128. <label>Housing Expense DTI (%) - Optional</label>
  129. <input :value="loans[sel].housingDti" @input="setHousingDti">
  130. <label>Total DTI (%) - Optional</label>
  131. <input :value="loans[sel].dti" @input="setDti">
  132. </section>
  133. </div>
  134. </template>
  135. <script>
  136. const example = {
  137. title: "Example",
  138. type: "",
  139. term: 0,
  140. ltv: 0, // Loan to home value ratio
  141. dti: 0,
  142. housingDti: 0,
  143. amount: 0,
  144. interest: 0,
  145. interestDays: 0,
  146. hazard: 0, // Hazard insurance monthly payment
  147. hazardMonths: 0, // Hazard insurance months
  148. hazardEscrowed: true, // If hazard insurance is escrowed
  149. tax: 0, // Real Estate taxes monthly payment
  150. taxEscrow: 0, // Months to escrow
  151. taxEscrowed: true, // If tax is escrowed
  152. program: "",
  153. pud: true, // Property under development
  154. zip: ''
  155. }
  156. const loans = [
  157. Object.assign({}, example),
  158. Object.assign(Object.assign({}, example), {title: "Another One"})
  159. ]
  160. const estimate = {
  161. property: "",
  162. transaction: 0,
  163. price: 0,
  164. borrowers: 0,
  165. creditScore: 0,
  166. mIncome: 0,
  167. loans: loans
  168. }
  169. // Clone loan from initial example as a new loan
  170. function create() {
  171. this.estimate.loans.push(Object.assign({}, loans[0]))
  172. }
  173. // Strips non-digits from an input box event and returns it's rounded integer
  174. function strip(e) {
  175. let value = parseInt(e.target.value.replace(/\D/g, '') || 0)
  176. e.target.value = value
  177. return value
  178. }
  179. function stripLetters(e) {
  180. let value = (e.target.value.replace(/[^\w\s]/g, '').slice(0, 20) || '')
  181. e.target.value = value
  182. return value
  183. }
  184. function del() {
  185. if (this.loans.length > 1) {
  186. let x = this.sel
  187. this.sel = 0
  188. this.loans.splice(x, 1)
  189. }
  190. }
  191. // Changes loan.ltv's <input> and data() values, then syncs with data.amount
  192. function setLtv(e) {
  193. let ltv = strip(e)
  194. let loan = this.loans[this.sel]
  195. if (!this.estimate.price) return
  196. if (ltv > 100) ltv = 100
  197. if (ltv < 0) ltv = 0
  198. loan.ltv = ltv
  199. e.target.value = ltv
  200. loan.amount = Math.round(ltv / 100 * this.estimate.price)
  201. }
  202. // Changes loan.amount's <input> and data() values, then syncs with data.ltv
  203. function setAmount(e) {
  204. let amount = strip(e)
  205. let loan = this.loans[this.sel]
  206. if (!this.estimate.price) return
  207. if (amount > loan.price) amount = loan.price
  208. if (amount < 0) amount = 0
  209. loan.amount = amount
  210. e.target.value = amount
  211. loan.ltv = Math.round(amount / this.estimate.price * 100)
  212. }
  213. // Updates the property price for all loans
  214. function setPrice(e) {
  215. let value = strip(e)
  216. this.estimate.price = value
  217. e.target.value = value
  218. }
  219. function setDti(e) {
  220. let dti = strip(e)
  221. let loan = this.loans[this.sel]
  222. if (!loan.price) return
  223. if (dti > 100) dti = 100
  224. if (dti < 0) dti = 0
  225. e.target.value = dti
  226. loan.dti = dti
  227. }
  228. function setHousingDti(e) {
  229. let housingDti = strip(e)
  230. let loan = this.loans[this.sel]
  231. if (!loan.price) return
  232. if (housingDti > 100) housingDti = 100
  233. if (housingDti < 0) housingDti = 0
  234. e.target.value = housingDti
  235. loan.housingDti = housingDti
  236. }
  237. export default {
  238. methods: {
  239. setPrice, setLtv, setAmount, setDti, setHousingDti,
  240. strip, stripLetters, del, create
  241. },
  242. props: ['user'],
  243. data() {
  244. return {
  245. estimate: estimate,
  246. loans: estimate.loans,
  247. sel: 0,
  248. }
  249. }
  250. }
  251. </script>