Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

settings.vue 3.7 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <template>
  2. <div class="page settings">
  3. <h2>Settings</h2>
  4. <section class="form inputs">
  5. <h3>Avatar</h3>
  6. <canvas class="displayer" width="200" height="200" ref="avatar"></canvas>
  7. <input type="file"
  8. @change="e => changeAvatar(e.target.files[0])"
  9. />
  10. <button @click="uploadAvatar">Upload</button>
  11. <label class="error">{{avatarError}}</label>
  12. </section>
  13. <section class="form inputs letterhead">
  14. <h3>Letterhead</h3>
  15. <canvas class="displayer" height="200" ref="letterhead"></canvas>
  16. <input type="file"
  17. @change="e => changeLetterhead(e.target.files[0])"
  18. />
  19. <button @click="uploadLetterhead">Upload</button>
  20. <label class="error">{{avatarError}}</label>
  21. </section>
  22. <section class="form inputs special">
  23. <h3>Profile</h3>
  24. <label for="">First Name</label>
  25. <input type="text">
  26. <label for="">Last Name</label>
  27. <input type="text">
  28. <label for="">NMLS ID</label>
  29. <input type="text">
  30. <label for="">Branch ID</label>
  31. <input type="text">
  32. <select id="" name="" >
  33. <option value="usa">USA</option>
  34. <option value="canada">Canada</option>
  35. </select>
  36. <button @click="check">Save</button>
  37. </section>
  38. <section class="form inputs special">
  39. <h3>Login</h3>
  40. <label for="">Email</label>
  41. <input type="text">
  42. <label for="">New Password</label>
  43. <input type="text">
  44. <button @click="check">Save</button>
  45. </section>
  46. <Dialog v-if="ready" @close="() => ready = false">
  47. <h3>Confirm your current password to save changes.</h3>
  48. <input type="text">
  49. <button>Confirm</button>
  50. </Dialog>
  51. </div>
  52. </template>
  53. <script setup>
  54. import { ref, watch, onMounted } from "vue"
  55. import Dialog from "./dialog.vue"
  56. let avatar = ref(null) // the canvas element
  57. let letterhead = ref(null) // the canvas element
  58. let ready = ref(false)
  59. let avatarChanged = ref(false)
  60. let avatarError = ref('')
  61. let letterheadError = ref('')
  62. const props = defineProps(['user', 'token'])
  63. const emit = defineEmits(['updateAvatar', 'updateLetterhead'])
  64. function save() {
  65. }
  66. function check() {
  67. ready.value = true
  68. }
  69. function uploadAvatar() {
  70. avatar.value.toBlob(b => {
  71. fetch(`/api/user/avatar`,
  72. {method: 'POST',
  73. body: b,
  74. headers: {
  75. "Accept": "application/json",
  76. "Authorization": `Bearer ${props.token}`,
  77. },
  78. }).then(resp => {
  79. if (resp.ok) {emit('updateAvatar')}
  80. })
  81. })
  82. }
  83. function uploadLetterhead() {
  84. letterhead.value.toBlob(b => {
  85. fetch(`/api/user/letterhead`,
  86. {method: 'POST',
  87. body: b,
  88. headers: {
  89. "Accept": "application/json",
  90. "Authorization": `Bearer ${props.token}`,
  91. },
  92. }).then(resp => {
  93. if (resp.ok) {emit('updateLetterhead')}
  94. })
  95. })
  96. }
  97. function changeAvatar(blob) {
  98. const validTypes = ['image/jpeg', 'image/png']
  99. if (!validTypes.includes(blob.type)) {
  100. avatarError.value = 'Image must be JPEG of PNG format'
  101. return
  102. }
  103. avatarError.value = ''
  104. createImageBitmap(blob,
  105. {resizeWidth: 200, resizeHeight: 200, resizeQuality: 'medium'}).
  106. then((img) => {
  107. avatar.value.getContext("2d").drawImage(img, 0, 0, 200, 200)
  108. })
  109. }
  110. function changeLetterhead(blob) {
  111. const validTypes = ['image/jpeg', 'image/png']
  112. if (!validTypes.includes(blob.type)) {
  113. letterheadError.value = 'Image must be JPEG of PNG format'
  114. return
  115. }
  116. letterheadError.value = ''
  117. return createImageBitmap(blob,
  118. {resizeWidth: 400, resizeHeight: 200, resizeQuality: 'medium'}).
  119. then((img) => {
  120. letterhead.value.getContext("2d").drawImage(img, 0, 0, 400, 200)
  121. })
  122. }
  123. watch(props.user, (u) => {
  124. if (props.user.avatar) {
  125. changeAvatar(props.user.avatar)
  126. }
  127. if (props.user.letterhead) {
  128. changeLetterhead(props.user.letterhead)
  129. }
  130. }, {immediate: true})
  131. </script>