Two month of work
This commit is contained in:
@@ -7,20 +7,21 @@ import draggable from 'vuedraggable';
|
||||
import { cn, toCurrency } from '@/lib/utils';
|
||||
import { LineItem, Product, Unit } from '@/types';
|
||||
import { newLineItem, newUnit } from '@/types/index.d'
|
||||
import { Table, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from '@/components/ui/table';
|
||||
import { Table, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from '@/components/ui/crm-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/crm-input';
|
||||
import { Loader2, GripVertical, Trash2, Plus, TextSelect, CheckIcon, ChevronsUpDownIcon } from 'lucide-vue-next';
|
||||
import { Button } from '@/components/ui/crm-button';
|
||||
import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from '@/components/ui/empty'
|
||||
import NumberInput from '@/components/ui/number-input/NumberInput.vue';
|
||||
import NumberInput from '@/components/ui/crm-number-input/NumberInput.vue';
|
||||
import { GrowingTextarea } from '@/components/ui/growing-textarea';
|
||||
import PlaceholderPattern from '@/components/PlaceholderPattern.vue';
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from '@/components/ui/command'
|
||||
import { Popover, PopoverContent, PopoverTrigger, } from '@/components/ui/popover'
|
||||
import axios, { AxiosError } from "axios";
|
||||
import { toast } from "vue-sonner";
|
||||
import ButtonGroup from '../ui/button-group/ButtonGroup.vue';
|
||||
|
||||
|
||||
const DEBUG = ref(true)
|
||||
@@ -194,7 +195,7 @@ const recalculatePositions = () => {
|
||||
|
||||
<TableRow v-if="element.isSection">
|
||||
<TableCell class="handle px-1 cursor-move w-6">
|
||||
<GripVertical :size="18" stroke-width="1.5" class="text-muted-foreground" />
|
||||
<GripVertical :size="18" class="text-muted-foreground" />
|
||||
</TableCell>
|
||||
|
||||
<!-- Title -->
|
||||
@@ -210,7 +211,7 @@ const recalculatePositions = () => {
|
||||
<TableCell class="w-8 text-right px-1">
|
||||
<Button variant="ghost" size="sm" @click="deleteItem(element)"
|
||||
class="has-[>svg]:px-1 text-muted-foreground hover:text-destructive">
|
||||
<Trash2 :size="18" stroke-width="1.5" />
|
||||
<Trash2 :size="18" />
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -218,7 +219,7 @@ const recalculatePositions = () => {
|
||||
|
||||
<TableRow v-else>
|
||||
<TableCell class="handle px-1 cursor-move w-6">
|
||||
<GripVertical :size="18" stroke-width="1.5" class="text-muted-foreground" />
|
||||
<GripVertical :size="18" class="text-muted-foreground" />
|
||||
</TableCell>
|
||||
|
||||
<!-- Pos. -->
|
||||
@@ -272,19 +273,19 @@ const recalculatePositions = () => {
|
||||
|
||||
<!-- Total -->
|
||||
<TableCell class="w-1/8 text-right tabular-nums font-bold">{{ toCurrency(element.price * element.quantity)
|
||||
}}
|
||||
}}
|
||||
</TableCell>
|
||||
|
||||
<!-- Buttons -->
|
||||
<TableCell class="w-8 text-right px-1">
|
||||
<Button variant="ghost" size="sm" @click="deleteItem(element)"
|
||||
class="has-[>svg]:px-1 text-muted-foreground hover:text-destructive">
|
||||
<Trash2 stroke-width="1.5" />
|
||||
<Trash2 />
|
||||
</Button>
|
||||
|
||||
<!-- <Button variant="ghost" size="sm" @click=""
|
||||
class="has-[>svg]:px-1 text-muted-foreground">
|
||||
<BetweenHorizonalEnd stroke-width="1.5"/>
|
||||
<BetweenHorizonalEnd />
|
||||
</Button> -->
|
||||
|
||||
</TableCell>
|
||||
@@ -299,18 +300,18 @@ const recalculatePositions = () => {
|
||||
<div class="flex gap-2 justify-center">
|
||||
|
||||
<Button class="mt-4" variant="ghost" @click="newItem(true)">
|
||||
<Plus stroke-width="1.5" /> Neuer Abschnitt
|
||||
<Plus /> Neuer Abschnitt
|
||||
</Button>
|
||||
|
||||
<Button class="mt-4" variant="ghost" @click="newItem(false)">
|
||||
<Plus stroke-width="1.5" /> Neue Zeile
|
||||
<Plus /> Neue Zeile
|
||||
</Button>
|
||||
|
||||
<Popover v-model:open="productsComboboxOpen">
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="ghost" role="combobox" :aria-expanded="productsComboboxOpen" class="mt-4"
|
||||
:disabled="!products || products.length === 0">
|
||||
<Plus stroke-width="1.5" />
|
||||
<Plus />
|
||||
Produkt hinzufügen
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
@@ -326,7 +327,7 @@ const recalculatePositions = () => {
|
||||
}" class="hover:bg-accent">
|
||||
|
||||
<!-- Thumbnail -->
|
||||
<div class="w-6 relative aspect-4/3 overflow-hidden rounded-lg">
|
||||
<div class="w-6 relative aspect-4/3 overflow-hidden rounded-sm shrink-0">
|
||||
<img v-if="product.image" :src="'storage/uploads/products/' + product.image"
|
||||
class="size-full object-cover dark:brightness-75" loading="lazy" />
|
||||
<PlaceholderPattern v-else />
|
||||
@@ -348,59 +349,63 @@ const recalculatePositions = () => {
|
||||
</Table>
|
||||
|
||||
<Loader2 v-if="props.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" />
|
||||
<TextSelect class="text-muted-foreground" />
|
||||
</EmptyMedia>
|
||||
<EmptyTitle>Diese Rechnung ist leer</EmptyTitle>
|
||||
<EmptyDescription>Erstelle hier deinen ersten Posten</EmptyDescription>
|
||||
</EmptyHeader>
|
||||
<div class="flex gap-2">
|
||||
|
||||
<Button variant="action" @click="newItem(true)">
|
||||
<Plus stroke-width="1.5" /> Neuer Abschnitt
|
||||
</Button>
|
||||
<ButtonGroup>
|
||||
|
||||
<Button variant="action" @click="newItem(false)">
|
||||
<Plus stroke-width="1.5" /> Neue Zeile
|
||||
</Button>
|
||||
<Button @click="newItem(true)">
|
||||
<Plus /> Neuer Abschnitt
|
||||
</Button>
|
||||
|
||||
<Popover v-model:open="productsComboboxOpen">
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="action" role="combobox" :aria-expanded="productsComboboxOpen"
|
||||
:disabled="!products || products.length === 0">
|
||||
<Plus stroke-width="1.5" />
|
||||
Produkt hinzufügen
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-50 p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Produkt suchen…" />
|
||||
<CommandList>
|
||||
<CommandEmpty>Kein Produkt gefunden</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<CommandItem v-for="product in products" :key="product.id" :value="product.id" @select="() => {
|
||||
productsComboboxOpen = false
|
||||
insertProduct(product)
|
||||
}" class="hover:bg-accent">
|
||||
<Button @click="newItem(false)">
|
||||
<Plus /> Neue Zeile
|
||||
</Button>
|
||||
|
||||
<!-- Thumbnail -->
|
||||
<div class="w-6 relative aspect-4/3 overflow-hidden rounded-lg">
|
||||
<img v-if="product.image" :src="'storage/uploads/products/' + product.image"
|
||||
class="size-full object-cover dark:brightness-75" loading="lazy" />
|
||||
<PlaceholderPattern v-else />
|
||||
</div>
|
||||
<Popover v-model:open="productsComboboxOpen">
|
||||
<PopoverTrigger as-child>
|
||||
<Button role="combobox" :aria-expanded="productsComboboxOpen"
|
||||
:disabled="!products || products.length === 0">
|
||||
<Plus />
|
||||
Produkt hinzufügen
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-50 p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Produkt suchen…" />
|
||||
<CommandList>
|
||||
<CommandEmpty>Kein Produkt gefunden</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<CommandItem v-for="product in products" :key="product.id" :value="product.id" @select="() => {
|
||||
productsComboboxOpen = false
|
||||
insertProduct(product)
|
||||
}" class="hover:bg-accent">
|
||||
|
||||
{{ product.title }}
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<!-- Thumbnail -->
|
||||
<div class="w-6 relative aspect-4/3 overflow-hidden rounded-sm shrink-0">
|
||||
<img v-if="product.image" :src="'storage/uploads/products/' + product.image"
|
||||
class="size-full object-cover dark:brightness-75" loading="lazy" />
|
||||
<PlaceholderPattern v-else />
|
||||
</div>
|
||||
|
||||
{{ product.title }}
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
</ButtonGroup>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user