This commit is contained in:
Florian Hoss 2023-07-04 11:51:13 +02:00
commit f90fdc0598
99 changed files with 15260 additions and 0 deletions

View file

@ -0,0 +1,25 @@
<template>
<div class="flex align-items-center">
<div @click="!isDisabled && $emit('decrementOrder')" :style="{ color: isDisabled ? 'grey' : 'red' }" style="cursor: pointer">
<i class="pi pi-minus"></i>
</div>
<div class="mx-2 font-bold">{{ order.order_count }}</div>
<div @click="!isDisabled && $emit('incrementOrder')" :style="{ color: isDisabled ? 'grey' : 'green' }" style="cursor: pointer">
<i class="pi pi-plus"></i>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue";
import { service_Order } from "@/services/openapi";
export default defineComponent({
name: "OrderAmountChange",
props: {
order: { type: Object as PropType<service_Order>, required: true },
isDisabled: { type: Boolean, default: false },
},
emits: ["incrementOrder", "decrementOrder"],
});
</script>

View file

@ -0,0 +1,48 @@
<template>
<div>
<BaseToolbar :title="generalItemTypeString(type)" :icon="generalItemTypeIcon(type)" @click="$emit('openModal', type)" btnIcon="plus" />
<div class="grid">
<TableOrderCard v-for="order in OrdersForType" v-bind:key="order.id" :order="order">
<div class="flex align-items-end">
<OrderAmountChange :order="order" :isDisabled="isLoading" @incrementOrder="incrementOrder(order)" @decrementOrder="decrementOrder(order)" />
</div>
</TableOrderCard>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, inject, PropType, ref } from "vue";
import { OrdersService, service_Order } from "@/services/openapi";
import { convertToEur, generalItemTypeString, generalItemTypeIcon } from "@/utils";
import BaseToolbar from "@/components/UI/BaseToolbar.vue";
import TableOrderCard from "@/components/Tables/TableOrderCard.vue";
import OrderAmountChange from "@/components/Tables/OrderAmountChange.vue";
import { loading } from "@/keys";
export default defineComponent({
name: "OverviewPerType",
components: { TableOrderCard, BaseToolbar, OrderAmountChange },
props: {
orders: { type: Array as PropType<service_Order[]>, default: () => [] },
type: { type: Array as PropType<number[]>, required: true },
},
emits: ["openModal", "getData"],
setup(props, { emit }) {
const OrdersForType = computed(() => props.orders.filter((order) => props.type.includes(order.order_item.item_type)));
const isLoading = inject(loading, ref(false));
function incrementOrder(order: service_Order) {
isLoading.value = true;
OrdersService.postOrders(order.order_item_id, order.table_id).finally(() => emit("getData"));
}
function decrementOrder(order: service_Order) {
isLoading.value = true;
OrdersService.deleteOrders(order.order_item_id, order.table_id).finally(() => emit("getData"));
}
return { OrdersForType, isLoading, convertToEur, incrementOrder, decrementOrder, generalItemTypeIcon, generalItemTypeString };
},
});
</script>

View file

@ -0,0 +1,48 @@
<template>
<SmallCard bgColor="a" :to="'/tables/' + table.id">
<template #description>Tisch {{ table.id }}</template>
<template #badge>{{ since }}</template>
<template #right>
<div class="flex align-items-end">
<TheBadge v-if="table.order_count" class="topRight">{{ table.order_count }}</TheBadge>
<div v-if="table.total" class="font-bold">{{ convertToEur(table.total) }}</div>
</div>
</template>
</SmallCard>
</template>
<script lang="ts">
import { defineComponent, onMounted, onUnmounted, PropType, ref } from "vue";
import { service_Table } from "@/services/openapi";
import moment from "moment";
import { convertToEur, getCurrentTimeSince } from "@/utils";
import TheBadge from "@/components/UI/TheBadge.vue";
import SmallCard from "@/components/UI/SmallCard.vue";
export default defineComponent({
name: "TableCard",
components: { TheBadge, SmallCard },
props: { table: { type: Object as PropType<service_Table>, required: true } },
setup(props) {
moment.locale("de");
// eslint-disable-next-line
let ticker: any;
const since = ref(getCurrentTimeSince(props.table.updated_at));
onMounted(() => {
ticker = setInterval(() => {
since.value = getCurrentTimeSince(props.table.updated_at);
}, 1000);
});
onUnmounted(() => ticker && clearInterval(ticker));
return { since, convertToEur };
},
});
</script>
<style scoped>
.topRight {
position: absolute;
top: -0.2rem;
right: 0.3rem;
}
</style>

View file

@ -0,0 +1,30 @@
<template>
<SmallCard bgColor="d" :badgeTwo="order.total !== order.order_item.price">
<template #description>{{ order.order_item.description }}</template>
<template #badgeOne>{{ convertToEur(order.order_item.price) }}</template>
<template #badgeTwo>{{ convertToEur(order.total) }}</template>
<template #right>
<slot></slot>
</template>
</SmallCard>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from "vue";
import { service_Order, types_ItemType } from "@/services/openapi";
import { convertToEur } from "@/utils";
import SmallCard from "@/components/UI/SmallCard.vue";
export default defineComponent({
name: "TableOrderCard",
components: { SmallCard },
props: {
order: { type: Object as PropType<service_Order>, required: true },
},
emits: ["decrementOrder", "incrementOrder"],
setup(props) {
const showTotal = computed(() => props.order.order_item.price !== props.order.total);
return { convertToEur, types_ItemType, showTotal };
},
});
</script>

