@@ -225,7 +225,19 @@ function start() { | |||||
} | } | ||||
function downloadEstimate(estimate) { | function downloadEstimate(estimate) { | ||||
fetch(`/api/pdf`, | |||||
{method: 'POST', | |||||
body: JSON.stringify(estimate), | |||||
headers: { | |||||
"Accept": "application/json", | |||||
"Authorization": `Bearer ${this.token}`, | |||||
}, | |||||
}).then(response => { | |||||
if (response.ok) { return response.blob() } | |||||
}).then (result => { | |||||
console.log(result) | |||||
if (!result) return // Exit if token is invalid or blank file returned | |||||
}) | |||||
} | } | ||||
export default { | export default { | ||||
@@ -0,0 +1,27 @@ | |||||
<template> | |||||
<Dialog @close="$emit('close')"> | |||||
<h3>'{{fname}}' ready</h3> | |||||
<div class="row"><a :href="props.url" :download="fname"> | |||||
<button>Download</button> | |||||
</a></div> | |||||
</Dialog> | |||||
</template> | |||||
<script setup> | |||||
import { computed } from "vue" | |||||
import Dialog from "./dialog.vue" | |||||
const emit = defineEmits(['close']) | |||||
const props = defineProps(['fileName', 'url']) | |||||
let fname = props.fileName | |||||
</script> | |||||
<style scoped> | |||||
.modal div.row { | |||||
display: flex; | |||||
justify-content: center; | |||||
} | |||||
</style> |
@@ -54,18 +54,23 @@ ${{(estimate.price / 100).toLocaleString()}} | |||||
<label>Total monthly: ${{format(l.result.totalMonthly)}}</label> | <label>Total monthly: ${{format(l.result.totalMonthly)}}</label> | ||||
<label>Cash to close: ${{format(l.result.cashToClose)}}</label> | <label>Cash to close: ${{format(l.result.cashToClose)}}</label> | ||||
</div> | </div> | ||||
<button @click="() => $emit('download', estimate)">Download</button> | |||||
<button @click="() => download(estimate)">PDF</button> | |||||
<button @click="() => estimate = null">Cancel</button> | <button @click="() => estimate = null">Cancel</button> | ||||
</div> | </div> | ||||
</section> | </section> | ||||
<DDialog v-if="dlink" @close="() => dlink = ''" | |||||
:fileName="`estimate-${estimate.id}.pdf`" :url="dlink"> | |||||
</DDialog> | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script setup> | <script setup> | ||||
import { ref, computed, onMounted } from 'vue' | import { ref, computed, onMounted } from 'vue' | ||||
import FeeDialog from "./fee-dialog.vue" | import FeeDialog from "./fee-dialog.vue" | ||||
import DDialog from "./download-dialog.vue" | |||||
import { format } from "../helpers.js" | import { format } from "../helpers.js" | ||||
const props = defineProps(['user', 'fees', 'token']) | const props = defineProps(['user', 'fees', 'token']) | ||||
@@ -73,6 +78,7 @@ const emit = defineEmits(['addFeeTemp', 'removeFeeTemp', 'preview']) | |||||
let edit = ref(null) | let edit = ref(null) | ||||
let estimates = ref([]) | let estimates = ref([]) | ||||
let estimate = ref() | let estimate = ref() | ||||
let dlink = ref("") | |||||
function newFee(fee, isDebit) { | function newFee(fee, isDebit) { | ||||
if (!isDebit) { | if (!isDebit) { | ||||
@@ -156,7 +162,30 @@ function summarize() { | |||||
} | } | ||||
function download(estimate) { | |||||
fetch(`/api/pdf`, | |||||
{method: 'POST', | |||||
body: JSON.stringify(estimate), | |||||
headers: { | |||||
"Accept": "application/json", | |||||
"Authorization": `Bearer ${props.token}`, | |||||
}, | |||||
}).then(response => { | |||||
if (response.ok) { return response.blob() } | |||||
}).then (result => { | |||||
if (!result) return // Exit if token is invalid or blank file returned | |||||
dlink.value = URL.createObjectURL(result) | |||||
}) | |||||
} | |||||
onMounted(() => { | onMounted(() => { | ||||
getEstimates() | getEstimates() | ||||
}) | }) | ||||
</script> | </script> | ||||
<style scoped> | |||||
.modal a.button { | |||||
margin: auto; | |||||
margin-top: 30px; | |||||
} | |||||
</style> |
@@ -2268,7 +2268,10 @@ func clipLetterhead(w http.ResponseWriter, db *sql.DB, r *http.Request) { | |||||
// claims, err := getClaims(r) | // claims, err := getClaims(r) | ||||
if err != nil { http.Error(w, "Invalid token.", 422); return } | if err != nil { http.Error(w, "Invalid token.", 422); return } | ||||
img, t, err := image.Decode(r.Body) | img, t, err := image.Decode(r.Body) | ||||
if err != nil { http.Error(w, "Invalid file.", 422); return } | |||||
if err != nil { | |||||
http.Error(w, "Invalid file, JPEG and PNG only.", 422) | |||||
return | |||||
} | |||||
for _, v := range validTypes { | for _, v := range validTypes { | ||||
if v == "image/"+t { isValidType = true } | if v == "image/"+t { isValidType = true } | ||||
} | } | ||||
@@ -2646,8 +2649,8 @@ func seedEstimates(db *sql.DB, users []User, ltypes []LoanType) []Estimate { | |||||
estimates = append(estimates, estimate) | estimates = append(estimates, estimate) | ||||
} | } | ||||
estimate[0].User = users[0].Id | |||||
estimate[1].User = users[0].Id | |||||
estimates[0].User = users[0].Id | |||||
estimates[1].User = users[0].Id | |||||
for i := range estimates { | for i := range estimates { | ||||
err = estimates[i].insertEstimate(db) | err = estimates[i].insertEstimate(db) | ||||