Move REST calls from invoice table to invoice dialog, fixes #56

This commit is contained in:
2025-11-18 20:46:40 +01:00
parent eda81628e5
commit 250c4538aa
4 changed files with 270 additions and 203 deletions
+28 -78
View File
@@ -2,6 +2,7 @@
import { computed, ref, onMounted } from 'vue'
import { type Invoice } from '@/types'
import { newInvoice } from '@/types/index.d'
import axios from 'axios'
import AppLayout from '@/layouts/AppLayout.vue'
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from '@/components/ui/select'
@@ -41,7 +42,7 @@ onMounted(async () => {
let queryString = window.location.search
let params = new URLSearchParams(queryString)
if (params.get('action') == 'new') editInvoice()
if (params.get('action') == 'new') createInvoice()
searchField.value = document.getElementById('search')
})
@@ -92,89 +93,37 @@ const filteredInvoices = computed(() => {
});
});
const editInvoice = (invoice?: Invoice) => {
const createInvoice = () => {
editInvoice(newInvoice())
}
const editInvoice = (invoice: Invoice) => {
// make a deep copy, so the changes in the dialog wont affect the data until saved
activeInvoice.value = invoice ? JSON.parse(JSON.stringify(invoice)) : null
activeInvoice.value = JSON.parse(JSON.stringify(invoice))
detailDialogOpen.value = true
}
const saveInvoice = async (updatedInvoice: Invoice) => {
try {
// Prepare the invoice data for API request
const invoiceToSave = {
nr: updatedInvoice.nr,
invoiceDate: updatedInvoice.invoiceDate,
dueDate: updatedInvoice.dueDate,
serviceStartDate: updatedInvoice.serviceStartDate,
serviceEndDate: updatedInvoice.serviceEndDate,
isRecurring: updatedInvoice.isRecurring,
isPartialService: updatedInvoice.isPartialService,
paymentStatus: updatedInvoice.paymentStatus,
totalAmount: updatedInvoice.totalAmount,
title: updatedInvoice.title,
text: updatedInvoice.text,
customerId: updatedInvoice.customer ? updatedInvoice.customer.id : null,
billingData: {
companyName: updatedInvoice.billingData?.companyName,
vatId: updatedInvoice.billingData?.vatId,
billingAddress: updatedInvoice.billingData?.billingAddress,
contactSalutation: updatedInvoice.billingData?.contactSalutation,
contactFirstName: updatedInvoice.billingData?.contactFirstName,
contactLastName: updatedInvoice.billingData?.contactLastName,
paymentTerms: updatedInvoice.billingData?.paymentTerms
},
const onSaveInvoice = async (updatedInvoice: Invoice) => {
// Update selectedYearIndex to ensure the new invoice is displayed
const newInvoiceYear = new Date(updatedInvoice.invoiceDate).getFullYear();
const currentYearIndex = years.value.findIndex(year => year === newInvoiceYear);
if (currentYearIndex !== -1) {
selectedYearIndex.value = currentYearIndex;
}
// Items will be handled separately in the controller
items: updatedInvoice.items.map(item => ({
id: item.id, // Include ID for existing items
position: item.position,
type: item.type,
title: item.title,
description: item.description,
quantity: item.quantity,
unit: item.unit,
price: item.price
}))
};
// console.log('Saving invoice:', invoiceToSave);
if (updatedInvoice.id === 0) {
// Create new invoice
const response = await axios.post('/api/invoices', invoiceToSave);
invoicesData.value.push(response.data);
// Update selectedYearIndex to ensure the new invoice is displayed
const newInvoiceYear = new Date(response.data.invoiceDate).getFullYear();
const currentYearIndex = years.value.findIndex(year => year === newInvoiceYear);
if (currentYearIndex !== -1) {
selectedYearIndex.value = currentYearIndex;
}
} else {
// Update existing invoice
const response = await axios.put(`/api/invoices/${updatedInvoice.id}`, invoiceToSave);
const index = invoicesData.value.findIndex(inv => inv.id === updatedInvoice.id);
if (index !== -1) {
invoicesData.value[index] = response.data;
}
}
} catch (error) {
toast.error("Rechnung konnte nicht gespeichert werden", {
description: (error as Error).message,
});
// Update table
const index = invoicesData.value.findIndex(inv => inv.id === updatedInvoice.id);
if (index !== -1) {
invoicesData.value[index] = updatedInvoice;
} else {
invoicesData.value.push(updatedInvoice);
}
}
const deleteInvoice = async (id: number) => {
try {
await axios.delete('/api/invoices/' + id)
const index = invoicesData.value.findIndex(invoice => invoice.id === id)
if (index !== -1) {
invoicesData.value.splice(index, 1)
}
} catch (error) {
toast.error("Rechnung konnte nicht gelöscht werden", {
description: (error as Error).message,
});
const onDeleteInvoice = async (id: number) => {
const index = invoicesData.value.findIndex(invoice => invoice.id === id)
if (index !== -1) {
invoicesData.value.splice(index, 1)
}
}
@@ -234,7 +183,7 @@ const deleteInvoice = async (id: number) => {
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<Button size="sm" variant="action" @click="editInvoice()">
<Button size="sm" variant="action" @click="createInvoice">
<Plus />
Neu
</Button>
@@ -257,7 +206,8 @@ const deleteInvoice = async (id: number) => {
<DocumentTable :invoices="filteredInvoices" :onItemClicked="editInvoice" />
<!-- Invoice detail dialog -->
<InvoiceDialog :invoiceData="activeInvoice" v-model="detailDialogOpen" @save="" @delete="" />
<InvoiceDialog :invoiceData="activeInvoice" v-model="detailDialogOpen" @save="onSaveInvoice"
@delete="onDeleteInvoice" />
</AppLayout>
</template>