Skouter mortgage estimates. Web application with view written in PHP and Vue, but controller and models in Go.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

138 líneas
2.8 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: 'POST',
  66. body: JSON.stringify(estimate.value),
  67. headers: {
  68. "Accept": "application/json",
  69. "Authorization": `Bearer ${props.token}`,
  70. },
  71. }).then(response => {
  72. if (response.ok) { return response.blob() }
  73. else {
  74. return null
  75. }
  76. }).then (result => {
  77. if (!result) return
  78. pdfLink.value = URL.createObjectURL(result)
  79. })
  80. }
  81. onMounted(() => {
  82. getEstimates().then(() => estimate.value = estimates.value[0])
  83. })
  84. </script>
  85. <style scoped>
  86. #pdf-doc {
  87. margin: 4px 30px;
  88. }
  89. .disclaimer {
  90. font-weight: bold;
  91. border-bottom: 1px solid lightgrey;
  92. margin-bottom: 20px;
  93. color: var(--text);
  94. }
  95. .disclaimer p {
  96. margin: 5px 0;
  97. }
  98. h4 {
  99. margin: 4px 0;
  100. }
  101. header.heading {
  102. display: flex;
  103. justify-content: space-between;
  104. }
  105. .user-info {
  106. display: flex;
  107. flex-flow: column;
  108. }
  109. #pdf-doc header.heading > div {
  110. display: flex;
  111. gap: 8px;
  112. text-align: right;
  113. }
  114. </style>