Move REST calls from invoice table to invoice dialog, fixes #56
This commit is contained in:
@@ -2,23 +2,23 @@
|
||||
<!-- TODO: Enter in LineItem = neue Zeile -->
|
||||
<script setup lang="ts">
|
||||
|
||||
import { ref, watch, HTMLAttributes } from 'vue'
|
||||
import { ref, watch, HTMLAttributes, onUpdated, onMounted } from 'vue'
|
||||
import draggable from 'vuedraggable';
|
||||
import { cn, toCurrency } from '@/lib/utils';
|
||||
import { LineItem } from '@/types';
|
||||
import { newLineItem } from '@/types/index.d'
|
||||
import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from '@/components/ui/table';
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from "@/components/ui/select"
|
||||
import { Table, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from '@/components/ui/table';
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"
|
||||
import { NumberField, NumberFieldContent, NumberFieldDecrement, NumberFieldIncrement, NumberFieldInput, } from '@/components/ui/number-field'
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { CirclePlus, GripVertical, Trash2, Plus, TextSelect } from 'lucide-vue-next';
|
||||
import Textarea from '../ui/textarea/Textarea.vue';
|
||||
import { Loader2, GripVertical, Trash2, Plus, TextSelect } from 'lucide-vue-next';
|
||||
import Button from '../ui/button/Button.vue';
|
||||
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from '@/components/ui/empty'
|
||||
import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from '@/components/ui/empty'
|
||||
import NumberInput from '../ui/number-input/NumberInput.vue';
|
||||
import { GrowingTextarea } from '../ui/growing-textarea';
|
||||
|
||||
const props = defineProps<{
|
||||
isLoading?: boolean,
|
||||
lineItems: LineItem[] | undefined,
|
||||
stickyTop: number | string,
|
||||
class?: HTMLAttributes['class']
|
||||
@@ -28,16 +28,24 @@ const emit = defineEmits<{
|
||||
(e: 'update:lineItems', value: LineItem[]): void
|
||||
}>()
|
||||
|
||||
const isLoading = ref(props.isLoading || false)
|
||||
const units = ref(['Stück', 'Stunden', 'Tage', 'pauschal'])
|
||||
const items = ref((props.lineItems ?? []).slice().sort(function (a, b) { return a.position - b.position })) // items only uses props.lineItems as the initial value;
|
||||
|
||||
onUpdated(() => {
|
||||
if (isLoading.value) isLoading.value = false
|
||||
})
|
||||
|
||||
watch(items, (newItems) => {
|
||||
if (isLoading.value) return
|
||||
|
||||
emit('update:lineItems', newItems)
|
||||
}, { deep: true })
|
||||
|
||||
watch(() => props.lineItems, (newLineItems) => {
|
||||
isLoading.value = (newLineItems?.length || 0) > 0
|
||||
items.value = (newLineItems ?? []).slice().sort(function (a, b) { return a.position - b.position })
|
||||
}, { deep: true })
|
||||
}, { deep: true, once: true })
|
||||
|
||||
const newItem = () => {
|
||||
const position = items.value.length + 1
|
||||
@@ -84,7 +92,8 @@ const recalculatePositions = () => {
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
<Table v-if="items.length > 0" class="table-fixed">
|
||||
<Table :class="{ 'opacity-100!': !isLoading && items.length >= 1 }"
|
||||
class="table-fixed transition-opacity opacity-0 duration-300">
|
||||
|
||||
<draggable v-model="items" tag="tbody" item-key="position" handle=".handle" ghostClass="ghost"
|
||||
@end="recalculatePositions">
|
||||
@@ -164,7 +173,7 @@ const recalculatePositions = () => {
|
||||
</template>
|
||||
</draggable>
|
||||
|
||||
<TableFooter class="bg-transparent">
|
||||
<TableFooter v-if="items.length >= 1" class="bg-transparent">
|
||||
<TableRow class="hover:bg-transparent dark:hover:bg-transparent">
|
||||
<TableCell colspan="8" class="text-center">
|
||||
|
||||
@@ -178,7 +187,9 @@ const recalculatePositions = () => {
|
||||
|
||||
</Table>
|
||||
|
||||
<Empty v-if="items.length < 1" class="md:pb-0 md:pt-8">
|
||||
<Loader2 v-if="isLoading" class="mx-auto mt-8 h-6 w-6 animate-spin text-muted-foreground" stroke-width="1.5" />
|
||||
|
||||
<Empty v-else-if="items.length < 1" class="py-8!">
|
||||
<EmptyHeader>
|
||||
<EmptyMedia variant="icon">
|
||||
<TextSelect class="text-muted-foreground" stroke-width="1.5" />
|
||||
|
||||
Reference in New Issue
Block a user