Optimise invoice data requests #56
This commit is contained in:
@@ -1,15 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import { computed, ref, onMounted, watch, defineProps, HTMLAttributes } from 'vue'
|
||||
import { type Invoice, type Customer, type Address } from '@/types'
|
||||
import { newInvoice } from '@/types/index.d'
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
import { type Invoice } from '@/types'
|
||||
import axios from 'axios'
|
||||
import AppLayout from '@/layouts/AppLayout.vue'
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from '@/components/ui/select'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import DocumentTable from '@/components/documents/DocumentTable.vue'
|
||||
import { ChevronLeft, ChevronRight, Plus, Search, Delete } from "lucide-vue-next"
|
||||
import InvoiceDialog from '@/components/documents/InvoiceDialog.vue'
|
||||
import Fuse from 'fuse.js';
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { toast } from 'vue-sonner'
|
||||
@@ -18,38 +16,35 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/comp
|
||||
import { Kbd, KbdGroup } from '@/components/ui/kbd'
|
||||
import { statusBadgeLabels } from '@/components/ui/status-badge'
|
||||
import AppHeader from '@/components/AppHeader.vue'
|
||||
import InvoiceDialog from '@/components/documents/InvoiceDialog.vue'
|
||||
|
||||
const invoicesData = ref([] as Invoice[])
|
||||
const activeInvoice = ref<Invoice | null>(null)
|
||||
const customersData = ref([] as Customer[])
|
||||
// initial invoice data from inertia
|
||||
interface Props {
|
||||
invoicesData: Invoice[];
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
const invoicesData = ref(props.invoicesData || [])
|
||||
const activeInvoice = ref<Invoice | undefined>(undefined)
|
||||
const selectedYearIndex = ref(0)
|
||||
const detailDialogOpen = ref(false)
|
||||
const searchQuery = ref('')
|
||||
const searchField = ref()
|
||||
|
||||
onMounted(async () => {
|
||||
const invoiceResponse = await axios.get('/api/invoices')
|
||||
invoicesData.value = invoiceResponse.data as Invoice[]
|
||||
|
||||
const customerResponse = await axios.get('/api/customers')
|
||||
customersData.value = customerResponse.data as Customer[]
|
||||
|
||||
searchField.value = document.getElementById('search')
|
||||
// Load older invoices after initial page load
|
||||
try {
|
||||
const invoiceBeforeThisYearResponse = await axios.get('/api/invoices/summaryBeforeThisYear')
|
||||
invoicesData.value = invoicesData.value.concat(invoiceBeforeThisYearResponse.data as Invoice[])
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Daten:', error)
|
||||
}
|
||||
|
||||
let queryString = window.location.search
|
||||
let params = new URLSearchParams(queryString)
|
||||
if (params.get('action') == 'new') showDetail(newInvoice())
|
||||
})
|
||||
if (params.get('action') == 'new') editInvoice()
|
||||
|
||||
watch(invoicesData, () => {
|
||||
// Die watch-Funktion wird automatisch ausgelöst, wenn sich invoicesData ändert
|
||||
// Das filteredInvoices-Array wird automatisch aktualisiert
|
||||
// Fügen Sie eine kleine Verzögerung hinzu, um sicherzustellen, dass die Daten aktualisiert werden
|
||||
setTimeout(() => {
|
||||
// Die watch-Funktion wird automatisch ausgelöst, wenn sich invoicesData ändert
|
||||
// Das filteredInvoices-Array wird automatisch aktualisiert
|
||||
}, 0);
|
||||
}, { deep: true });
|
||||
searchField.value = document.getElementById('search')
|
||||
})
|
||||
|
||||
const years = computed((): number[] => {
|
||||
const allYears = invoicesData.value.map(invoice => {
|
||||
@@ -61,10 +56,11 @@ const years = computed((): number[] => {
|
||||
return uniqueYears
|
||||
})
|
||||
|
||||
// Filter / search
|
||||
const fuse = computed(() => {
|
||||
const options = {
|
||||
keys: [
|
||||
'customer.companyName',
|
||||
'billingData.companyName',
|
||||
{
|
||||
name: 'paymentStatus',
|
||||
getFn: (invoice: Invoice) => statusBadgeLabels[invoice.paymentStatus] || invoice.paymentStatus
|
||||
@@ -79,28 +75,26 @@ const fuse = computed(() => {
|
||||
})
|
||||
|
||||
const filteredInvoices = computed(() => {
|
||||
// Filter by query
|
||||
if (!searchQuery.value) {
|
||||
return years.value[selectedYearIndex.value] ?
|
||||
invoicesData.value.filter(invoice => {
|
||||
return years.value[selectedYearIndex.value]
|
||||
? invoicesData.value.filter(invoice => {
|
||||
const invoiceDate = new Date(invoice.invoiceDate);
|
||||
return invoiceDate.getFullYear() === years.value[selectedYearIndex.value];
|
||||
}) :
|
||||
invoicesData.value;
|
||||
})
|
||||
: invoicesData.value;
|
||||
}
|
||||
|
||||
return fuse.value.search(searchQuery.value)
|
||||
.map(result => result.item)
|
||||
.filter(invoice => {
|
||||
// Stellen Sie sicher, dass die gefilterten Rechnungen auch zum ausgewählten Jahr gehören
|
||||
const invoiceDate = new Date(invoice.invoiceDate);
|
||||
return !years.value[selectedYearIndex.value] || invoiceDate.getFullYear() === years.value[selectedYearIndex.value];
|
||||
});
|
||||
});
|
||||
|
||||
const showDetail = (invoice: Invoice) => {
|
||||
const editInvoice = (invoice?: Invoice) => {
|
||||
// make a deep copy, so the changes in the dialog won’t affect the data until saved
|
||||
activeInvoice.value = JSON.parse(JSON.stringify(invoice))
|
||||
activeInvoice.value = invoice ? JSON.parse(JSON.stringify(invoice)) : null
|
||||
detailDialogOpen.value = true
|
||||
}
|
||||
|
||||
@@ -171,10 +165,9 @@ const saveInvoice = async (updatedInvoice: Invoice) => {
|
||||
}
|
||||
|
||||
const deleteInvoice = async (id: number) => {
|
||||
|
||||
try {
|
||||
const response = axios.delete('/api/invoices/' + id)
|
||||
const index = invoicesData.value.findIndex(invoice => invoice.id === id);
|
||||
await axios.delete('/api/invoices/' + id)
|
||||
const index = invoicesData.value.findIndex(invoice => invoice.id === id)
|
||||
if (index !== -1) {
|
||||
invoicesData.value.splice(index, 1)
|
||||
}
|
||||
@@ -189,7 +182,7 @@ const deleteInvoice = async (id: number) => {
|
||||
|
||||
<template>
|
||||
|
||||
|
||||
|
||||
<!-- Function Header -->
|
||||
<AppLayout title="Rechnungen">
|
||||
|
||||
@@ -200,9 +193,10 @@ const deleteInvoice = async (id: number) => {
|
||||
@click="selectedYearIndex++">
|
||||
<ChevronLeft />
|
||||
</Button>
|
||||
<Select size="sm" v-model="selectedYearIndex" v-if="years.length > 1">
|
||||
<SelectTrigger class=" hover:bg-accent">
|
||||
<SelectValue placeholder="Jahr" />
|
||||
<Select size="sm" v-model="selectedYearIndex">
|
||||
<SelectTrigger class="hover:bg-accent">
|
||||
<SelectValue :placeholder="(new Date()).getFullYear().toString()"
|
||||
:disabled="years.length < 1" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
@@ -240,7 +234,7 @@ const deleteInvoice = async (id: number) => {
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<Button size="sm" variant="action" @click="showDetail(newInvoice())">
|
||||
<Button size="sm" variant="action" @click="editInvoice()">
|
||||
<Plus />
|
||||
Neu
|
||||
</Button>
|
||||
@@ -260,11 +254,10 @@ const deleteInvoice = async (id: number) => {
|
||||
</AppHeader>
|
||||
|
||||
<!-- Invoice Table -->
|
||||
<DocumentTable :invoices="filteredInvoices" :onItemClicked="showDetail" />
|
||||
<DocumentTable :invoices="filteredInvoices" :onItemClicked="editInvoice" />
|
||||
|
||||
<!-- Invoice detail dialog -->
|
||||
<InvoiceDialog :invoiceData="activeInvoice" :customers="customersData" v-model="detailDialogOpen"
|
||||
@save="saveInvoice" @delete="deleteInvoice" />
|
||||
<InvoiceDialog :invoiceData="activeInvoice" v-model="detailDialogOpen" @save="" @delete="" />
|
||||
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user