Merge branch 'devCorrected' into 'beta'
Dev corrected See merge request fedeo/software!54
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<script setup >
|
||||
<script setup>
|
||||
// Falls useDropZone nicht auto-importiert wird:
|
||||
// import { useDropZone } from '@vueuse/core'
|
||||
|
||||
const props = defineProps({
|
||||
fileData: {
|
||||
@@ -12,11 +14,35 @@ const props = defineProps({
|
||||
const emit = defineEmits(["uploadFinished"])
|
||||
|
||||
const modal = useModal()
|
||||
const profileStore = useProfileStore()
|
||||
// const profileStore = useProfileStore() // Wird im Snippet nicht genutzt, aber ich lasse es drin
|
||||
|
||||
const uploadInProgress = ref(false)
|
||||
const availableFiletypes = ref([])
|
||||
|
||||
// 1. State für die Dateien und die Dropzone Referenz
|
||||
const selectedFiles = ref([])
|
||||
const dropZoneRef = ref(null)
|
||||
|
||||
// 2. Setup der Dropzone
|
||||
const onDrop = (files) => {
|
||||
// Wenn Dateien gedroppt werden, speichern wir sie
|
||||
// files ist hier meist ein Array, wir stellen sicher, dass es passt
|
||||
selectedFiles.value = files || []
|
||||
}
|
||||
|
||||
const { isOverDropZone } = useDropZone(dropZoneRef, {
|
||||
onDrop,
|
||||
// Verhindert, dass der Browser das Bild einfach öffnet
|
||||
preventDefaultForDrop: true,
|
||||
})
|
||||
|
||||
// 3. Handler für den klassischen Datei-Input Klick
|
||||
const onFileInputChange = (e) => {
|
||||
if (e.target.files) {
|
||||
selectedFiles.value = Array.from(e.target.files)
|
||||
}
|
||||
}
|
||||
|
||||
const setup = async () => {
|
||||
availableFiletypes.value = await useEntities("filetags").select()
|
||||
}
|
||||
@@ -24,81 +50,112 @@ const setup = async () => {
|
||||
setup()
|
||||
|
||||
const uploadFiles = async () => {
|
||||
// Validierung: Keine Dateien ausgewählt
|
||||
if (!selectedFiles.value || selectedFiles.value.length === 0) {
|
||||
alert("Bitte wählen Sie zuerst Dateien aus.") // Oder eine schönere Toast Notification
|
||||
return
|
||||
}
|
||||
|
||||
uploadInProgress.value = true;
|
||||
|
||||
let fileData = props.fileData
|
||||
delete fileData.typeEnabled
|
||||
|
||||
|
||||
|
||||
await useFiles().uploadFiles(fileData, document.getElementById("fileUploadInput").files,[],true)
|
||||
// 4. Hier nutzen wir nun selectedFiles.value statt document.getElementById
|
||||
await useFiles().uploadFiles(fileData, selectedFiles.value, [], true)
|
||||
|
||||
uploadInProgress.value = false;
|
||||
emit("uploadFinished")
|
||||
modal.close()
|
||||
}
|
||||
|
||||
// Helper Funktion um Dateinamen anzuzeigen (da das Input Feld leer bleibt beim Droppen)
|
||||
const fileNames = computed(() => {
|
||||
if (!selectedFiles.value.length) return ''
|
||||
return selectedFiles.value.map(f => f.name).join(', ')
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UModal>
|
||||
<UCard :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Datei hochladen
|
||||
</h3>
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="-my-1"
|
||||
@click="modal.close()"
|
||||
:disabled="uploadInProgress"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<div ref="dropZoneRef" class="relative h-full flex flex-col">
|
||||
|
||||
<UFormGroup
|
||||
label="Datei:"
|
||||
<div
|
||||
v-if="isOverDropZone"
|
||||
class="absolute inset-0 z-50 flex items-center justify-center bg-primary-500/10 border-2 border-primary-500 border-dashed rounded-lg backdrop-blur-sm transition-all"
|
||||
>
|
||||
<UInput
|
||||
type="file"
|
||||
id="fileUploadInput"
|
||||
multiple
|
||||
accept="image/jpeg, image/png, image/gif, application/pdf"
|
||||
/>
|
||||
</UFormGroup>
|
||||
<UFormGroup
|
||||
label="Typ:"
|
||||
class="mt-3"
|
||||
>
|
||||
<USelectMenu
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
searchable-placeholder="Suchen..."
|
||||
:options="availableFiletypes"
|
||||
v-model="props.fileData.type"
|
||||
:disabled="!props.fileData.typeEnabled"
|
||||
<span class="text-xl font-bold text-primary-600 bg-white/80 px-4 py-2 rounded shadow-sm">
|
||||
Dateien hier ablegen
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<UCard :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Datei hochladen
|
||||
</h3>
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="-my-1"
|
||||
@click="modal.close()"
|
||||
:disabled="uploadInProgress"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<UFormGroup
|
||||
label="Datei:"
|
||||
:help="selectedFiles.length > 0 ? `${selectedFiles.length} Datei(en) ausgewählt` : 'Ziehen Sie Dateien hierher oder klicken Sie'"
|
||||
>
|
||||
<template #label>
|
||||
<span v-if="availableFiletypes.find(x => x.id === props.fileData.type)">{{availableFiletypes.find(x => x.id === props.fileData.type).name}}</span>
|
||||
<span v-else>Keine Typ ausgewählt</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
<UInput
|
||||
v-if="selectedFiles.length === 0"
|
||||
type="file"
|
||||
id="fileUploadInput"
|
||||
multiple
|
||||
accept="image/jpeg, image/png, image/gif, application/pdf"
|
||||
@change="onFileInputChange"
|
||||
/>
|
||||
|
||||
<template #footer>
|
||||
<UButton
|
||||
@click="uploadFiles"
|
||||
:loading="uploadInProgress"
|
||||
:disabled="uploadInProgress"
|
||||
>Hochladen</UButton>
|
||||
</template>
|
||||
</UCard>
|
||||
<div v-if="selectedFiles.length > 0" class="mt-2 text-sm text-gray-500">
|
||||
Ausgewählt: <span class="font-medium text-gray-700 dark:text-gray-300">{{ fileNames }}</span>
|
||||
</div>
|
||||
</UFormGroup>
|
||||
|
||||
<UFormGroup
|
||||
label="Typ:"
|
||||
class="mt-3"
|
||||
>
|
||||
<USelectMenu
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
searchable-placeholder="Suchen..."
|
||||
:options="availableFiletypes"
|
||||
v-model="props.fileData.type"
|
||||
:disabled="!props.fileData.typeEnabled"
|
||||
>
|
||||
<template #label>
|
||||
<span v-if="availableFiletypes.find(x => x.id === props.fileData.type)">{{availableFiletypes.find(x => x.id === props.fileData.type).name}}</span>
|
||||
<span v-else>Kein Typ ausgewählt</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<template #footer>
|
||||
<UButton
|
||||
@click="uploadFiles"
|
||||
:loading="uploadInProgress"
|
||||
:disabled="uploadInProgress || selectedFiles.length === 0"
|
||||
>Hochladen</UButton>
|
||||
</template>
|
||||
</UCard>
|
||||
</div>
|
||||
</UModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
/* Optional: Animationen für das Overlay */
|
||||
</style>
|
||||
@@ -9,6 +9,7 @@ const props = defineProps({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span v-if="props.row.infoData.streetNumber">{{props.row.infoData.streetNumber}},</span>
|
||||
<span v-if="props.row.infoData.street">{{props.row.infoData.street}},</span>
|
||||
<span v-if="props.row.infoData.special">{{props.row.infoData.special}},</span>
|
||||
<span v-if="props.row.infoData.zip">{{props.row.infoData.zip}},</span>
|
||||
|
||||
@@ -7,7 +7,7 @@ export default defineNuxtConfig({
|
||||
}
|
||||
},
|
||||
|
||||
modules: ['@pinia/nuxt', '@nuxt/ui', '@nuxtjs/supabase', "nuxt-editorjs", '@nuxtjs/fontaine', 'nuxt-viewport', 'nuxt-tiptap-editor', '@nuxtjs/leaflet'],
|
||||
modules: ['@pinia/nuxt', '@nuxt/ui', '@nuxtjs/supabase', "nuxt-editorjs", '@nuxtjs/fontaine', 'nuxt-viewport', 'nuxt-tiptap-editor', '@nuxtjs/leaflet', '@vueuse/nuxt'],
|
||||
|
||||
ssr: false,
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"@capacitor/cli": "^7.0.0",
|
||||
"@nuxtjs/leaflet": "^1.2.3",
|
||||
"@nuxtjs/supabase": "^1.1.4",
|
||||
"@vueuse/core": "^14.1.0",
|
||||
"@vueuse/nuxt": "^14.1.0",
|
||||
"nuxt": "^3.14.1592",
|
||||
"nuxt-tiptap-editor": "^1.2.0",
|
||||
"vue": "^3.5.13",
|
||||
@@ -87,4 +89,4 @@
|
||||
"zod": "^3.25.76",
|
||||
"zpl-renderer-js": "^2.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ const clearSearchString = () => {
|
||||
searchString.value = ''
|
||||
}
|
||||
|
||||
const filterAccount = ref(bankaccounts || [])
|
||||
const filterAccount = ref(bankaccounts.value || [])
|
||||
|
||||
const displayCurrency = (value, currency = "€") => {
|
||||
return `${Number(value).toFixed(2).replace(".",",")} ${currency}`
|
||||
@@ -150,7 +150,7 @@ setupPage()
|
||||
</USelectMenu>
|
||||
</template>
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
<!-- <USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
@@ -162,7 +162,7 @@ setupPage()
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</USelectMenu>-->
|
||||
<USelectMenu
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
multiple
|
||||
|
||||
@@ -12,7 +12,7 @@ defineShortcuts({
|
||||
})
|
||||
|
||||
const dataStore = useDataStore()
|
||||
const profileStore = useProfileStore()
|
||||
const tempStore = useTempStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const mode = ref(route.params.mode || "show")
|
||||
@@ -177,7 +177,14 @@ const removeAllocation = async (allocationId) => {
|
||||
await setup()
|
||||
}
|
||||
|
||||
const searchString = ref("")
|
||||
const searchString = ref(tempStore.searchStrings["bankstatementsedit"] ||'')
|
||||
|
||||
const clearSearchString = () => {
|
||||
searchString.value = ''
|
||||
tempStore.clearSearchString("bankstatementsedit")
|
||||
|
||||
}
|
||||
|
||||
const filteredDocuments = computed(() => {
|
||||
|
||||
|
||||
@@ -546,7 +553,15 @@ const archiveStatement = async () => {
|
||||
class="mr-3 mt-3"
|
||||
@click="removeAllocation(item.id)"
|
||||
/>
|
||||
<UButton
|
||||
icon="i-heroicons-eye"
|
||||
variant="outline"
|
||||
color="primary"
|
||||
class="mr-3 mt-3"
|
||||
@click="navigateTo(`/createDocument/show/${item.createddocument}`)"
|
||||
/>
|
||||
</UCard>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -780,6 +795,7 @@ const archiveStatement = async () => {
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block w-full mr-1"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
@change="tempStore.modifySearchString('bankstatementsedit',searchString)"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
@@ -789,7 +805,7 @@ const archiveStatement = async () => {
|
||||
variant="outline"
|
||||
icon="i-heroicons-x-mark"
|
||||
color="rose"
|
||||
@click="searchString = ''"
|
||||
@click="clearSearchString"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<UDashboardNavbar title="Ausgangsbelege" :badge="filteredRows.length">
|
||||
<UDashboardNavbar :badge="filteredRows.length" title="Ausgangsbelege">
|
||||
<template #right>
|
||||
<UInput
|
||||
id="searchinput"
|
||||
v-model="searchString"
|
||||
icon="i-heroicons-funnel"
|
||||
autocomplete="off"
|
||||
placeholder="Suche..."
|
||||
class="hidden lg:block"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
icon="i-heroicons-funnel"
|
||||
placeholder="Suche..."
|
||||
@change="tempStore.modifySearchString('createddocuments',searchString)"
|
||||
@keydown.esc="$event.target.blur()"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="/" />
|
||||
<UKbd value="/"/>
|
||||
</template>
|
||||
</UInput>
|
||||
<UButton
|
||||
v-if="searchString.length > 0"
|
||||
color="rose"
|
||||
icon="i-heroicons-x-mark"
|
||||
variant="outline"
|
||||
color="rose"
|
||||
@click="clearSearchString()"
|
||||
v-if="searchString.length > 0"
|
||||
/>
|
||||
<UButton
|
||||
@click="router.push(`/createDocument/edit`)"
|
||||
@@ -33,27 +33,27 @@
|
||||
|
||||
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
<!-- <USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
multiple
|
||||
class="hidden lg:block"
|
||||
by="key"
|
||||
class="hidden lg:block"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
multiple
|
||||
@change="tempStore.modifyColumns('createddocuments',selectedColumns)"
|
||||
>
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</USelectMenu>-->
|
||||
<USelectMenu
|
||||
v-if="selectableFilters.length > 0"
|
||||
v-model="selectedFilters"
|
||||
:color="selectedFilters.length > 0 ? 'primary' : 'white'"
|
||||
:options="selectableFilters"
|
||||
:ui-menu="{ width: 'min-w-max' }"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
multiple
|
||||
v-model="selectedFilters"
|
||||
:options="selectableFilters"
|
||||
:color="selectedFilters.length > 0 ? 'primary' : 'white'"
|
||||
:ui-menu="{ width: 'min-w-max' }"
|
||||
>
|
||||
<template #label>
|
||||
Filter
|
||||
@@ -63,36 +63,36 @@
|
||||
</UDashboardToolbar>
|
||||
<UTabs :items="selectedTypes" class="m-3">
|
||||
<template #default="{item}">
|
||||
{{item.label}}
|
||||
{{ item.label }}
|
||||
<UBadge
|
||||
variant="outline"
|
||||
class="ml-2"
|
||||
variant="outline"
|
||||
>
|
||||
{{filteredRows.filter(i => item.key === 'invoices' ? ['invoices','advanceInvoices','cancellationInvoices'].includes(i.type) : item.key === i.type).length}}
|
||||
{{ filteredRows.filter(i => item.key === 'invoices' ? ['invoices', 'advanceInvoices', 'cancellationInvoices'].includes(i.type) : item.key === i.type).length }}
|
||||
</UBadge>
|
||||
</template>
|
||||
<template #item="{item}">
|
||||
<div style="height: 80vh; overflow-y: scroll">
|
||||
<UTable
|
||||
:rows="filteredRows.filter(i => item.key === 'invoices' ? ['invoices','advanceInvoices','cancellationInvoices'].includes(i.type) : item.key === i.type)"
|
||||
:columns="columns"
|
||||
class="w-full"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
@select="selectItem"
|
||||
:empty-state="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Belege anzuzeigen' }"
|
||||
:rows="filteredRows.filter(i => item.key === 'invoices' ? ['invoices','advanceInvoices','cancellationInvoices'].includes(i.type) : item.key === i.type)"
|
||||
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
|
||||
class="w-full"
|
||||
@select="selectItem"
|
||||
>
|
||||
<template #type-data="{row}">
|
||||
{{dataStore.documentTypesForCreation[row.type].labelSingle}}
|
||||
<!--
|
||||
<span v-if="row.type === 'cancellationInvoices'"> zu {{row.linkedDocument.documentNumber}}</span>
|
||||
-->
|
||||
{{ dataStore.documentTypesForCreation[row.type].labelSingle }}
|
||||
<!--
|
||||
<span v-if="row.type === 'cancellationInvoices'"> zu {{row.linkedDocument.documentNumber}}</span>
|
||||
-->
|
||||
</template>
|
||||
<template #state-data="{row}">
|
||||
<span
|
||||
v-if="row.state === 'Entwurf'"
|
||||
class="text-rose-500"
|
||||
>
|
||||
{{row.state}}
|
||||
{{ row.state }}
|
||||
</span>
|
||||
<!-- <span
|
||||
v-if="row.state === 'Gebucht'"
|
||||
@@ -104,49 +104,56 @@
|
||||
v-if="row.state === 'Gebucht' && !items.find(i => i.createddocument && i.createddocument.id === row.id)"
|
||||
class="text-primary-500"
|
||||
>
|
||||
{{row.state}}
|
||||
{{ row.state }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="row.state === 'Gebucht' && items.find(i => i.createddocument && i.createddocument.id === row.id && i.type === 'cancellationInvoices') && ['invoices','advanceInvoices'].includes(row.type)"
|
||||
class="text-cyan-500"
|
||||
>
|
||||
Storniert mit {{items.find(i => i.createddocument && i.createddocument.id === row.id).documentNumber}}
|
||||
Storniert mit {{ items.find(i => i.createddocument && i.createddocument.id === row.id).documentNumber }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="row.state === 'Gebucht'"
|
||||
class="text-primary-500"
|
||||
>
|
||||
{{row.state}}
|
||||
{{ row.state }}
|
||||
</span>
|
||||
</template>
|
||||
<template #partner-data="{row}">
|
||||
<span v-if="row.customer && row.customer.name.length <21">{{row.customer ? row.customer.name : ""}}</span>
|
||||
<span v-if="row.customer && row.customer.name.length <21">{{ row.customer ? row.customer.name : "" }}</span>
|
||||
<UTooltip v-else-if="row.customer && row.customer.name.length > 20" :text="row.customer.name">
|
||||
{{row.customer.name.substring(0,20)}}...
|
||||
{{ row.customer.name.substring(0, 20) }}...
|
||||
</UTooltip>
|
||||
</template>
|
||||
<template #reference-data="{row}">
|
||||
<span v-if="row === filteredRows[selectedItem]" class="text-primary-500 font-bold">{{row.documentNumber}}</span>
|
||||
<span v-else>{{row.documentNumber}}</span>
|
||||
<span v-if="row === filteredRows[selectedItem]"
|
||||
class="text-primary-500 font-bold">{{ row.documentNumber }}</span>
|
||||
<span v-else>{{ row.documentNumber }}</span>
|
||||
</template>
|
||||
<template #date-data="{row}">
|
||||
<span v-if="row.date">{{row.date ? dayjs(row.date).format("DD.MM.YY") : ''}}</span>
|
||||
<span v-if="row.documentDate">{{row.documentDate ? dayjs(row.documentDate).format("DD.MM.YY") : ''}}</span>
|
||||
<span v-if="row.date">{{ row.date ? dayjs(row.date).format("DD.MM.YY") : '' }}</span>
|
||||
<span
|
||||
v-if="row.documentDate">{{ row.documentDate ? dayjs(row.documentDate).format("DD.MM.YY") : '' }}</span>
|
||||
</template>
|
||||
<template #dueDate-data="{row}">
|
||||
<span v-if="row.state === 'Gebucht' && row.paymentDays && ['invoices','advanceInvoices'].includes(row.type) && !items.find(i => i.linkedDocument && i.linkedDocument.id === row.id)" :class="dayjs(row.documentDate).add(row.paymentDays,'day').diff(dayjs()) <= 0 && !isPaid(row) ? ['text-rose-500'] : '' ">{{row.documentDate ? dayjs(row.documentDate).add(row.paymentDays,'day').format("DD.MM.YY") : ''}}</span>
|
||||
<span
|
||||
v-if="row.state === 'Gebucht' && row.paymentDays && ['invoices','advanceInvoices'].includes(row.type) && !items.find(i => i.linkedDocument && i.linkedDocument.id === row.id)"
|
||||
:class="dayjs(row.documentDate).add(row.paymentDays,'day').diff(dayjs()) <= 0 && !isPaid(row) ? ['text-rose-500'] : '' ">{{ row.documentDate ? dayjs(row.documentDate).add(row.paymentDays, 'day').format("DD.MM.YY") : '' }}</span>
|
||||
</template>
|
||||
<template #paid-data="{row}">
|
||||
<div v-if="(row.type === 'invoices' ||row.type === 'advanceInvoices') && row.state === 'Gebucht' && !items.find(i => i.linkedDocument && i.linkedDocument.id === row.id)">
|
||||
<div
|
||||
v-if="(row.type === 'invoices' ||row.type === 'advanceInvoices') && row.state === 'Gebucht' && !items.find(i => i.linkedDocument && i.linkedDocument.id === row.id)">
|
||||
<span v-if="useSum().getIsPaid(row,items)" class="text-primary-500">Bezahlt</span>
|
||||
<span v-else class="text-rose-600">Offen</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #amount-data="{row}">
|
||||
<span v-if="row.type !== 'deliveryNotes'">{{displayCurrency(useSum().getCreatedDocumentSum(row,items))}}</span>
|
||||
<span
|
||||
v-if="row.type !== 'deliveryNotes'">{{ displayCurrency(useSum().getCreatedDocumentSum(row, items)) }}</span>
|
||||
</template>
|
||||
<template #amountOpen-data="{row}">
|
||||
<span v-if="!['deliveryNotes','cancellationInvoices','quotes','confirmationOrders'].includes(row.type) && row.state !== 'Entwurf' && !useSum().getIsPaid(row,items) && !items.find(i => i.linkedDocument && i.linkedDocument.id === row.id) ">{{displayCurrency(useSum().getCreatedDocumentSum(row, items) - row.statementallocations.reduce((n,{amount}) => n + amount, 0))}}</span>
|
||||
<span
|
||||
v-if="!['deliveryNotes','cancellationInvoices','quotes','confirmationOrders'].includes(row.type) && row.state !== 'Entwurf' && !useSum().getIsPaid(row,items) && !items.find(i => i.linkedDocument && i.linkedDocument.id === row.id) ">{{ displayCurrency(useSum().getCreatedDocumentSum(row, items) - row.statementallocations.reduce((n, {amount}) => n + amount, 0)) }}</span>
|
||||
</template>
|
||||
</UTable>
|
||||
</div>
|
||||
@@ -175,14 +182,14 @@ defineShortcuts({
|
||||
}
|
||||
},
|
||||
'arrowdown': () => {
|
||||
if(selectedItem.value < filteredRows.value.length - 1) {
|
||||
if (selectedItem.value < filteredRows.value.length - 1) {
|
||||
selectedItem.value += 1
|
||||
} else {
|
||||
selectedItem.value = 0
|
||||
}
|
||||
},
|
||||
'arrowup': () => {
|
||||
if(selectedItem.value === 0) {
|
||||
if (selectedItem.value === 0) {
|
||||
selectedItem.value = filteredRows.value.length - 1
|
||||
} else {
|
||||
selectedItem.value -= 1
|
||||
@@ -202,7 +209,7 @@ const selectedItem = ref(0)
|
||||
|
||||
|
||||
const setupPage = async () => {
|
||||
items.value = (await useEntities("createddocuments").select("*, customer(id,name), statementallocations(id,amount),linkedDocument(*)","documentNumber",true, true))
|
||||
items.value = (await useEntities("createddocuments").select("*, customer(id,name), statementallocations(id,amount),linkedDocument(*)", "documentNumber", true, true))
|
||||
}
|
||||
|
||||
setupPage()
|
||||
@@ -309,7 +316,7 @@ const filteredRows = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
if(selectedFilters.value.length > 0) {
|
||||
if (selectedFilters.value.length > 0) {
|
||||
selectedFilters.value.forEach(filterName => {
|
||||
let filter = dataType.filters.find(i => i.name === filterName)
|
||||
tempItems = tempItems.filter(filter.filterFunction)
|
||||
@@ -317,7 +324,6 @@ const filteredRows = computed(() => {
|
||||
}
|
||||
|
||||
|
||||
|
||||
tempItems = useSearch(searchString.value, tempItems)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
<template>
|
||||
<UDashboardNavbar title="Serienrechnungen" :badge="filteredRows.length">
|
||||
<template #right>
|
||||
@@ -25,7 +23,7 @@
|
||||
</UDashboardNavbar>
|
||||
<UDashboardToolbar>
|
||||
<template #right>
|
||||
<USelectMenu
|
||||
<!-- <USelectMenu
|
||||
v-model="selectedColumns"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
:options="templateColumns"
|
||||
@@ -36,7 +34,7 @@
|
||||
<template #label>
|
||||
Spalten
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</USelectMenu>-->
|
||||
<USelectMenu
|
||||
v-model="selectedFilters"
|
||||
icon="i-heroicons-adjustments-horizontal-solid"
|
||||
@@ -65,26 +63,6 @@
|
||||
<template #type-data="{row}">
|
||||
{{dataStore.documentTypesForCreation[row.type].labelSingle}}
|
||||
</template>
|
||||
<template #state-data="{row}">
|
||||
<span
|
||||
v-if="row.state === 'Entwurf'"
|
||||
class="text-rose-500"
|
||||
>
|
||||
{{row.state}}
|
||||
</span>
|
||||
<span
|
||||
v-if="row.state === 'Gebucht'"
|
||||
class="text-cyan-500"
|
||||
>
|
||||
{{row.state}}
|
||||
</span>
|
||||
<span
|
||||
v-if="row.state === 'Abgeschlossen'"
|
||||
class="text-primary-500"
|
||||
>
|
||||
{{row.state}}
|
||||
</span>
|
||||
</template>
|
||||
<template #partner-data="{row}">
|
||||
<span v-if="row.customer">{{row.customer ? row.customer.name : ""}}</span>
|
||||
|
||||
@@ -116,6 +94,10 @@
|
||||
<template #contract-data="{row}">
|
||||
<span v-if="row.contract">{{row.contract.contractNumber}} - {{row.contract.name}}</span>
|
||||
</template>
|
||||
<template #serialConfig.intervall-data="{row}">
|
||||
<span v-if="row.serialConfig?.intervall === 'monatlich'">Monatlich</span>
|
||||
<span v-if="row.serialConfig?.intervall === 'vierteljährlich'">Quartalsweise</span>
|
||||
</template>
|
||||
</UTable>
|
||||
|
||||
</template>
|
||||
@@ -161,13 +143,9 @@ const filteredRows = computed(() => {
|
||||
|
||||
const templateColumns = [
|
||||
{
|
||||
key: 'type',
|
||||
label: "Typ"
|
||||
key: 'serialConfig.active',
|
||||
label: "Aktiv"
|
||||
},{
|
||||
key: 'state',
|
||||
label: "Status"
|
||||
},
|
||||
{
|
||||
key: "amount",
|
||||
label: "Betrag"
|
||||
},
|
||||
@@ -180,8 +158,8 @@ const templateColumns = [
|
||||
label: "Vertrag"
|
||||
},
|
||||
{
|
||||
key: 'serialConfig.active',
|
||||
label: "Aktiv"
|
||||
key: 'serialConfig.intervall',
|
||||
label: "Rhythmus"
|
||||
}
|
||||
]
|
||||
const selectedColumns = ref(templateColumns)
|
||||
|
||||
@@ -364,33 +364,67 @@ const clearSearchString = () => {
|
||||
variant="outline"
|
||||
v-if="Object.keys(selectedFiles).find(i => selectedFiles[i] === true)"
|
||||
>Herunterladen</UButton>
|
||||
<UModal
|
||||
v-model="createFolderModalOpen"
|
||||
>
|
||||
<UCard>
|
||||
<UModal v-model="createFolderModalOpen">
|
||||
<UCard :ui="{ body: { base: 'space-y-4' } }">
|
||||
<template #header>
|
||||
Ordner Erstellen
|
||||
</template>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Ordner Erstellen
|
||||
</h3>
|
||||
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="createFolderModalOpen = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<UFormGroup label="Name des Ordners" required>
|
||||
<UInput
|
||||
v-model="createFolderData.name"
|
||||
placeholder="z.B. Rechnungen 2024"
|
||||
autofocus
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
|
||||
<UFormGroup
|
||||
label="Ordner erstellen"
|
||||
<UFormGroup
|
||||
label="Standard Dateityp"
|
||||
>
|
||||
<USelectMenu
|
||||
v-model="createFolderData.standardFiletype"
|
||||
:options="filetags"
|
||||
option-attribute="name"
|
||||
value-attribute="id"
|
||||
searchable
|
||||
searchable-placeholder="Typ suchen..."
|
||||
placeholder="Kein Standard-Typ"
|
||||
clear-search-on-close
|
||||
>
|
||||
<UInput
|
||||
v-model="createFolderData.name"
|
||||
<template #label>
|
||||
<span v-if="createFolderData.standardFiletype">
|
||||
{{ filetags.find(t => t.id === createFolderData.standardFiletype)?.name }}
|
||||
</span>
|
||||
<span v-else class="text-gray-400">Kein Typ ausgewählt</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</UFormGroup>
|
||||
|
||||
<div v-if="createFolderData.standardFiletype">
|
||||
<UCheckbox
|
||||
v-model="createFolderData.standardFiletypeIsOptional"
|
||||
name="isOptional"
|
||||
label="Dateityp ist optional"
|
||||
help="Wenn deaktiviert, MUSS der Nutzer beim Upload diesen Typ verwenden."
|
||||
/>
|
||||
</UFormGroup>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<UButton
|
||||
@click="createFolder"
|
||||
>
|
||||
Erstellen
|
||||
</UButton>
|
||||
<div class="flex justify-end gap-2">
|
||||
<UButton color="gray" variant="ghost" @click="createFolderModalOpen = false">
|
||||
Abbrechen
|
||||
</UButton>
|
||||
<UButton @click="createFolder" :disabled="!createFolderData.name">
|
||||
Erstellen
|
||||
</UButton>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
|
||||
</UModal>
|
||||
|
||||
</template>
|
||||
@@ -429,8 +463,8 @@ const clearSearchString = () => {
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="entry.type === 'file'" class="text-xl">{{dayjs(documents.find(i => i.id === entry.id).created_at).format("DD.MM.YY HH:mm")}}</span>
|
||||
<span v-if="entry.type === 'folder'" class="text-xl">{{dayjs(currentFolders.find(i => i.id === entry.id).created_at).format("DD.MM.YY HH:mm")}}</span>
|
||||
<span v-if="entry.type === 'file'" class="text-xl">{{dayjs(documents.find(i => i.id === entry.id).createdAt).format("DD.MM.YY HH:mm")}}</span>
|
||||
<span v-if="entry.type === 'folder'" class="text-xl">{{dayjs(currentFolders.find(i => i.id === entry.id).createdAt).format("DD.MM.YY HH:mm")}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Reference in New Issue
Block a user