Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

summary.vue 2.7 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <template>
  2. <div v-if="valid">
  3. <section class="form inputs">
  4. <h3>Monthly Payment - ${{format(totalMonthly)}}</h3>
  5. <label>Loan payment: ${{format(loanPayment)}}</label>
  6. <label v-if="loan.mi.monthly">
  7. Mortgage insurance: ${{format(loan.amount*loan.mi.rate/100/12)}}
  8. </label>
  9. <label>Property taxes: ${{format(loan.tax)}}</label>
  10. <label>Homeowner's Insurance: ${{format(loan.hoa)}}</label>
  11. </section>
  12. <section class="form inputs">
  13. <h3>Cash to Close - ${{format(cashToClose)}}</h3>
  14. <label>Closing costs: ${{format(fees)}}</label>
  15. <label v-if="credits">Credits: ${{credits}}</label>
  16. <label>Down payment: ${{format(downpayment)}}</label>
  17. <label v-if="!loan.mi.monthly">
  18. Mortgage insurance: ${{format(loan.amount*loan.mi.rate/100)}}
  19. </label>
  20. </section>
  21. <section class="form inputs">
  22. <button>Save Estimate</button>
  23. <button>Generate PDF</button>
  24. </section>
  25. </div>
  26. </template>
  27. <script setup>
  28. import { ref, computed, onMounted } from 'vue'
  29. let valid = ref(false)
  30. const props = defineProps(['downpayment', 'loan', 'token', 'estimate'])
  31. function amortize(principle, rate, periods) {
  32. return principle * rate*(1+rate)**periods / ((1+rate)**periods - 1)
  33. }
  34. const loanPayment = computed(() => {
  35. let amount = props.loan.amount
  36. return amortize(props.loan.amount,
  37. props.loan.interest / 100 / 12,
  38. props.loan.term*12)
  39. })
  40. const totalMonthly = computed (() => {
  41. let total = loanPayment.value +
  42. props.loan.tax +
  43. props.loan.hoa +
  44. props.loan.hazard
  45. if (props.loan.mi.monthly) {
  46. total = total + props.loan.mi.rate/100*(props.loan.amount)
  47. }
  48. return total
  49. })
  50. // Closing costs
  51. const fees = computed(() => {
  52. return props.loan.fees.reduce((total, x) => {
  53. return x.amount > 0 ? total + x.amount : 0
  54. }, 0
  55. )
  56. })
  57. const credits = computed(() => {
  58. return props.loan.fees.reduce((total, x) => {
  59. return x.amount < 0 ? total + x.amount : 0
  60. }, 0
  61. )
  62. })
  63. const cashToClose = computed(() => {
  64. let total = fees.value + credits.value + props.downpayment
  65. if (!props.loan.mi.monthly) {
  66. total = total + props.loan.mi.rate/100*(props.loan.amount)
  67. }
  68. return total
  69. })
  70. function validate() {
  71. fetch(`/api/estimate/validate`,
  72. {method: 'POST',
  73. body: JSON.stringify(props.estimate),
  74. headers: {
  75. "Accept": "application/json",
  76. "Authorization": `Bearer ${props.token}`,
  77. },
  78. }).then(resp => {
  79. if (resp.ok && resp.status == 200) {
  80. valid.value = true
  81. return
  82. } else {
  83. // resp.text().then(t => this.errors = [t])
  84. // window.location.hash = 'new'
  85. }
  86. })
  87. }
  88. // Print number of cents as a nice string of dollars
  89. function format(num) {
  90. return (num/100).toFixed(2)
  91. }
  92. onMounted(() => {validate()})
  93. </script>