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.
 
 
 
 
 
 

202 lines
4.6 KiB

  1. <template>
  2. <div class="panel">
  3. <template v-if="user">
  4. <side-bar v-if="user" :role="user && user.status" :active="active">
  5. </side-bar>
  6. <div v-if="loading" class="page loading">
  7. <span class="error" >{{loadingError}}</span>
  8. <spinner></spinner>
  9. </div>
  10. <home :user="user" v-else-if="active == 1" />
  11. <new-estimate :user="user" :fees="fees" v-else-if="active == 2" />
  12. <estimates :user="user" :fees="fees" v-else-if="active == 3" />
  13. <settings :user="user" v-else-if="active == 4" />
  14. <sign-out :user="user" v-else-if="active == 5" />
  15. </template>
  16. <template v-if="!user && active == 6">
  17. <login @login="start" />
  18. </template>
  19. </div>
  20. </template>
  21. <script>
  22. import SideBar from "./sidebar.vue"
  23. import Spinner from "./spinner.vue"
  24. import Home from "./home.vue"
  25. import NewEstimate from "./new.vue"
  26. import Estimates from "./estimates.vue"
  27. import Settings from "./settings.vue"
  28. import SignOut from "./sign-out.vue"
  29. import Login from "./login.vue"
  30. function getCookie(name) {
  31. var re = new RegExp(name + "=([^;]+)")
  32. var value = re.exec(document.cookie)
  33. return (value != null) ? unescape(value[1]) : null
  34. }
  35. function refreshToken() {
  36. const token = getCookie("skouter")
  37. fetch(`/api/token`,
  38. {method: 'GET',
  39. headers: {
  40. "Accept": "application/json",
  41. "Authorization": `Bearer ${token}`,
  42. },
  43. }).then(response => {
  44. if (!response.ok) {
  45. console.log("Error refreshing token.")
  46. }
  47. })
  48. // Recursive refresh
  49. setTimeout(this.refreshToken, 1000*60*25)
  50. }
  51. function getUser() {
  52. const token = getCookie("skouter")
  53. return fetch(`/api/user`,
  54. {method: 'GET',
  55. headers: {
  56. "Accept": "application/json",
  57. "Authorization": `Bearer ${token}`,
  58. },
  59. }).then(response => {
  60. if (response.ok) {
  61. return response.json()
  62. } else {
  63. // Redirect to login if starting token is invalid
  64. window.location.hash = '#login'
  65. }
  66. }).then (result => {
  67. if (!result || !result.length) return // Exit if token is invalid
  68. this.user = result[0]
  69. })
  70. }
  71. function getFees() {
  72. const token = getCookie("skouter")
  73. return fetch(`/api/fees`,
  74. {method: 'GET',
  75. headers: {
  76. "Accept": "application/json",
  77. "Authorization": `Bearer ${token}`,
  78. },
  79. }).then(response => {
  80. if (response.ok) { return response.json() }
  81. }).then (result => {
  82. if (!result || !result.length) return // Exit if token is invalid or no fees are saved
  83. this.fees = result
  84. })
  85. }
  86. // The default fees of a new loan. Percentage values take precedent over amounts
  87. const fees = [
  88. { name: 'Processing fee', type: 'Lender Fees', amount: 500, perc: 0 },
  89. { name: 'Underwriting fee', type: 'Lender Fees', amount: 500, perc: 0 },
  90. { name: 'Credit Report', type: 'Services Required by Lender',
  91. amount: 52.50 },
  92. { name: 'Appraisal', type: 'Services Required by Lender', amount: 52.50 },
  93. { name: 'Title Services', type: 'Title Company', amount: 1000 },
  94. { name: 'Lender\'s Title Insurance', type: 'Title Company', amount: 1599 },
  95. { name: 'Owner\'s Title Insurance', type: 'Title Company', amount: 451.00 },
  96. { name: 'Recording Charges', type: 'Government', amount: 99.00 },
  97. { name: 'State Tax', type: 'Government', amount: 2411.00 },
  98. ]
  99. // Used to check the current section of the app generally without a regex match
  100. // each time.
  101. function active() {
  102. if (this.hash == '' || this.hash == '#') {
  103. return 1
  104. } else if (/^#new\/?/.exec(this.hash)) {
  105. return 2
  106. } else if (/^#estimates\/?/.exec(this.hash)) {
  107. return 3
  108. } else if (/^#settings\/?/.exec(this.hash)) {
  109. return 4
  110. } else if (/^#sign-out\/?/.exec(this.hash)) {
  111. return 5
  112. } else if (/^#login\/?/.exec(this.hash)) {
  113. return 6
  114. } else {
  115. return 0
  116. }
  117. }
  118. // Fetch data before showing UI. If requests fail, assume token is expired.
  119. function start() {
  120. this.loading = true
  121. let loaders = []
  122. loaders.push(this.getUser())
  123. loaders.push(this.getFees())
  124. Promise.all(loaders).then((a, b) => {
  125. this.loading = false
  126. if (!b) {
  127. // Time untill token expiration may have elapsed before the page
  128. // reloaded
  129. this.refreshToken()
  130. }
  131. }).catch(error => {
  132. console.log("An error occured %O", error)
  133. this.loadingError = "Could not initialize app."
  134. window.location.hash = 'login'
  135. })
  136. }
  137. export default {
  138. components: {
  139. SideBar,
  140. Spinner,
  141. Home,
  142. NewEstimate,
  143. Estimates,
  144. Settings,
  145. SignOut,
  146. Login
  147. },
  148. computed: { active },
  149. methods: {
  150. getCookie,
  151. start,
  152. getUser,
  153. getFees,
  154. refreshToken,
  155. },
  156. data() {
  157. return {
  158. loading: true,
  159. user: null,
  160. hash: window.location.hash,
  161. fees: [],
  162. loadingError: "",
  163. }
  164. },
  165. created() {
  166. window.onhashchange = () => this.hash = window.location.hash
  167. this.token = this.getCookie("skouter")
  168. if (!this.token) {
  169. window.location.hash = 'login'
  170. this.loading = false
  171. return
  172. }
  173. this.start()
  174. }
  175. }
  176. </script>