Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

158 lignes
3.7 KiB

  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>