diff options
author | Vidhu Kant Sharma <vidhukant@vidhukant.com> | 2024-04-06 10:26:44 +0530 |
---|---|---|
committer | Vidhu Kant Sharma <vidhukant@vidhukant.com> | 2024-04-06 10:26:44 +0530 |
commit | 63823d41addec00556a93eabffa455630d169ca6 (patch) | |
tree | 2b548e2a6b00ae7ef3859e4a4cb807329a62a4a2 /src/components | |
parent | a26ab9f60314420aad1c7d2a328d299f503532fa (diff) |
added basic (and incomplete) print preview template
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/InvoiceHeaderEditor.vue (renamed from src/components/invoice_header_editor.vue) | 28 | ||||
-rw-r--r-- | src/components/PrintPreview.vue | 31 | ||||
-rw-r--r-- | src/components/PrintPreviewHeader.vue | 99 | ||||
-rw-r--r-- | src/components/PrintPreviewItemsList.vue | 59 | ||||
-rw-r--r-- | src/components/PrintPreviewRecipientDetails.vue | 146 | ||||
-rw-r--r-- | src/components/invoice_header.vue | 1 |
6 files changed, 363 insertions, 1 deletions
diff --git a/src/components/invoice_header_editor.vue b/src/components/InvoiceHeaderEditor.vue index 83c5281..6fe8a25 100644 --- a/src/components/invoice_header_editor.vue +++ b/src/components/InvoiceHeaderEditor.vue @@ -4,6 +4,7 @@ import { useRouter } from 'vue-router' import axios from 'axios' import { useToast } from 'vue-toast-notification' import Customer from "./../classes/customer" +import User from "./../classes/user" const toast = useToast({ position: 'top-right' @@ -16,6 +17,7 @@ const submitting = ref(false) // shows spinner on continue button const allCustomers = ref([]) const customer = ref(new Customer()) +const user = ref(new User()) const customerSelection = ref(null) const invoiceDate = ref(new Date().toISOString().substr(0, 10)) @@ -36,12 +38,31 @@ const getAllCustomers = async () => { gettingData.value = false } +const getUser = async () => { + user.value = new User() + gettingData.value = true + + try { + const r = await axios.get('/user') + if (r.status === 200) { + user.value = r.data.data + } + } catch (err) { + toast.error('An unhandled exception occoured. Please check logs') + console.error(err) + } + + gettingData.value = false + console.log(user) +} + const submit = async (e: Event) => { e.preventDefault() submitting.value = true try { const c = toRaw(customer.value) + const u = toRaw(user.value) const res = await axios.post('/invoice', { "invoicedate": new Date(toRaw(invoiceDate.value)).toISOString(), @@ -68,6 +89,12 @@ const submit = async (e: Event) => { "customerphone": c.Phone, "customeremail": c.Email, "customerwebsite": c.Website, + "issuerfirmname": u.FirmName, + "issuerfirmaddress": u.AddressText, + "issuerfirmgstin": u.Gstin, + "issuerfirmphone": u.Phone, + "issuerfirmemail": u.Email, + "issuerfirmwebsite": u.Website, }) route.push({ name: "edit-invoice", params: { id: res.data.data.ID }}) @@ -110,6 +137,7 @@ const refreshCustomer = async () => { } onMounted(() => { + getUser() getAllCustomers() }) </script> diff --git a/src/components/PrintPreview.vue b/src/components/PrintPreview.vue new file mode 100644 index 0000000..ecbda88 --- /dev/null +++ b/src/components/PrintPreview.vue @@ -0,0 +1,31 @@ +<script setup lang="ts"> + import PrintPreviewHeader from './PrintPreviewHeader.vue' + import PrintPreviewRecipientDetails from './PrintPreviewRecipientDetails.vue' + import PrintPreviewItemsList from './PrintPreviewItemsList.vue' + + const props = defineProps(["invoice"]) + + setTimeout(() => { + console.log(props.invoice) + }, 1000) +</script> + +<template> + <div class="print-preview"> + <PrintPreviewHeader + :invoice="props.invoice" /> + <PrintPreviewRecipientDetails + :invoice="props.invoice"/> + <PrintPreviewItemsList + :items="props.invoice.Items"/> + </div> +</template> + +<style> +.print-preview * { + font-size: 9pt; +} +.print-preview p { + margin: 0; +} +</style> diff --git a/src/components/PrintPreviewHeader.vue b/src/components/PrintPreviewHeader.vue new file mode 100644 index 0000000..33f82f2 --- /dev/null +++ b/src/components/PrintPreviewHeader.vue @@ -0,0 +1,99 @@ +<script setup lang="ts"> + const props = defineProps(["invoice"]) +</script> + +<template> + <div class="print-preview-header"> + <div class="logo-container"> + <img src="../assets/placeholderlogo.png"/> + </div> + + <div> + <div class="firm-name"> + <p>{{ props.invoice.IssuerFirmName }}</p> + </div> + <div class="firm-address"> + {{ props.invoice.IssuerFirmAddress }} + </div> + </div> + + <div class="header-col3"> + <div class="firm-contact"> + <div class="label"> + <span><strong>Phone:</strong></span> + <span>{{ props.invoice.IssuerFirmPhone }}</span> + </div> + <div class="label"> + <span><strong>Email:</strong></span> + <span>{{ props.invoice.IssuerFirmEmail }}</span> + </div> + <div class="label"> + <span><strong>Website:</strong></span> + <span>{{ props.invoice.IssuerFirmWebsite }}</span> + </div> + <div class="label"> + <span><strong>GSTIN:</strong></span> + <span>{{ props.invoice.IssuerFirmGstin }}</span> + </div> + </div> + <div class="qr-container"> + <img src="../assets/placeholderqr.png"/> + </div> + </div> + </div> +</template> + +<style> +.print-preview-header { + display: grid; + grid-template-columns: 1.7in 2.4in auto; + grid-column-gap: 1em; + width: 100%; + margin-bottom: 1em; +} +.logo-container { + display: flex; + justify-content: center; + align-items: flex-start; + max-width: 1.7in; +} +.logo-container img { + max-width: 100%; + max-height: 100%; +} +.firm-name { + height: 2em; +} +.firm-name p { + line-height: 0.8em; + font-size: 1.6em; + font-weight: bold; +} +.firm-address { + font-size: 0.9em; + line-height: 1.2em; + white-space: pre-wrap; +} +.header-col3 { + display: grid; + grid-template-columns: auto 0.8in; +} +.firm-contact { + display: flex; + flex-direction: column; + font-size: 0.9em; +} +.firm-contact .label { + display: grid; + grid-template-columns: 4.5em auto; +} +.qr-container { + display: flex; + justify-content: flex-end; + align-items: flex-start; + width: 100%; +} +.qr-container img { + max-width: 100%; +} +</style> diff --git a/src/components/PrintPreviewItemsList.vue b/src/components/PrintPreviewItemsList.vue new file mode 100644 index 0000000..72f0fc1 --- /dev/null +++ b/src/components/PrintPreviewItemsList.vue @@ -0,0 +1,59 @@ +<script setup lang="ts"> + const props = defineProps(["items"]) +</script> + +<template> + <div class="items-list-wrapper"> + <div class="items-list-header"> + <div class="cell">#</div> + <div class="cell">Item Name</div> + <div class="cell">HSN</div> + <div class="cell">Qty</div> + <div class="cell">Unit Price</div> + <div class="cell">Discount</div> + <div class="cell">Taxable Value</div> + <div class="cell">GST</div> + <div class="cell">Total</div> + </div> + <div class="item-list"> + <div v-for="(item, index) in props.items" :key="item['id']" class="item-list-row"> + <div class="cell">{{ index + 1 }}</div> + <div class="cell">{{ item.Name }}</div> + <div class="cell">{{ item.HSN }}</div> + <div class="cell">1</div> + <div class="cell">100</div> + <div class="cell">0</div> + <div class="cell">10</div> + <div class="cell">18</div> + <div class="cell">1000</div> + </div> + </div> + </div> +</template> + +<style> +.items-list-wrapper { + margin-top: 1em; + border-top: 1px solid gray; + border-left: 1px solid gray; +} +.cell { + border-right: 1px solid gray; + border-bottom: 1px solid gray; +} +.items-list-header, .item-list-row { + display: grid; + grid-template-columns: 0.3in 2in 0.5in 0.5in 0.5in 0.6in 0.77in 1.5in 0.6in; +} +.items-list-header .cell { + font-weight: bold; + text-align: center; + display: flex; + align-items: center; + justify-content: center; +} +.item-list { + display: flex; + flex-direction: column; +} +</style> diff --git a/src/components/PrintPreviewRecipientDetails.vue b/src/components/PrintPreviewRecipientDetails.vue new file mode 100644 index 0000000..6f1f5b7 --- /dev/null +++ b/src/components/PrintPreviewRecipientDetails.vue @@ -0,0 +1,146 @@ +<script setup lang="ts"> + const props = defineProps(["invoice"]) +</script> + +<template> + <div class="print-preview-recipient-info"> + <div class="recipient-info--row1"> + <div class="recipient-info--col1"> + </div> + <div class="recipient-info--col2"> + <span class="invoice-label"> + <span><strong>INVOICE</strong></span> + <span>Original for Recipient</span> + </span> + </div> + </div> + <div class="recipient-info--row2"> + <div class="recipient-info--col1 recipient-contact"> + <div class="label"> + <span><strong>Bill To</strong></span> + <span>{{ props.invoice.CustomerName }}</span> + </div> + <div class="label"> + <span><strong>Address</strong></span> + <span> + {{ props.invoice.BillingAddress.AddressText }}<br> + {{ props.invoice.BillingAddress.City }} + ({{ props.invoice.BillingAddress.PostalCode }}), + {{ props.invoice.BillingAddress.State }}, + {{ props.invoice.BillingAddress.Country }} + </span> + </div> + <div class="label"> + <span><strong>Contact</strong></span> + <span>{{ props.invoice.CustomerContactName }}</span> + </div> + <div class="label"> + <span><strong>Phone</strong></span> + <span>{{ props.invoice.CustomerPhone }}</span> + </div> + <div class="label"> + <span><strong>Email</strong></span> + <span>{{ props.invoice.CustomerEmail }}</span> + </div> + <div class="label"> + <span><strong>Website</strong></span> + <span>{{ props.invoice.CustomerWebsite }}</span> + </div> + <div class="label"> + <span><strong>GSTIN</strong></span> + <span>{{ props.invoice.CustomerGstin }}</span> + </div> + </div> + <div class="recipient-info--col2"> + <div class="invoice-meta"> + <div class="label"> + <span><strong>Invoice Number: </strong></span> + <span>{{ props.invoice.InvoiceNumber }}</span> + </div> + <div class="label"> + <span><strong>Invoice Date: </strong></span> + <span>{{ new Date(props.invoice.InvoiceDate).toLocaleDateString() }}</span> + </div> + </div> + <div class="shipping-address"> + <div class="label"> + <span><strong>Shipping Address</strong></span> + <span> + {{ props.invoice.ShippingAddress.AddressText }}<br> + {{ props.invoice.ShippingAddress.City }} + ({{ props.invoice.ShippingAddress.PostalCode }}), + {{ props.invoice.ShippingAddress.State }}, + {{ props.invoice.ShippingAddress.Country }} + </span> + + <span><strong>City</strong></span> + <span>{{ props.invoice.ShippingAddress.City }}</span> + + <span><strong>State</strong></span> + <span>{{ props.invoice.ShippingAddress.State }}</span> + + <span><strong>ZIP Code</strong></span> + <span>{{ props.invoice.ShippingAddress.PostalCode }}</span> + + <span><strong>Country</strong></span> + <span>{{ props.invoice.ShippingAddress.Country }}</span> + </div> + </div> + </div> + </div> + </div> +</template> + +<style> +.print-preview-recipient-info { + border: 1px solid gray; + display: grid; + grid-template-rows: 2em auto; + width: 100%; +} +.recipient-info--row1, +.recipient-info--row2 { + display: grid; + grid-template-columns: 3fr 4fr; +} +.recipient-info--row1 { + border-bottom: 1px solid gray; +} +.recipient-info--col1 { + border-right: 1px solid gray; +} +.recipient-info--col1 { + padding: 0.1em 0.3em; +} +.invoice-label { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 0.3em; +} +.recipient-contact { + display: flex; + flex-direction: column; +} +.recipient-contact .label { + display: grid; + grid-template-columns: 5em auto; +} +.invoice-meta { + width: 100%; + border-bottom: 1px solid gray; + padding: 0.3em 0.3em; + display: grid; + grid-template-columns: 1fr 1fr; +} +.invoice-meta .label, .shipping-address .label { + display: grid; + grid-template-columns: 9em auto; +} +.shipping-address { + width: 100%; + padding: 0.1em 0.3em; +} +</style> diff --git a/src/components/invoice_header.vue b/src/components/invoice_header.vue index 5a57fc8..fe35980 100644 --- a/src/components/invoice_header.vue +++ b/src/components/invoice_header.vue @@ -1,5 +1,4 @@ <script setup lang="ts"> -import { defineProps } from 'vue' const props = defineProps(["invoice"]) </script> |