View file

@ -0,0 +1,172 @@
<template>
<BaseCard>
<Transition>
<WaveSpinner v-if="initialLoading" />
<div v-else>
<OverviewPerType :type="[types_ItemType.Food]" :orders="orders" @getData="getData" @openModal="(t) => addBeverage(t)" />
<OverviewPerType :type="[types_ItemType.ColdDrink, types_ItemType.HotDrink]" :orders="orders" @getData="getData" @openModal="(t) => addBeverage(t)" />
<div class="h-4rem"></div>
<BottomNavigation>
<template #left>
<router-link :to="{ name: 'Tables' }" class="no-underline">
<Button :disabled="isLoading" icon="pi pi-arrow-left" class="p-button-rounded" />
</router-link>
</template>
<template #middle>
<div class="flex flex-column align-items-center">
<div class="text-sm">Tisch {{ table }}</div>
<div class="font-bold">{{ convertToEur(total) }}</div>
</div>
</template>
<template #right>
<router-link
:style="{ cursor: isLoading || orders.length === 0 ? 'default' : 'pointer' }"
:to="{ name: isLoading || orders.length === 0 ? 'TableDetail' : 'Checkout' }"
class="no-underline"
>
<Button :disabled="isLoading || orders.length === 0" icon="pi pi-money-bill" class="p-button-danger p-button-rounded" />
</router-link>
</template>
</BottomNavigation>
</div>
</Transition>
<Sidebar v-model:visible="newOrderModal" :baseZIndex="10000" position="full">
<div class="p-fluid">
<Listbox
v-model="selected"
:options="options"
:filter="true"
optionLabel="description"
dataKey="id"
optionValue="id"
listStyle="max-height:65vh"
filterPlaceholder="Suchen"
/>
</div>
<div class="flex justify-content-end mt-4">
<Button :loading="isLoading" label="Speichern" icon="pi pi-check" class="p-button p-button-success mr-3" @click="postOrder" />
</div>
</Sidebar>
</BaseCard>
</template>
<script lang="ts">
import { computed, defineComponent, provide, ref } from "vue";
import BaseCard from "@/components/UI/BaseCard.vue";
import { useStore } from "vuex";
import { OrdersService, service_Order, service_OrderItem, types_ItemType } from "@/services/openapi";
import BottomNavigation from "@/components/UI/BottomNavigation.vue";
import Button from "primevue/button";
import { convertToEur } from "@/utils";
import WaveSpinner from "@/components/UI/WaveSpinner.vue";
import Sidebar from "primevue/sidebar";
import Listbox from "primevue/listbox";
import OverviewPerType from "@/components/Tables/OverviewPerType.vue";
import { loading } from "@/keys";
export default defineComponent({
name: "TableOverview",
// eslint-disable-next-line
components: { OverviewPerType, WaveSpinner, BottomNavigation, BaseCard, Button, Sidebar, Listbox },
props: { id: { type: String, default: "0" } },
setup(props) {
const initialLoading = ref(false);
const isLoading = ref(false);
provide(loading, isLoading);
const newOrderModal = ref(false);
const store = useStore();
const selectedOrder = ref();
const table = computed(() => parseInt(props.id));
const total = ref(0);
const orderItems = computed(() => store.getters.getOrderItems);
const options = ref();
const orders = ref<service_Order[]>([]);
store.dispatch("getAllOrderItems");
getData(true);
function getData(initial = false) {
initial && (initialLoading.value = true);
OrdersService.getOrders(table.value, true)
.then((res) => (orders.value = res))
.finally(() => {
updateTotal();
resetValues();
});
}
function resetValues() {
newOrderModal.value = false;
selectedOrder.value = undefined;
isLoading.value = false;
initialLoading.value = false;
}
function updateTotal() {
let temp = 0;
orders.value.forEach((order) => (temp += order.total));
total.value = temp;
}
function addBeverage(itemType: types_ItemType[]) {
newOrderModal.value = true;
options.value = [];
itemType.forEach((type) => {
options.value = options.value.concat(orderItems.value.get(type));
});
options.value.sort((a: service_OrderItem, b: service_OrderItem) => {
const x = a.description.toLowerCase();
const y = b.description.toLowerCase();
if (x < y) return -1;
if (x > y) return 1;
return 0;
});
}
function postOrder() {
isLoading.value = true;
if (selectedOrder.value) {
OrdersService.postOrders(selectedOrder.value, table.value).finally(() => getData());
} else isLoading.value = false;
}
return {
initialLoading,
isLoading,
newOrderModal,
selected: selectedOrder,
options,
table,
total,
convertToEur,
addBeverage,
types_ItemType,
postOrder,
orders,
getData,
};
},
});
</script>
<style scoped>
.v-enter-active {
transition: opacity 0.2s ease-in;
}
.v-enter-from {
opacity: 0;
}
</style>
<style>
.p-sidebar-content {
margin: 0 !important;
padding: 0 !important;
}
.p-listbox {
border: 0 !important;
}
</style>