diff --git a/frontend/src/App.vue b/frontend/src/App.vue index c8c3abf..28ed6f0 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,5 +1,6 @@ diff --git a/frontend/src/components/orders/PdfDownloadButton.vue b/frontend/src/components/orders/PdfDownloadButton.vue new file mode 100644 index 0000000..efcc5bf --- /dev/null +++ b/frontend/src/components/orders/PdfDownloadButton.vue @@ -0,0 +1,44 @@ + + + diff --git a/frontend/src/composables/usePdf.js b/frontend/src/composables/usePdf.js new file mode 100644 index 0000000..6ff5bae --- /dev/null +++ b/frontend/src/composables/usePdf.js @@ -0,0 +1,34 @@ +const API_URL = import.meta.env.VITE_API_URL || '/api' + +export function usePdf() { + function getToken() { + return localStorage.getItem('token') + } + + async function downloadPdf(url, filename) { + const token = getToken() + const res = await fetch(`${API_URL}${url}`, { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }) + if (!res.ok) throw new Error('Eroare la descarcarea PDF-ului') + const blob = await res.blob() + const objectUrl = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = objectUrl + a.download = filename + document.body.appendChild(a) + a.click() + document.body.removeChild(a) + URL.revokeObjectURL(objectUrl) + } + + async function downloadDevizPdf(orderId, nrComanda) { + await downloadPdf(`/orders/${orderId}/pdf/deviz`, `deviz-${nrComanda || orderId}.pdf`) + } + + async function downloadInvoicePdf(invoiceId, nrFactura) { + await downloadPdf(`/invoices/${invoiceId}/pdf`, `factura-${nrFactura || invoiceId}.pdf`) + } + + return { downloadDevizPdf, downloadInvoicePdf } +} diff --git a/frontend/src/layouts/AppLayout.vue b/frontend/src/layouts/AppLayout.vue index 985c67d..e5e51f7 100644 --- a/frontend/src/layouts/AppLayout.vue +++ b/frontend/src/layouts/AppLayout.vue @@ -88,6 +88,7 @@ const mobileMenuOpen = ref(false) const navItems = [ { path: '/dashboard', label: 'Dashboard' }, { path: '/orders', label: 'Comenzi' }, + { path: '/invoices', label: 'Facturi' }, { path: '/vehicles', label: 'Vehicule' }, { path: '/appointments', label: 'Programari' }, { path: '/catalog', label: 'Catalog' }, diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index c275e3c..84694c8 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -13,8 +13,9 @@ const router = createRouter({ { path: '/vehicles', component: () => import('../views/vehicles/VehiclesListView.vue'), meta: { requiresAuth: true } }, { path: '/appointments', component: () => import('../views/appointments/AppointmentsView.vue'), meta: { requiresAuth: true } }, { path: '/catalog', component: () => import('../views/catalog/CatalogView.vue'), meta: { requiresAuth: true } }, + { path: '/invoices', component: () => import('../views/orders/InvoicesView.vue'), meta: { requiresAuth: true } }, { path: '/settings', component: () => import('../views/settings/SettingsView.vue'), meta: { requiresAuth: true } }, - { path: '/p/:token', component: () => import('../views/client/DevizPublicView.vue') }, + { path: '/p/:token', component: () => import('../views/client/DevizPublicView.vue'), meta: { layout: 'none' } }, { path: '/', redirect: '/dashboard' }, ], scrollBehavior: () => ({ top: 0 }) diff --git a/frontend/src/views/client/DevizPublicView.vue b/frontend/src/views/client/DevizPublicView.vue index 495306c..d592ba0 100644 --- a/frontend/src/views/client/DevizPublicView.vue +++ b/frontend/src/views/client/DevizPublicView.vue @@ -1,6 +1,207 @@ + + diff --git a/frontend/src/views/orders/InvoicesView.vue b/frontend/src/views/orders/InvoicesView.vue new file mode 100644 index 0000000..a9af6d1 --- /dev/null +++ b/frontend/src/views/orders/InvoicesView.vue @@ -0,0 +1,76 @@ + + + diff --git a/frontend/src/views/orders/OrderDetailView.vue b/frontend/src/views/orders/OrderDetailView.vue index 7b01327..b55cfa8 100644 --- a/frontend/src/views/orders/OrderDetailView.vue +++ b/frontend/src/views/orders/OrderDetailView.vue @@ -6,6 +6,13 @@

{{ order.nr_comanda }}

+