Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

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