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.

пре 8 месеци
пре 8 месеци
пре 8 месеци
пре 8 месеци
пре 8 месеци
пре 8 месеци
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. <template>
  2. <form>
  3. <div>
  4. <label>Given name</label>
  5. <input required type="text" name="gname" v-model="user.firstName"/>
  6. </div>
  7. <div>
  8. <label>Surname</label>
  9. <input required type="text" name="sname" v-model="user.lastName"/>
  10. </div>
  11. <div>
  12. <label>Email</label>
  13. <input type="email" name="email" v-model="user.email"/>
  14. </div>
  15. <div>
  16. <label>Title</label>
  17. <select name="country" v-model="user.title">
  18. <option value="Loan Officer">Loan Officer</option>
  19. <option value="Mortgage Broker">Mortgage Broker</option>
  20. <option value="Executive">Executive</option>
  21. <option value="Other">Other</option>
  22. </select>
  23. </div>
  24. <div>
  25. <label>Password</label>
  26. <input requried type="password" name="pass" v-model="user.password"/>
  27. </div>
  28. <div>
  29. <label>Country</label>
  30. <select name="country" v-model="user.country">
  31. <option value="USA">USA</option>
  32. <option value="Canada">Canada</option>
  33. </select>
  34. </div>
  35. <div class="address-entry">
  36. <label for="">Address</label>
  37. <input
  38. type="text" @input="searchLocation" v-model="address.full">
  39. <dropdown v-if="addresses && addresses.length"
  40. :entries="addresses.map(a => ({text: a.full_address, value: a}))"
  41. @select="setAddress"
  42. >
  43. </dropdown>
  44. </div>
  45. <div><label>NMLS ID</label><input type="text" name="nmls"/></div>
  46. <div id="newsletter">
  47. <label>Monthly Newsletter</label>
  48. <input type="checkbox" name="newsletter" v-model="user.newsletter"/>
  49. </div>
  50. <div><span class="error">{{err}}</span></div>
  51. <div>
  52. <button class="btn" @click="submit" type="button">Continue</button>
  53. </div>
  54. </form>
  55. </template>
  56. <script setup>
  57. import { ref } from "vue"
  58. import Dropdown from "./dropdown.vue"
  59. const addresses = ref([])
  60. const user = ref({country: "USA", title: "Loan Officer", newsletter: true})
  61. const address = ref({})
  62. const locationsId = ref(null)
  63. const props = defineProps(['err'])
  64. const emit = defineEmits(['submit'])
  65. function searchLocation(e) {
  66. address.value.full = e.target.value
  67. clearTimeout(locationsId.value)
  68. locationsId.value = setTimeout(getLocations, 1000, e)
  69. }
  70. function getLocations(e) {
  71. let prefix = "https://api.mapbox.com/search/searchbox/v1/suggest?"
  72. let search = e.target.value
  73. let key = encodeURIComponent(process.env.MAPBOX_API_KEY)
  74. if (!search) return
  75. fetch(`${prefix}q=${search}&proximity=ip&access_token=${key}&session_token=1`
  76. ).then(resp => resp.json()).then(entries => {
  77. if (!entries?.suggestions) {
  78. addresses.value = null
  79. return
  80. }
  81. addresses.value = entries.suggestions.filter(e => e.full_address)
  82. })
  83. }
  84. function setAddress(a) {
  85. address.value = {
  86. id: address.value.id,
  87. full: a.full_address,
  88. street: a.address,
  89. city: a.context?.place.name ?? '',
  90. region: a.context?.region?.name ?? '',
  91. country: a.context?.country?.name ?? '',
  92. zip: a.context?.postcode?.name ?? '',
  93. }
  94. addresses.value = null
  95. }
  96. function submit() {
  97. user.value.address = address.value
  98. emit('submit', user.value)
  99. }
  100. </script>
  101. <style scoped>
  102. form > div {
  103. display: flex;
  104. justify-content: space-between;
  105. margin: 10px;
  106. position: relative;
  107. }
  108. button {
  109. margin: auto;
  110. min-width: 90px;
  111. display: block;
  112. }
  113. span.error {
  114. margin: 10px auto;
  115. color: darkred;
  116. }
  117. div#newsletter {
  118. justify-content: normal;
  119. gap: 30px;
  120. }
  121. </style>