Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

137 Zeilen
2.7 KiB

  1. <template>
  2. <div id="pdf-doc" ref="doc" v-if="estimate">
  3. <div class="disclaimer"><p>Actual costs may vary from estimates after approval. Get an official quote before choosing a loan.</p></div>
  4. <header class="heading">
  5. <img :src="letterhead" />
  6. <div>
  7. <div class="user-info">
  8. <h4>{{user.firstName + " " + user.lastName}}</h4>
  9. <span>{{user.email}}</span>
  10. <span>{{user.phone}}</span>
  11. <small>{{user.address.street}}</small>
  12. <small>
  13. {{`${user.address.city}, ${user.address.region} ${user.address.zip}`}}
  14. </small>
  15. </div>
  16. <img :src="avatar"/>
  17. </div>
  18. </header>
  19. <button @click="getPdf">Generate</button>
  20. <a :href="pdfLink" v-if="pdfLink" download="estimate.pdf">download </a>
  21. </div>
  22. </template>
  23. <script setup>
  24. import { ref, computed, onMounted } from "vue"
  25. import html2pdf from "html2pdf.js";
  26. const doc = ref(null)
  27. const props = defineProps(['token', 'estimate', 'user'])
  28. const estimate = ref(null)
  29. const estimates = ref(null)
  30. const pdfLink = ref('')
  31. const letterhead = computed(() => {
  32. if (!props.user.letterhead) return null
  33. return URL.createObjectURL(props.user.letterhead)
  34. })
  35. const avatar = computed(() => {
  36. if (!props.user.letterhead) return null
  37. console.log(props.user)
  38. return URL.createObjectURL(props.user.avatar)
  39. })
  40. function makePDF() {
  41. var opt = {
  42. image: { type: 'png', quality: 1 },
  43. }
  44. html2pdf(doc.value, opt)
  45. }
  46. function getEstimates() {
  47. return fetch(`/api/estimates`,
  48. {method: 'GET',
  49. headers: {
  50. "Accept": "application/json",
  51. "Authorization": `Bearer ${props.token}`,
  52. },
  53. }).then(response => {
  54. if (response.ok) { return response.json() } else {
  55. response.text().then(t => console.log(t))
  56. }
  57. }).then (result => {
  58. if (!result || !result.length) return // Exit if token is invalid or no fees are saved
  59. estimates.value = result
  60. // console.log(result)
  61. })
  62. }
  63. function getPdf() {
  64. fetch(`/api/pdf`,
  65. {method: 'GET',
  66. headers: {
  67. "Accept": "application/json",
  68. "Authorization": `Bearer ${props.token}`,
  69. },
  70. }).then(response => {
  71. if (response.ok) { return response.blob() }
  72. else {
  73. return null
  74. }
  75. }).then (result => {
  76. if (!result) return
  77. pdfLink.value = URL.createObjectURL(result)
  78. })
  79. }
  80. onMounted(() => {
  81. getEstimates().then(() => estimate.value = estimates.value[0])
  82. })
  83. </script>
  84. <style scoped>
  85. #pdf-doc {
  86. margin: 4px 30px;
  87. }
  88. .disclaimer {
  89. font-weight: bold;
  90. border-bottom: 1px solid lightgrey;
  91. margin-bottom: 20px;
  92. color: var(--text);
  93. }
  94. .disclaimer p {
  95. margin: 5px 0;
  96. }
  97. h4 {
  98. margin: 4px 0;
  99. }
  100. header.heading {
  101. display: flex;
  102. justify-content: space-between;
  103. }
  104. .user-info {
  105. display: flex;
  106. flex-flow: column;
  107. }
  108. #pdf-doc header.heading > div {
  109. display: flex;
  110. gap: 8px;
  111. text-align: right;
  112. }
  113. </style>