Table summary of orders

This commit is contained in:
2024-07-12 17:11:52 +02:00
parent 200242252c
commit bbec759b08
16 changed files with 414 additions and 136 deletions

View File

@@ -1,10 +1,28 @@
<template> <template>
<RouterView /> <Suspense>
<RouterView />
</Suspense>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import './assets/style.scss' import './assets/style.scss'
import { RouterView } from 'vue-router' import { RouterView } from 'vue-router'
import { watch } from 'vue'
import { getActivePinia } from 'pinia'
const pinia = getActivePinia();
if(pinia != undefined) {
watch(
pinia.state,
(state) => {
// persist the whole state to the local storage whenever it changes
localStorage.setItem('piniaState', JSON.stringify(state))
},
{ deep: true }
);
}
</script> </script>
<style> <style>

View File

@@ -48,8 +48,4 @@ async function confirmOrder() {
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style scoped>
</style>

View File

@@ -131,8 +131,4 @@ function cancelOrder(event: Event) {
</div> </div>
</div> </div>
</form> </form>
</template> </template>
<style scoped>
</style>

View File

@@ -9,8 +9,4 @@
<div class="box is-skeleton mb-3 mx-3" style="height: 20vh"></div> <div class="box is-skeleton mb-3 mx-3" style="height: 20vh"></div>
</div> </div>
</template> </template>
<style scoped>
</style>

View File

@@ -43,8 +43,4 @@ function sendLogin() {
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style scoped>
</style>

View File

@@ -1,12 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import VueDatePicker from '@vuepic/vue-datepicker'; import VueDatePicker from '@vuepic/vue-datepicker';
import { axiosInstance, type Category, type Contractor, type OrderProduct } from '@/main' import { axiosInstance, type Contractor, type OrderProduct } from '@/main'
import { useCategoriesStore } from '@/stores/categories.store' import { useCategoriesStore } from '@/stores/categories.store'
import { useContractorsStore } from '@/stores/contractors.store' import { useContractorsStore } from '@/stores/contractors.store'
import { useOrdersStore } from '@/stores/orders.store' import { useOrdersStore } from '@/stores/orders.store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useSiteControlStore } from '@/stores/siteControl.store' import { useSiteControlStore } from '@/stores/siteControl.store'
import { ref } from 'vue' import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const categoriesStore = useCategoriesStore(); const categoriesStore = useCategoriesStore();
const contractorsStore = useContractorsStore(); const contractorsStore = useContractorsStore();
@@ -17,26 +18,60 @@ const { contractor, contractors } = storeToRefs(contractorsStore);
const { deliveryDate, uuid } = storeToRefs(ordersStore); const { deliveryDate, uuid } = storeToRefs(ordersStore);
const { categories } = storeToRefs(categoriesStore); const { categories } = storeToRefs(categoriesStore);
const { showConfirmationModal, isDarkTheme } = storeToRefs(siteControlStore); const { showConfirmationModal, isDarkTheme } = storeToRefs(siteControlStore);
const contractorSearch = ref<string>();
const filteredContractors = ref<Array<Contractor>>();
const showContractorsDropdown = ref<boolean>(false);
const contractorInput = ref(null);
const showErrorNotification = ref<boolean>(false); const showErrorNotification = ref<boolean>(false);
const errorNotificationMessage = ref<string>();
const route = useRoute();
watch(contractor, (contractor) => {
if(contractor == undefined) {
contractorSearch.value = '';
} else {
contractorSearch.value = contractor.Knt_NipE + ', ' + contractor.Knt_Nazwa1 + contractor.Knt_Nazwa2 + contractor.Knt_Nazwa3;
}
}, { immediate: true });
function createJSON(event: Event) { function createJSON(event: Event) {
event.preventDefault(); event.preventDefault();
console.log(route);
const json = { const json = {
MZN_UUID: uuid.value, MZN_UUID: uuid.value,
MZN_DataZam: new Date(Date.now()).toISOString(), MZN_DataZam: new Date(Date.now()).toISOString().split('T')[0],
MZN_DataDos: deliveryDate.value != undefined ? deliveryDate.value.toISOString() : null, MZN_DataDos: deliveryDate.value != undefined ? deliveryDate.value.toISOString() : null,
MZN_PodID: contractor.value, MZN_PodID: contractor.value?.Knt_KntId,
MZamElem: new Array<OrderProduct> MZamElem: new Array<OrderProduct>
}; };
if(categories.value == undefined) return; if(categories.value == undefined) {
showErrorNotification.value=true;
errorNotificationMessage.value = "Produkty nie zostały pobrane z bazy danych.";
return;
}
if(contractor.value == undefined) {
showErrorNotification.value=true;
errorNotificationMessage.value = "Klient nie został wybrany.";
return;
}
if(deliveryDate.value == undefined) {
showErrorNotification.value=true;
errorNotificationMessage.value = "Data dostawy nie została wybrana.";
return;
}
for (let category of categories.value) { for (let category of categories.value) {
for (let product of category.Towary) { for (let product of category.Towary) {
if(product.Quantity != null && product.Quantity != '') { if(product.Quantity != null && product.Quantity != '') {
if(isNaN(Number(product.Quantity)) || isNaN(Number(product.Twr_CenaZ)) || isNaN(Number(product.Twr_Cena))) { if(isNaN(Number(product.Quantity)) || isNaN(Number(product.Twr_CenaZ)) || isNaN(Number(product.Twr_Cena))) {
showErrorNotification.value=true; showErrorNotification.value=true;
return; errorNotificationMessage.value = "W zamówieniu znajdują się niepoprawne wartości.";
return;
} }
const productObject : OrderProduct = { const productObject : OrderProduct = {
MZE_TwrId: product.Twr_TwrId, MZE_TwrId: product.Twr_TwrId,
@@ -54,10 +89,12 @@ function createJSON(event: Event) {
} }
if(json.MZamElem.length == 0) { if(json.MZamElem.length == 0) {
showErrorNotification.value=true; showErrorNotification.value=true;
errorNotificationMessage.value = "Zamówienie jest puste.";
return; return;
} }
showErrorNotification.value=false; showErrorNotification.value=false;
console.log(json);
console.log(JSON.stringify(json));
axiosInstance.post('/zamowienie', JSON.stringify(json)).then( response => { axiosInstance.post('/zamowienie', JSON.stringify(json)).then( response => {
uuid.value = response.data.MZN_UUID; uuid.value = response.data.MZN_UUID;
}); });
@@ -65,12 +102,64 @@ function createJSON(event: Event) {
function setConfirmationModal(event : Event) { function setConfirmationModal(event : Event) {
event.preventDefault(); event.preventDefault();
if(uuid.value == undefined) {
showErrorNotification.value=true;
errorNotificationMessage.value = "Zamówienie nie zostało jeszcze zapisane w bazie danych.";
return;
}
showConfirmationModal.value = true; showConfirmationModal.value = true;
} }
function cancelOrder(event: Event) {
event.preventDefault();
axiosInstance.delete('/zamowienie/' + uuid.value);
siteControlStore.newOrder();
}
function filterContractors() {
if (contractorSearch.value == "") {
contractor.value = undefined;
filteredContractors.value = contractors.value;
return;
}
filteredContractors.value = contractors.value.filter(
contractor =>
(contractor.Knt_NipE + contractor.Knt_Nazwa1 + contractor.Knt_Nazwa2 + contractor.Knt_Nazwa3).toLowerCase().includes(contractorSearch.value as string)
);
}
function toggleContractorsDropdown() {
if(!showContractorsDropdown.value) {
showContractorsDropdown.value = true;
if(contractorSearch.value == undefined || contractorSearch.value == '') {
filteredContractors.value = contractors.value;
}
}
}
function handleClickOutsideDropdown(event : Event) {
if(contractorInput.value != null && !contractorInput.value.contains(event.target)){
showContractorsDropdown.value = false;
}
}
function selectContractorFromDropdown(selectedContractor : Contractor) {
console.log(selectedContractor);
contractor.value = selectedContractor;
showContractorsDropdown.value = false;
}
onMounted(function (){
document.addEventListener('click', handleClickOutsideDropdown);
});
onBeforeUnmount( function () {
document.removeEventListener('click', handleClickOutsideDropdown);
})
</script> </script>
<template> <template>
<form class="box" @submit="createJSON"> <form class="box" @submit.prevent="createJSON">
<div class="mb-3"> <div class="mb-3">
<div class="box"> <div class="box">
<div class="mb-3"> <div class="mb-3">
@@ -78,12 +167,29 @@ function setConfirmationModal(event : Event) {
<h1 class="subtitle is-5" v-if="uuid != undefined" ><b>{{ uuid }}</b></h1> <h1 class="subtitle is-5" v-if="uuid != undefined" ><b>{{ uuid }}</b></h1>
</div> </div>
<div class="field mb-5"> <div class="field mb-5">
<label class="label is-small">NIP</label> <label class="label is-small">Klient</label>
<div class="field"> <div class="field">
<div class="select is-small is-expanded" style="width: 100%"> <div ref="contractorInput" class="dropdown maxwidth"
<select v-model="contractor" class="is-expanded" style="width: 100%" required> v-bind:class="{'is-active': showContractorsDropdown == true}">
<option class="is-expanded" v-for="contractor in contractors" :key="contractor.Knt_KntId" :value="contractor">{{ contractor.Knt_NipE + ', ' + contractor.Knt_Miasto + ', ' + contractor.Knt_Nazwa1 + ' ' + contractor.Knt_Nazwa2 + ' ' + contractor.Knt_Nazwa3 }}</option> <div class="dropdown-trigger maxwidth" @click="toggleContractorsDropdown">
</select> <div class="field maxwidth" @onclick.prevent="toggleContractorsDropdown">
<p class="control is-expanded has-icons-right is-small maxwidth" @onclick.prevent="toggleContractorsDropdown">
<input class="input is-small is-expanded maxwidth" type="search"
v-model="contractorSearch" @input="filterContractors" />
<span class="icon is-small is-right"><i class="fas fa-search"></i></span>
</p>
</div>
</div>
<div class="dropdown-menu is-clipped has-background-info-on-scheme-invert" id="dropdown-menu" role="menu" style="max-width: calc(100vw - 3rem); box-shadow: 0px 0px 6px -1px rgba(165, 165, 165, 0.8); border-radius: 10px 10px 10px 10px; overflow-x:auto">
<div class="dropdown-content" style="max-height: 50vh; overflow-x: auto">
<a v-if="filteredContractors != undefined && filteredContractors.length == 0" class="dropdown-item is-clipped">Brak wyników</a>
<a v-for="dropdownContractor in filteredContractors" v-bind:key="dropdownContractor.Knt_KntId"
class="dropdown-item is-clipped" @click = "selectContractorFromDropdown(dropdownContractor)"
v-bind:class = "{'has-background-info' : dropdownContractor == contractor}">
{{dropdownContractor.Knt_NipE + ', ' + dropdownContractor.Knt_Nazwa1 + dropdownContractor.Knt_Nazwa2 + dropdownContractor.Knt_Nazwa3}}
</a>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -101,9 +207,10 @@ function setConfirmationModal(event : Event) {
</div> </div>
<button class="button is-info mt-5">Zapisz</button> <button class="button is-info mt-5">Zapisz</button>
<button class="button is-success mt-5 ml-3" @click="setConfirmationModal">Potwierdź</button> <button class="button is-success mt-5 ml-3" @click="setConfirmationModal">Potwierdź</button>
<div v-if="showErrorNotification==true" class="notification is-danger is-light mt-5"> <button class="button is-danger mt-5 ml-3" @click="cancelOrder" v-bind:disabled="uuid == undefined">Anuluj</button>
<div v-if="showErrorNotification==true" class="notification is-danger is-bold mt-5">
<button class="delete" @click.prevent="showErrorNotification = false"></button> <button class="delete" @click.prevent="showErrorNotification = false"></button>
W formularzu znajdują się pola, które nie liczbami, lub wszystkie pola puste. {{ errorNotificationMessage }}
</div> </div>
</div> </div>
</div> </div>
@@ -120,7 +227,7 @@ function setConfirmationModal(event : Event) {
type="text" type="text"
placeholder="Kwota" placeholder="Kwota"
v-model="product.Twr_Cena" v-model="product.Twr_Cena"
v-bind:class="{ 'is-danger has-background-danger-90': product.Twr_Cena != undefined && isNaN(Number(product.Twr_Cena)),'is-success has-background-success-85': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}" v-bind:class="{ 'is-danger has-background-danger-soft': product.Twr_Cena != undefined && isNaN(Number(product.Twr_Cena)),'is-success has-background-success-soft': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}"
/> />
</div> </div>
</div> </div>
@@ -131,7 +238,7 @@ function setConfirmationModal(event : Event) {
type="text" type="text"
placeholder="Kwota" placeholder="Kwota"
v-model="product.Twr_CenaZ" v-model="product.Twr_CenaZ"
v-bind:class="{ 'is-danger has-background-danger-90': product.Twr_CenaZ != undefined && isNaN(Number(product.Twr_CenaZ)), 'is-success has-background-success-90': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity)) v-bind:class="{ 'is-danger has-background-danger-soft': product.Twr_CenaZ != undefined && isNaN(Number(product.Twr_CenaZ)), 'is-success has-background-success-soft': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))
}" }"
/> />
</div> </div>
@@ -139,14 +246,14 @@ function setConfirmationModal(event : Event) {
<div class="column"> <div class="column">
<div class="field has-addons"> <div class="field has-addons">
<p class="control"> <p class="control">
<span class="select is-small" v-bind:class="{ 'is-danger has-background-danger-90': product.Quantity != undefined && isNaN(Number(product.Quantity)),'is-success has-background-success-90': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}"> <span class="select is-small" v-bind:class="{ 'is-danger': product.Quantity != undefined && isNaN(Number(product.Quantity)),'is-success': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}">
<select v-model="product.ChosenOption" v-bind:class="{ 'is-danger has-background-danger-90': product.Quantity != undefined && isNaN(Number(product.Quantity)),'is-success has-background-success-90': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}"> <select v-model="product.ChosenOption" v-bind:class="{ 'is-danger has-background-danger-soft': product.Quantity != undefined && isNaN(Number(product.Quantity)),'is-success has-background-success-soft': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}">
<option v-for="option in product.Options" :key="option">{{ option }}</option> <option v-for="option in product.Options" :key="option">{{ option }}</option>
</select> </select>
</span> </span>
</p> </p>
<p class="control is-expanded"> <p class="control is-expanded">
<input class="input is-small" type="text" placeholder="Ilość" v-model="product.Quantity" v-bind:class="{ 'is-danger has-background-danger-90': product.Quantity != undefined && isNaN(Number(product.Quantity)),'is-success has-background-success-90': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}"> <input class="input is-small" type="text" placeholder="Ilość" v-model="product.Quantity" v-bind:class="{ 'is-danger has-background-danger-soft': product.Quantity != undefined && isNaN(Number(product.Quantity)),'is-success has-background-success-soft': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}">
</p> </p>
</div> </div>
</div> </div>
@@ -174,7 +281,8 @@ function setConfirmationModal(event : Event) {
--dp-menu-border-color: var(--bulma-border); --dp-menu-border-color: var(--bulma-border);
--dp-border-color-hover: var(--bulma-border); --dp-border-color-hover: var(--bulma-border);
--dp-border-color-focus: var(--bulma-border); --dp-border-color-focus: var(--bulma-border);
--dp-primary-color: var(--bulma-info-00); --dp-primary-color: var(--bulma-info);
--dp-primary-text-color: #000;
} }
} }
@@ -188,4 +296,8 @@ function setConfirmationModal(event : Event) {
--dp-primary-text-color: #000; --dp-primary-text-color: #000;
} }
} }
.maxwidth {
width: 100%;
}
</style> </style>

View File

@@ -19,14 +19,13 @@ const userStore = useUserStore();
const { username } = storeToRefs(userStore); const { username } = storeToRefs(userStore);
function makeBurger() { function makeBurger() {
activator.value = !activator.value activator.value = !activator.value
return activator return activator
} }
function clickForm() { function clickForm() {
siteControlStore.switchToFrom(); siteControlStore.switchToForm();
if(activator.value) { if(activator.value) {
activator.value = false; activator.value = false;
} }
@@ -39,27 +38,21 @@ function clickOrders() {
} }
} }
function clickTable() {
siteControlStore.switchToTable();
if(activator.value) {
activator.value = false;
}
}
function routeLogin() { function routeLogin() {
axiosInstance.post('/logout'); axiosInstance.post('/logout');
router.push("/login"); router.push("/login");
} }
function newOrder() {
const {order, uuid, deliveryDate, orderDate } = storeToRefs(ordersStore);
const { contractor } = storeToRefs(contractorsStore);
contractor.value = undefined;
order.value = undefined;
uuid.value = undefined;
deliveryDate.value = undefined;
orderDate.value = undefined;
categoriesStore.fetchCategories();
siteControlStore.switchToFrom();
window.scrollTo(0, 0);
}
</script> </script>
<template> <template>
<nav class="navbar" role="navigation" aria-label="main navigation"> <nav class="navbar has-shadow" role="navigation" aria-label="main navigation">
<div class="navbar-brand"> <div class="navbar-brand">
<a class="navbar-item is-overflow-hidden" style="max-width: calc(100vw - 50px); white-space: nowrap; overflow: hidden"> <a class="navbar-item is-overflow-hidden" style="max-width: calc(100vw - 50px); white-space: nowrap; overflow: hidden">
<h3 class="title is-4">Mleczarnia</h3> <h3 class="title is-4">Mleczarnia</h3>
@@ -81,15 +74,17 @@ function newOrder() {
<a class="navbar-item" @click="clickOrders"> <a class="navbar-item" @click="clickOrders">
Zamówienia Zamówienia
</a> </a>
<a class="navbar-item" @click="clickTable">
Tabela
</a>
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
<div class="navbar-item"> <div class="navbar-item">
<div class="buttons"> <div class="buttons">
<button class="button is-info" @click="newOrder"> <button class="button is-info" @click="siteControlStore.newOrder">
Nowe Zamówienie Nowe Zamówienie
</button> </button>
<button class="button is-light" @click="routeLogin" > <button class="button is-info" @click="routeLogin" >
Wyloguj Wyloguj
</button> </button>
</div> </div>
@@ -97,8 +92,4 @@ function newOrder() {
</div> </div>
</div> </div>
</nav> </nav>
</template> </template>
<style scoped>
</style>

View File

@@ -1,17 +1,18 @@
<script setup lang="ts"> <script setup lang="ts">
import VueDatePicker from '@vuepic/vue-datepicker'; import VueDatePicker from '@vuepic/vue-datepicker';
import { ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { useOrdersStore } from '@/stores/orders.store' import { useOrdersStore } from '@/stores/orders.store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useSiteControlStore } from '@/stores/siteControl.store' import { useSiteControlStore } from '@/stores/siteControl.store'
const ordersStore = useOrdersStore(); const ordersStore = useOrdersStore();
const siteControlStore = useSiteControlStore(); const siteControlStore = useSiteControlStore();
const searchOrderDate = ref<Date>(); const searchOrderDate = ref<Array<Date>>();
const isOutOfBuffer = ref<boolean>(false); const isOutOfBuffer = ref<boolean>(false);
const isInBufor = ref<boolean>(false); const isInBufor = ref<boolean>(false);
const { orders } = storeToRefs(ordersStore); const { orders } = storeToRefs(ordersStore);
const areOrdersLoading = ref<boolean>(false); const areOrdersLoading = ref<boolean>(false);
const { isDarkTheme } = storeToRefs(siteControlStore);
watch(isInBufor, (val) => { watch(isInBufor, (val) => {
if(val && val == isOutOfBuffer.value) { if(val && val == isOutOfBuffer.value) {
@@ -29,6 +30,12 @@ watch(isOutOfBuffer, (val) => {
immediate: true immediate: true
}); });
const buffer = computed(()=>{
if (!isInBufor.value && !isOutOfBuffer.value) {
return null;
} else return !!isInBufor.value;
});
function viewOrder(uuid : string) { function viewOrder(uuid : string) {
siteControlStore.viewOrder(uuid); siteControlStore.viewOrder(uuid);
} }
@@ -36,10 +43,13 @@ function viewOrder(uuid : string) {
async function fetchOrders(event : Event) { async function fetchOrders(event : Event) {
event.preventDefault(); event.preventDefault();
areOrdersLoading.value = true; areOrdersLoading.value = true;
if(isInBufor.value) { console.log(searchOrderDate.value);
orders.value = await ordersStore.fetchOrdersInBuffer();
} else if (isOutOfBuffer.value) { if(searchOrderDate.value == undefined) {
orders.value = await ordersStore.fetchOrdersOutOfBuffer(); orders.value = await ordersStore.fetchOrdersByBuffer(buffer.value);
}
if(searchOrderDate.value != undefined) {
orders.value = await ordersStore.fetchOrdersByDateStartAndEnd(searchOrderDate.value[0], searchOrderDate.value[1], buffer.value);
} }
areOrdersLoading.value = false; areOrdersLoading.value = false;
} }
@@ -57,7 +67,10 @@ async function fetchOrders(event : Event) {
<VueDatePicker v-model="searchOrderDate" <VueDatePicker v-model="searchOrderDate"
:enable-time-picker="false" :enable-time-picker="false"
:clearable="true" :clearable="true"
input-class-name="input is-small"/> input-class-name="input is-small calendar-background"
menu-class-name="calendar-background"
v-bind:dark = "isDarkTheme"
range/>
</div> </div>
</div> </div>
<div class="field mb-5"> <div class="field mb-5">
@@ -73,15 +86,14 @@ async function fetchOrders(event : Event) {
</label> </label>
</div> </div>
</div> </div>
<button class="button is-primary is-small is-expanded" @click="fetchOrders" :class="{ 'is-loading': areOrdersLoading }">Pobierz zamówienia</button> <button class="button is-info is-small is-expanded" @click="fetchOrders" :class="{ 'is-loading': areOrdersLoading }">Pobierz zamówienia</button>
</div> </div>
</form> </form>
<div class="box"> <div class="box">
<h1 class="is-large mb-3"><b>ZAMÓWIENIA</b></h1> <h1 class="is-large mb-3"><b>ZAMÓWIENIA</b></h1>
<div class="columns is-multiline"> <div class="columns is-multiline">
<div class="column is-4" v-for="order in orders" :key="order.MZN_UUID"> <div class="column is-4" v-for="order in orders" :key="order.MZN_UUID">
<div class="box"> <div class="box" :class="{'confirmed' : order.MZN_Bufor == 0 && order.MZN_Anulowane != 1, 'cancelled' : order.MZN_Anulowane == 1}">
<!-- <h1 class="mb-3 is-size-7"><b>{{ order.MZN_UUID }}</b></h1>-->
<label class="label is-small">Klient</label> <label class="label is-small">Klient</label>
<div class="field is-small mb-3"> <div class="field is-small mb-3">
<input class="input is-small is-static" <input class="input is-small is-static"
@@ -122,7 +134,7 @@ async function fetchOrders(event : Event) {
value="Nie" value="Nie"
readonly/> readonly/>
</div> </div>
<button class="button is-primary is-small is-expanded" @click="viewOrder(order.MZN_UUID)" :name="order.MZN_UUID">Podgląd</button> <button class="button is-info is-small is-expanded" @click="viewOrder(order.MZN_UUID)" :name="order.MZN_UUID">Podgląd</button>
</div> </div>
</div> </div>
</div> </div>
@@ -130,6 +142,34 @@ async function fetchOrders(event : Event) {
</div> </div>
</template> </template>
<style scoped> <style>
@media (prefers-color-scheme: dark){
.calendar-background {
--dp-background-color: rgb(20, 22, 26);
--dp-border-color: var(--bulma-border);
--dp-menu-border-color: var(--bulma-border);
--dp-border-color-hover: var(--bulma-border);
--dp-border-color-focus: var(--bulma-border);
--dp-primary-color: var(--bulma-info);
--dp-primary-text-color: #000;
}
}
@media (prefers-color-scheme: light){
.calendar-background {
--dp-border-color: var(--bulma-border);
--dp-menu-border-color: var(--bulma-border);
--dp-border-color-hover: var(--bulma-border);
--dp-border-color-focus: var(--bulma-border);
--dp-primary-color: var(--bulma-info);
--dp-primary-text-color: #000;
}
}
.cancelled {
--bulma-box-background-color: var(--bulma-danger-soft)
}
.confirmed {
--bulma-box-background-color: var(--bulma-success-soft)
}
</style> </style>

View File

@@ -1,4 +1,4 @@
import { createApp } from 'vue'; import { createApp, watch } from 'vue'
import App from './App.vue'; import App from './App.vue';
import VueDatePicker from '@vuepic/vue-datepicker'; import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css'; import '@vuepic/vue-datepicker/dist/main.css';
@@ -24,10 +24,18 @@ const pinia = createPinia();
app.use(pinia); app.use(pinia);
app.use(VueCookies); app.use(VueCookies);
app.use(router); app.use(router);
useOrdersStore();
useContractorsStore(); if(localStorage.getItem('piniaState')) {
useCategoriesStore(); pinia.state.value = JSON.parse(localStorage.getItem('piniaState') as string);
useSiteControlStore(); }
watch (
() => pinia.state.value,
(state) => {
localStorage.setItem('piniaState', JSON.stringify(state));
},
{deep: true}
)
export const axiosInstance = axios.create({ export const axiosInstance = axios.create({
@@ -103,6 +111,7 @@ export interface Contractor {
export interface Order { export interface Order {
MZN_Bufor: number, MZN_Bufor: number,
MZN_Anulowane: number,
MZN_DataDos: string, MZN_DataDos: string,
MZN_DataZam: string, MZN_DataZam: string,
MZN_MZNID: number, MZN_MZNID: number,

View File

@@ -1,22 +1,14 @@
import { createRouter, createWebHistory } from 'vue-router'; import { createRouter, createWebHistory } from 'vue-router';
import { MainView, LoginView } from '@/views'; import { MainView, LoginView, SummedOrdersView } from '@/views';
export const router = createRouter({ export const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), history: createWebHistory(import.meta.env.BASE_URL),
linkActiveClass: 'active', linkActiveClass: 'active',
routes: [ routes: [
{ path: '/', component: MainView }, { path: '/', component: MainView },
{ path: '/login', component: LoginView } { path: '/login', component: LoginView },
{ path: '/table', component: SummedOrdersView, },
] ]
}); });
router.beforeEach(async (to) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/login'];
const authRequired = !publicPages.includes(to.path);
//
// if (authRequired) {
// return '/login';
// }
});

View File

@@ -4,40 +4,52 @@ import { type Ref, ref } from 'vue'
import { axiosInstance } from '@/main' import { axiosInstance } from '@/main'
export const useOrdersStore = defineStore('orders', () => { export const useOrdersStore = defineStore('orders', () => {
const orders = ref<Array<Order>>([]); const orders = ref<Array<Order>>();
const order = ref<Order>(); const order = ref<Order>();
const uuid = ref<string>(); const uuid = ref<string>();
const deliveryDate = ref<Date>(); const deliveryDate = ref<Date>();
const orderDate = ref<Date>(); const orderDate = ref<Date>();
async function fetchOrders() { async function fetchOrders() {
orders.value=[];
let ordersTemp : Array<Order> = await fetchOrdersInBuffer();
orders.value.push(...ordersTemp);
ordersTemp = await fetchOrdersOutOfBuffer();
orders.value.push(...ordersTemp);
}
async function fetchOrdersOutOfBuffer() : Promise<Array<Order>> {
const response = await axiosInstance.get('/zamowienia', {withCredentials: true}); const response = await axiosInstance.get('/zamowienia', {withCredentials: true});
const ordersTemp : Array<Order> = response.data; const ordersTemp : Array<Order> = response.data;
return ordersTemp; return ordersTemp;
} }
async function fetchOrdersInBuffer() : Promise<Array<Order>> { async function fetchOrdersByBuffer(inBuffer : boolean | null) {
const response = await axiosInstance.get('/zamowienia/bufor', {withCredentials: true}); let urlString = '/zamowienia';
if(inBuffer != null) {
urlString += '?bufor=' + Number(inBuffer).toString();
}
const response = await axiosInstance.get(urlString, {withCredentials: true});
const ordersTemp : Array<Order> = response.data; const ordersTemp : Array<Order> = response.data;
return ordersTemp; return ordersTemp;
} }
async function fetchOrder(uuid : string) { async function fetchOrdersByDateStartAndEnd(dateStart : Date, dateEnd : Date, inBuffer : boolean | null) {
let urlString = '/zamowienia?od=' + dateStart.toISOString().split('T')[0] + '&do=' + dateEnd.toISOString().split('T')[0]
if(inBuffer != null) {
urlString += '&bufor=' + Number(inBuffer).toString();
}
const response = await axiosInstance.get(urlString, {withCredentials: true});
const ordersTemp : Array<Order> = response.data;
return ordersTemp;
}
async function fetchOrdersByDay(date : Date, inBuffer : boolean | null) {
let urlString = "/zamowienia/" + date.toISOString().split("T")[0];
console.log(urlString);
if(inBuffer != null) {
urlString += '?bufor=' + Number(inBuffer).toString();
}
const response = await axiosInstance.get(urlString, {withCredentials: true});
const ordersTemp : Array<Order> = response.data;
return ordersTemp;
} }
async function loadOrder(uuidString: string, confirmed: boolean, contractor: Ref<Contractor|undefined>, contractors: Ref<Array<Contractor>>, categories: Ref<Array<Category>>) { async function loadOrder(uuidString: string, confirmed: boolean, contractor: Ref<Contractor|undefined>, contractors: Ref<Array<Contractor>>, categories: Ref<Array<Category>>) {
const response = await axiosInstance.get('/zamowienie/' + uuidString); const response = await axiosInstance.get('/zamowienie/' + uuidString);
const tempOrder = response.data; const tempOrder = response.data;
console.log(tempOrder); console.log(tempOrder);
if(confirmed) { if(confirmed) {
@@ -58,8 +70,14 @@ export const useOrdersStore = defineStore('orders', () => {
for(const category of categories.value) { for(const category of categories.value) {
const product = category.Towary.find(product => (product.Twr_TwrId == orderProduct.MZE_TwrId)); const product = category.Towary.find(product => (product.Twr_TwrId == orderProduct.MZE_TwrId));
if(product != undefined && orderProduct.MZE_TwrCena != null) { if(product != undefined && orderProduct.MZE_TwrCena != null) {
product.Twr_Cena = orderProduct.MZE_TwrCena.slice(0, -2); console.log(product);
if(orderProduct.MZE_TwrJm == product.Twr_JM) {
product.Twr_Cena = orderProduct.MZE_TwrCena.slice(0, -2);
} else if(orderProduct.Twr_Cena == product.Twr_JMZ) {
product.Twr_CenaZ = orderProduct.MZE_TwrCena.slice(0, -2);
}
product.Quantity = orderProduct.MZE_TwrIlosc.slice(0, -2); product.Quantity = orderProduct.MZE_TwrIlosc.slice(0, -2);
product.ChosenOption = orderProduct.MZE_TwrJm;
category.isVisible = true; category.isVisible = true;
break; break;
} }
@@ -67,5 +85,5 @@ export const useOrdersStore = defineStore('orders', () => {
} }
} }
return {orders, order, uuid, deliveryDate, orderDate, fetchOrders, fetchOrdersInBuffer, fetchOrdersOutOfBuffer, loadOrder} return {orders, order, uuid, deliveryDate, orderDate, fetchOrders, loadOrder, fetchOrdersByDay, fetchOrdersByBuffer, fetchOrdersByDateStartAndEnd}
}) })

View File

@@ -4,34 +4,42 @@ import { useOrdersStore } from '@/stores/orders.store'
import type { Order } from '@/main' import type { Order } from '@/main'
import { useContractorsStore } from '@/stores/contractors.store' import { useContractorsStore } from '@/stores/contractors.store'
import { useCategoriesStore } from '@/stores/categories.store' import { useCategoriesStore } from '@/stores/categories.store'
import { router } from '@/router/router'
export const useSiteControlStore = defineStore('siteControl', () => { export const useSiteControlStore = defineStore('siteControl', () => {
const isForm = ref<boolean>(true); const shownComponent = ref<string>('mainForm');
const isOrders = ref<boolean>(false);
const showConfirmationModal = ref<boolean>(false); const showConfirmationModal = ref<boolean>(false);
const isDarkTheme = ref<boolean>(false); const isDarkTheme = ref<boolean>(false);
const isLoading = ref<boolean>(true); const isLoading = ref<boolean>(true);
function switchToFrom() { function switchToForm() {
if(!isForm.value) { shownComponent.value = "mainForm";
isForm.value = true; if(router.currentRoute.value.fullPath != "/") {
isOrders.value = false; router.push("/");
} }
} }
async function switchToOrders() { async function switchToOrders() {
if(!isOrders.value) { if(shownComponent.value != 'orderSelector') {
const orderStore = useOrdersStore(); const orderStore = useOrdersStore();
const { orders } = storeToRefs(orderStore); const { orders } = storeToRefs(orderStore);
isLoading.value = true; isLoading.value = true;
isForm.value = false; shownComponent.value = "orderSelector"
isOrders.value = true;
orders.value = new Array<Order>(); orders.value = new Array<Order>();
orders.value.push(... await orderStore.fetchOrdersInBuffer()); orders.value = await orderStore.fetchOrders();
orders.value.push(... await orderStore.fetchOrdersOutOfBuffer());
isLoading.value = false; isLoading.value = false;
} }
if(router.currentRoute.value.fullPath != "/") {
router.push("/");
}
}
async function switchToTable() {
if(router.currentRoute.value.fullPath != "/table") {
shownComponent.value = "table"
router.push("/table");
}
} }
function checkTheme() { function checkTheme() {
@@ -42,15 +50,31 @@ export const useSiteControlStore = defineStore('siteControl', () => {
const orderStore = useOrdersStore(); const orderStore = useOrdersStore();
const contractorsStore = useContractorsStore(); const contractorsStore = useContractorsStore();
const categoriesStore = useCategoriesStore(); const categoriesStore = useCategoriesStore();
isForm.value = true; shownComponent.value = "mainForm";
isOrders.value = false;
isLoading.value = true; isLoading.value = true;
window.scrollTo(0, 0); window.scrollTo(0, 0);
await categoriesStore.fetchCategories();
const { contractor, contractors } = storeToRefs(contractorsStore); const { contractor, contractors } = storeToRefs(contractorsStore);
const { categories } = storeToRefs(categoriesStore); const { categories } = storeToRefs(categoriesStore);
await orderStore.loadOrder(uuid, false, contractor, contractors, categories); await orderStore.loadOrder(uuid, false, contractor, contractors, categories);
isLoading.value=false; isLoading.value=false;
} }
return {isForm, isOrders, isLoading, showConfirmationModal, isDarkTheme, switchToFrom, switchToOrders, checkTheme, viewOrder}; function newOrder() {
const ordersStore = useOrdersStore();
const contractorsStore = useContractorsStore();
const categoriesStore = useCategoriesStore();
const { order, uuid, deliveryDate, orderDate } = storeToRefs(ordersStore);
const { contractor } = storeToRefs(contractorsStore);
contractor.value = undefined;
order.value = undefined;
uuid.value = undefined;
deliveryDate.value = undefined;
orderDate.value = undefined;
categoriesStore.fetchCategories();
switchToForm();
window.scrollTo(0, 0);
}
return {isLoading, showConfirmationModal, isDarkTheme, shownComponent, switchToForm, switchToOrders, switchToTable, checkTheme, viewOrder, newOrder};
}) })

View File

@@ -12,15 +12,12 @@ const schema = Yup.object().shape({
}); });
async function onSubmit(values : any, { setErrors } : any) { async function onSubmit(values : any, { setErrors } : any) {
const { username, password, errors } = values; const { username, password } = values;
console.log(username + ' ' + password);
const body = await axiosInstance.post('/login', { const body = await axiosInstance.post('/login', {
username: username, username: username,
password: password password: password
}).catch ((error) => { }).catch ((error) => {
console.log(error.response);
if(error.response.status == 401) { if(error.response.status == 401) {
setErrors({ apiError: "unauthorized" }) setErrors({ apiError: "unauthorized" })
} }
@@ -77,7 +74,3 @@ async function onSubmit(values : any, { setErrors } : any) {
</div> </div>
</template> </template>
<style scoped>
</style>

View File

@@ -4,23 +4,24 @@
<div v-if="isLoading"> <div v-if="isLoading">
<LoadingComponent/> <LoadingComponent/>
</div> </div>
<div v-else> <div>
<div v-if="isForm"> <div v-if="shownComponent == 'mainForm'">
<MainForm <MainForm
v-if="order == undefined || order.MZN_Bufor==1" v-if="order == undefined || order.MZN_Bufor==1"
/> />
<ConfirmedForm v-else-if="order.MZN_Bufor==0"/> <ConfirmedForm v-else-if="order.MZN_Bufor==0"/>
</div> </div>
<OrdersSelector class="box is-shadowless" v-else-if="isOrders" <OrdersSelector class="box is-shadowless" v-else-if="shownComponent == 'orderSelector'"
/> />
</div> </div>
<ConfirmationModal v-show="showConfirmationModal" @close="showConfirmationModal = false" @confirm="closeConfirmationModal" :order-uuid="uuid"></ConfirmationModal> <ConfirmationModal v-show="showConfirmationModal" @close="showConfirmationModal = false" @confirm="closeConfirmationModal" :order-uuid="uuid"></ConfirmationModal>
<button class="button" @click="test">test</button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import '@/assets/base.css' import '@/assets/base.css'
import { useContractorsStore } from '@/stores/contractors.store' import { useContractorsStore } from '@/stores/contractors.store'
import { storeToRefs } from 'pinia' import { getActivePinia, storeToRefs } from 'pinia'
import { useCategoriesStore } from '@/stores/categories.store' import { useCategoriesStore } from '@/stores/categories.store'
import { useOrdersStore } from '@/stores/orders.store' import { useOrdersStore } from '@/stores/orders.store'
import { useSiteControlStore } from '@/stores/siteControl.store' import { useSiteControlStore } from '@/stores/siteControl.store'
@@ -36,7 +37,7 @@ const contractor = storeToRefs(contractorsStore).contractor;
const categories = storeToRefs(categoriesStore).categories; const categories = storeToRefs(categoriesStore).categories;
const { uuid, order } = storeToRefs(ordersStore); const { uuid, order } = storeToRefs(ordersStore);
const { username } = storeToRefs(userStore); const { username } = storeToRefs(userStore);
const { isForm, isOrders, showConfirmationModal, isLoading } = storeToRefs(siteControlStore); const { isForm, isOrders, showConfirmationModal, isLoading, shownComponent } = storeToRefs(siteControlStore);
async function fetchData() { async function fetchData() {
@@ -49,6 +50,10 @@ async function fetchData() {
isLoading.value = false; isLoading.value = false;
} }
function test() {
console.log(getActivePinia());
}
function closeConfirmationModal() { function closeConfirmationModal() {
showConfirmationModal.value = false; showConfirmationModal.value = false;
if (uuid.value != undefined) { if (uuid.value != undefined) {
@@ -57,6 +62,7 @@ function closeConfirmationModal() {
} }
} }
console.log(localStorage.getItem('piniaState'));
siteControlStore.checkTheme(); siteControlStore.checkTheme();
fetchData(); fetchData();
</script> </script>

View File

@@ -0,0 +1,90 @@
<script setup lang="ts">
import { useOrdersStore } from '@/stores/orders.store'
import { storeToRefs } from 'pinia'
import { useRoute } from 'vue-router'
import NavBar from '@/components/NavBar.vue'
import VueDatePicker from '@vuepic/vue-datepicker'
import { useSiteControlStore } from '@/stores/siteControl.store'
import { ref } from 'vue'
const ordersStore = useOrdersStore();
const siteControlStore = useSiteControlStore();
const { orders } = storeToRefs(ordersStore);
const { isDarkTheme } = storeToRefs(siteControlStore);
const searchDate = ref<Date>();
const confirmedOrders = ref<boolean>();
orders.value = await ordersStore.fetchOrdersByDay(new Date(Date.now()), null);
const route = useRoute();
console.log(route);
async function fetchOrders() {
console.log((confirmedOrders.value) ? true : null);
orders.value = await ordersStore.fetchOrdersByDateStartAndEnd(searchDate.value != undefined ? searchDate.value : new Date(Date.now()),
searchDate.value != undefined ? searchDate.value : new Date(Date.now()),
(confirmedOrders.value) ? true : null);
}
</script>
<template>
<NavBar/>
<div class="columns box is-shadowless">
<div class="column box mr-3">
<h1 class="title is-4 mb-3">Opcje</h1>
<label class="label is-small">Data dostawy</label>
<VueDatePicker v-model="searchDate"
:enable-time-picker="false"
:clearable="true"
input-class-name="input is-small calendar-background"
menu-class-name="calendar-background"
v-bind:dark = "isDarkTheme" />
<div class="control mt-3">
<label class="checkbox mr-5">
<input type="checkbox" v-model="confirmedOrders"/>
Tylko potwierdzone zamówienia?
</label>
</div>
<button class="button mt-3" @click="fetchOrders">Potwierdź</button>
</div>
<div class="column is-four-fifths is-flex is-align-content-center box is-justify-content-center">
<table class="table blackBorder">
<thead>
<tr class="has-background-grey-light">
<th>Nazwa produktu</th>
<th>Ilość</th>
<th>Jednostka miary</th>
<th>Cena jednostkowa</th>
<th>Cena całkowita</th>
</tr>
</thead>
<tbody v-for="order in orders" :key="order.MZN_UUID">
<tr class="has-background-grey-lighter">
<th colspan="5">
{{ order.MZN_PodNazwa1 + order.MZN_PodNazwa2 + order.MZN_PodNazwa3 + order.MZN_DataDos.toString()}}
</th>
</tr>
<tr v-for="product in order.MZamElem" :key="product.MZE_MZEID">
<th>{{ product.MZE_TwrNazwa }}</th>
<th>{{ Number(product.MZE_TwrIlosc).toFixed(2) }}</th>
<th>{{ product.MZE_TwrJm }}</th>
<th>{{ Number(product.MZE_TwrCena).toFixed(2) }}</th>
<th>{{ (Number(product.MZE_TwrCena) * Number(product.MZE_TwrIlosc)).toFixed(2) }}</th>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<style scoped>
.blackBorder {
--bulma-table-cell-border-color : black;
}
</style>

View File

@@ -1,2 +1,3 @@
export { default as LoginView } from "./LoginView.vue"; export { default as LoginView } from "./LoginView.vue";
export { default as MainView } from "./MainView.vue"; export { default as MainView } from "./MainView.vue";
export { default as SummedOrdersView } from "./SummedOrdersView.vue"