Compare commits
18 Commits
modal
...
components
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d0d27b502 | |||
| eeac03235b | |||
| 8140233e3a | |||
| d7e28cd926 | |||
| ce89b79074 | |||
| feee47f464 | |||
| ff3b22fb1b | |||
| bbec759b08 | |||
| 200242252c | |||
| 673eb10b7b | |||
| 15271a873b | |||
| dce8e294c5 | |||
| 2a06bb27ab | |||
| 87c8579e9e | |||
| 93c015fcb7 | |||
| 2fecc061e2 | |||
| a289c8dd0f | |||
| a3ec0fa06d |
29
components.d.ts
vendored
Normal file
29
components.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
CancelationModal: typeof import('./src/components/CancelationModal.vue')['default']
|
||||
Column: typeof import('primevue/column')['default']
|
||||
ConfirmationModal: typeof import('./src/components/confirmationModal.vue')['default']
|
||||
ConfirmedForm: typeof import('./src/components/ConfirmedForm.vue')['default']
|
||||
DataTable: typeof import('primevue/datatable')['default']
|
||||
IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
|
||||
IconDocumentation: typeof import('./src/components/icons/IconDocumentation.vue')['default']
|
||||
IconEcosystem: typeof import('./src/components/icons/IconEcosystem.vue')['default']
|
||||
IconSupport: typeof import('./src/components/icons/IconSupport.vue')['default']
|
||||
IconTooling: typeof import('./src/components/icons/IconTooling.vue')['default']
|
||||
LoadingComponent: typeof import('./src/components/LoadingComponent.vue')['default']
|
||||
LoginModal: typeof import('./src/components/LoginModal.vue')['default']
|
||||
MainForm: typeof import('./src/components/MainForm.vue')['default']
|
||||
NavBar: typeof import('./src/components/NavBar.vue')['default']
|
||||
OrdersSelector: typeof import('./src/components/OrdersSelector.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SummaryComponent: typeof import('./src/components/SummaryComponent.vue')['default']
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vite App</title>
|
||||
<title>Mleczarnia Kuzma</title>
|
||||
</head>
|
||||
<body>
|
||||
<body class="has-navbar-fixed-top">
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
||||
1452
package-lock.json
generated
1452
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@@ -13,13 +13,23 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
||||
"@primevue/themes": "^4.0.4",
|
||||
"@vuepic/vue-datepicker": "^8.7.0",
|
||||
"axios": "^1.7.2",
|
||||
"bulma": "^1.0.1",
|
||||
"cors": "^2.8.5",
|
||||
"pinia": "^2.1.7",
|
||||
"primevue": "^4.0.4",
|
||||
"vee-validate": "^4.13.1",
|
||||
"vue": "^3.4.21",
|
||||
"vue-router": "^4.3.0"
|
||||
"vue-router": "^4.3.3",
|
||||
"vue3-cookies": "^1.0.6",
|
||||
"vue3-print-nb": "^0.1.4",
|
||||
"yup": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@primevue/auto-import-resolver": "^4.0.4",
|
||||
"@rushstack/eslint-patch": "^1.8.0",
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@types/node": "^20.12.5",
|
||||
@@ -33,6 +43,7 @@
|
||||
"prettier": "^3.2.5",
|
||||
"sass": "^1.77.2",
|
||||
"typescript": "~5.4.0",
|
||||
"unplugin-vue-components": "^0.27.3",
|
||||
"vite": "^5.2.8",
|
||||
"vue-tsc": "^2.0.11"
|
||||
}
|
||||
|
||||
381
src/App.vue
381
src/App.vue
@@ -1,376 +1,27 @@
|
||||
<template>
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item">
|
||||
<h3 class="title is-3">Mleczarnia</h3>
|
||||
</a>
|
||||
<button @click="makeBurger" class="button navbar-burger" data-target="navMenu" v-bind:class="{ 'is-active': activator }">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu" id="navMenu" v-bind:class="{ 'is-active': activator }">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" @click="switchToFrom">
|
||||
Formularz
|
||||
</a>
|
||||
|
||||
<a class="navbar-item" @click="switchToOrders">
|
||||
Zamówienia
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<a class="button is-light">
|
||||
Log in
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div v-if="isForm">
|
||||
<form class="box" @submit="createJSON">
|
||||
<div class="mb-3">
|
||||
<div class="box">
|
||||
<h1 class="is-large mb-3"><b>ZAMÓWIENIE</b></h1>
|
||||
<h1 class="is-large mb-3" v-if="uuid != null" ><b>{{ uuid }}</b></h1>
|
||||
<div class="field mb-5">
|
||||
<label class="label is-small">NIP</label>
|
||||
<div class="field">
|
||||
<div class="select is-small is-expanded" style="width: 100%">
|
||||
<select v-model="contractor" class="is-expanded" style="width: 100%" required>
|
||||
<option class="is-expanded" v-for="contractor in contractors" :key="contractor" :value=contractor.Knt_KntId>{{ contractor.Knt_NipE + ', ' + contractor.Knt_Miasto + ', ' + contractor.Knt_Nazwa1 + ' ' + contractor.Knt_Nazwa2 + ' ' + contractor.Knt_Nazwa3 }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label is-small">Data dostawy</label>
|
||||
<div class="field is-small">
|
||||
<VueDatePicker class ="bulma-is-small"
|
||||
v-model="deliveryDate"
|
||||
:enable-time-picker="false"
|
||||
:clearable="true"
|
||||
input-class-name="input is-small"
|
||||
required/>
|
||||
</div>
|
||||
</div>
|
||||
<button class="button is-primary mt-5">Submit</button>
|
||||
<button class="button is-primary mt-5 ml-3" @click="showModal = true">Potwierdź</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="(kategoria, index) in wares" :key="kategoria.Kod">
|
||||
<div class="box" >
|
||||
<h1 class="is-large mb-3"><b>{{ kategoria.Kod }}</b></h1>
|
||||
<div class="field" v-for="(ware, index) in kategoria.Towary" :key="ware.Twr_Nazwa">
|
||||
<label class="label is-small">{{ ware.Twr_Nazwa }}</label>
|
||||
<div class="columns is-mobile">
|
||||
<div class="column" v-if="ware.chosenOption == ware.Twr_JM">
|
||||
<div class="field">
|
||||
<input
|
||||
class="input is-small"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
v-model="ware.Twr_Cena"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" v-else-if="ware.chosenOption == ware.Twr_JMZ">
|
||||
<div class="field">
|
||||
<input
|
||||
class="input is-small"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
v-model="ware.Twr_CenaZ"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="field has-addons">
|
||||
<p class="control">
|
||||
<span class="select is-small">
|
||||
<select v-model="ware.chosenOption" readonly>
|
||||
<option v-for="option in ware.Options" :key="option">{{ option }}</option>
|
||||
</select>
|
||||
</span>
|
||||
</p>
|
||||
<p class="control is-expanded">
|
||||
<input class="input is-small" type="text" placeholder="Ilość" v-model="ware.Quantity">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!(index == kategoria.Towary.length - 1)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3" v-if="!(index == wares.length - 1)"></div>
|
||||
</div>
|
||||
<button class="button is-primary mt-3 is-large is-fullwidth">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="box is-shadowless" v-else-if="isOrders">
|
||||
<form class="mb-3">
|
||||
<div class="box">
|
||||
<h1 class="is-large mb-3"><b>FILTR ZAMÓWIEŃ</b></h1>
|
||||
<div class="field mb-5">
|
||||
<label class="label is-small">Data zamówienia</label>
|
||||
<div class="field is-small">
|
||||
<VueDatePicker v-model="searchOrderDate"
|
||||
:enable-time-picker="false"
|
||||
:clearable="true"
|
||||
input-class-name="input is-small"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mb-5">
|
||||
<label class="label is-small">Zamówienie potwierdzone?</label>
|
||||
<div class="control">
|
||||
<label class="checkbox mr-5">
|
||||
<input type="checkbox" v-model="isOutOfBufor"/>
|
||||
Tak
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-model="isInBufor"/>
|
||||
Nie
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="button is-primary is-small is-expanded" @click="createJSON">Pobierz zamówienia</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="box">
|
||||
<h1 class="is-large mb-3"><b>ZAMÓWIENIA</b></h1>
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-4" v-for="order in orders" :key="order.MZN_UUID">
|
||||
<div class="box">
|
||||
<h1 class="mb-3 is-size-7"><b>{{ order.MZN_UUID }}</b></h1>
|
||||
<label class="label is-small">Klient</label>
|
||||
<div class="field is-small mb-3">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
:value="order.MZN_PodNazwa1 + order.MZN_PodNazwa2 + order.MZN_PodNazwa3"
|
||||
readonly/>
|
||||
</div>
|
||||
<div class="columns is-mobile field is-small mb-0">
|
||||
<div class="column is-6">
|
||||
<label class="label is-small">Data dostawy</label>
|
||||
<div class="field is-small">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
v-model="order.MZN_DataDos"
|
||||
readonly/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-6">
|
||||
<label class="label is-small">Data zamówienia</label>
|
||||
<div class="field is-small">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
v-model="order.MZN_DataZam.split('T')[0]"
|
||||
readonly/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="label is-small">Zamówienie potwierdzone?</label>
|
||||
<div class="field is-small mb-3" v-if="order.MZN_Bufor==0">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
value="Tak"
|
||||
readonly/>
|
||||
</div>
|
||||
<div class="field is-small mb-3" v-else>
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
value="Nie"
|
||||
readonly/>
|
||||
</div>
|
||||
<button class="button is-primary is-small is-expanded" @click="viewOrder" :name="order.MZN_UUID">Podgląd</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ConfirmationModal v-show="showModal" @close="showModal = false" :order-uuid="uuid"></ConfirmationModal>
|
||||
<RouterView class="has-navbar-fixed-top"/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import './assets/style.scss';
|
||||
import { ref } from 'vue';
|
||||
import ConfirmationModal from '@/components/ConfirmationModal.vue';
|
||||
<script setup lang="ts">
|
||||
import './assets/style.scss'
|
||||
import './assets/print.css'
|
||||
import { RouterView } from 'vue-router'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
|
||||
export default {
|
||||
components: { ConfirmationModal },
|
||||
data() {
|
||||
return {
|
||||
contractors: [],
|
||||
contractor: {},
|
||||
wares: [],
|
||||
orders: ref(new Array<Object>),
|
||||
order: ref(),
|
||||
deliveryDate: ref(),
|
||||
searchOrderDate: ref(null),
|
||||
isInBufor: ref(false),
|
||||
isOutOfBufor: ref(false),
|
||||
uuid: ref(),
|
||||
activator: ref(false),
|
||||
isForm: ref(true),
|
||||
isOrders: ref(false),
|
||||
showModal: ref(false)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isInBufor(val) {
|
||||
if(val == true && val == this.isOutOfBufor) {
|
||||
this.isOutOfBufor = false;
|
||||
}
|
||||
},
|
||||
isOutOfBufor(val) {
|
||||
if(val == true && val == this.isInBufor) {
|
||||
this.isInBufor = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetchData() {
|
||||
const response1 = await fetch('https://zamowienia.mleczarnia-kuzma.pl/api/kontrahenci');
|
||||
this.contractors = await response1.json();
|
||||
console.log(this.contractors);
|
||||
const response2 = await fetch('https://zamowienia.mleczarnia-kuzma.pl/api/towary');
|
||||
this.wares = await response2.json();
|
||||
console.log(this.wares);
|
||||
for (let kategoria of this.wares) {
|
||||
for (let ware of kategoria.Towary) {
|
||||
ware.Options = new Array(ware.Twr_JM);
|
||||
ware.chosenOption = ware.Twr_JM;
|
||||
if (ware.Twr_JMZ != null) {
|
||||
ware.Options.push(ware.Twr_JMZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
const response3 = await fetch('https://zamowienia.mleczarnia-kuzma.pl/api/zamowienia/bufor');
|
||||
let ordersTemp : Array<Object> = await response3.json();
|
||||
this.orders.push(...ordersTemp);
|
||||
const response4 = await fetch('https://zamowienia.mleczarnia-kuzma.pl/api/zamowienia');
|
||||
ordersTemp = await response4.json();
|
||||
this.orders.push(...ordersTemp);
|
||||
console.log(this.orders);
|
||||
},
|
||||
createJSON(event: Event) {
|
||||
event.preventDefault();
|
||||
console.log(this.contractor);
|
||||
const json = {
|
||||
MZN_UUID: this.uuid,
|
||||
MZN_DataZam: new Date(Date.now()).toISOString(),
|
||||
MZN_DataDos: this.deliveryDate != null ? this.deliveryDate.toISOString() : null,
|
||||
MZN_PodID: this.contractor,
|
||||
MZamElem: new Array()
|
||||
};
|
||||
for (let category of this.wares) {
|
||||
for (let ware of category.Towary) {
|
||||
if(ware.Quantity != null) {
|
||||
ware.Options = new Array(ware.Twr_JM);
|
||||
ware.chosenOption = ware.Twr_JM;
|
||||
if (ware.Twr_JMZ != null) {
|
||||
ware.Options.push(ware.Twr_JMZ);
|
||||
}
|
||||
const wareObject = {
|
||||
MZE_TwrId: ware.Twr_TwrId,
|
||||
MZE_TwrJM: ware.chosenOption,
|
||||
MZE_TwrCena: ware.chosenOption == ware.Twr_JMZ ? ware.Twr_CenaZ : ware.Twr_Cena,
|
||||
MZE_TwrIlosc: ware.Quantity
|
||||
}
|
||||
json.MZamElem.push(wareObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(JSON.stringify(json));
|
||||
fetch('https://zamowienia.mleczarnia-kuzma.pl/api/zamowienie', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(json)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(response => this.uuid = response.MZN_UUID)
|
||||
},
|
||||
parseOrderJSON(event: Event) {
|
||||
event.preventDefault();
|
||||
const json = "{\"MZN_UUID\":\"55ca3087-38c0-445f-ab7e-7e566c68c0d4\",\"MZN_DataZam\":1704063600000,\"MZN_DataDos\":1717493437880,\"MZN_PodID\":194,\"MZamElem\":[{\"MZE_TwrId\":1833,\"MZE_TwrJM\":\"kg\",\"MZE_TwrCena\":\"16.00\",\"MZN_TwrIlosc\":2},{\"MZE_TwrId\":1837,\"MZE_TwrJM\":\"kg\",\"MZE_TwrCena\":\"16.10\",\"MZN_TwrIlosc\":4}]}";
|
||||
const parsedJson = JSON.parse(json);
|
||||
console.log(this.deliveryDate.toJSON());
|
||||
console.log(this.contractor);
|
||||
fetch('https://zamowienia.mleczarnia-kuzma.pl/api/zamowienie/' + this.uuid, {
|
||||
method: 'PUT'
|
||||
})
|
||||
},
|
||||
async viewOrder(event: Event) {
|
||||
console.log(event.target.name);
|
||||
let tempOrder = this.orders.find(order => (order.MZN_UUID == event.target.name));
|
||||
console.log(tempOrder);
|
||||
const response = await fetch('https://zamowienia.mleczarnia-kuzma.pl/api/zamowienie/' + tempOrder.MZN_UUID);
|
||||
let order = await response.json();
|
||||
this.uuid = order.MZN_UUID;
|
||||
this.contractor = order.MZN_PodID;
|
||||
this.deliveryDate = new Date(order.MZN_DataDos);
|
||||
console.log(order);
|
||||
for(let product of order.MZamElem){
|
||||
for(let kategoria of this.wares) {
|
||||
let towar = kategoria.Towary.find(ware => (ware.Twr_TwrId == product.MZE_TwrId));
|
||||
if(towar != null) {
|
||||
console.log('ten towar ' + towar);
|
||||
towar.Twr_Cena = product.MZE_TwrCena.slice(0, -2);
|
||||
towar.Quantity = product.MZE_TwrIlosc.slice(0, -2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.isForm = true;
|
||||
this.isOrders = false;
|
||||
window.scrollTo(0, 0);
|
||||
},
|
||||
makeBurger () {
|
||||
this.activator = !this.activator
|
||||
return this.activator
|
||||
},
|
||||
switchToFrom() {
|
||||
if(!this.isForm) {
|
||||
this.isForm = true;
|
||||
this.isOrders = false;
|
||||
if(this.activator) {
|
||||
this.activator = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
switchToOrders() {
|
||||
if(!this.isOrders) {
|
||||
this.isForm = false;
|
||||
this.isOrders = true;
|
||||
if(this.activator) {
|
||||
this.activator = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
// const categoriesStore = useCategoriesStore();
|
||||
// await categoriesStore.fetchCategories();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
min-height: 100vh;
|
||||
@media screen and (min-width: 500px) {
|
||||
.box {
|
||||
--bulma-box-padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
body {
|
||||
min-height: 100vh;
|
||||
@media screen and (max-width: 500px) {
|
||||
.box {
|
||||
--bulma-box-padding: 0.75rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition:
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.blackBorder {
|
||||
--bulma-table-cell-border-color : black;
|
||||
}
|
||||
|
||||
.tableOverflow {
|
||||
overflow-x: scroll;
|
||||
display: block;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
|
||||
8
src/assets/print.css
Normal file
8
src/assets/print.css
Normal file
@@ -0,0 +1,8 @@
|
||||
.blackBorder {
|
||||
--bulma-table-cell-border-color : black;
|
||||
}
|
||||
|
||||
.tableOverflow {
|
||||
overflow-x: scroll;
|
||||
display: block;
|
||||
}
|
||||
@@ -1,3 +1,22 @@
|
||||
@import 'node_modules/bulma/bulma.scss';
|
||||
@import '/home/patryk/WebstormProjects/Zamowienia-UI/node_modules/bulma/sass/utilities/mixins';
|
||||
|
||||
|
||||
.element {
|
||||
&.is-loading {
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
opacity: 1;
|
||||
&:after {
|
||||
@include loader;
|
||||
position: absolute;
|
||||
top: calc(50% - 1em);
|
||||
left: calc(50% - 1em);
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
border-width: 0.25em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$primary-color: #111111;
|
||||
45
src/components/CancelationModal.vue
Normal file
45
src/components/CancelationModal.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { axiosInstance } from '@/main'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
|
||||
const ordersStore = useOrdersStore();
|
||||
const siteControlStore = useSiteControlStore();
|
||||
const contractorStore = useContractorsStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
|
||||
const { uuid } = storeToRefs(ordersStore);
|
||||
const { showCancellationModal, isLoading } = storeToRefs(siteControlStore);
|
||||
|
||||
async function cancelOrder() {
|
||||
showCancellationModal.value = false;
|
||||
axiosInstance.delete('/zamowienie/' + uuid.value);
|
||||
siteControlStore.newOrder(true);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="modal is-active">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card p-3">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">Uwaga</p>
|
||||
<button class="delete" aria-label="close" @click="$emit('close')"></button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
Czy napewno chcesz anulować zamówienie? Czynności tej nie można odwrócić.
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
<div class="buttons">
|
||||
<button class="button is-success" @click="cancelOrder">Tak</button>
|
||||
<button class="button" @click="$emit('close')">Nie</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,17 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
const emit = defineEmits(['close']);
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { axiosInstance } from '@/main'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useRoutesStore } from '@/stores/routes.store'
|
||||
|
||||
const props = defineProps(
|
||||
{
|
||||
orderUuid : String
|
||||
const ordersStore = useOrdersStore();
|
||||
const siteControlStore = useSiteControlStore();
|
||||
const contractorStore = useContractorsStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
const routeStore = useRoutesStore();
|
||||
|
||||
const { contractor, contractors } = storeToRefs(contractorStore);
|
||||
const { categories } = storeToRefs(categoriesStore);
|
||||
const { uuid } = storeToRefs(ordersStore);
|
||||
const { showConfirmationModal, isLoading} = storeToRefs(siteControlStore);
|
||||
const { route, routes } = storeToRefs(routeStore);
|
||||
|
||||
async function confirmOrder() {
|
||||
await axiosInstance.put('/zamowienie/' + uuid.value);
|
||||
showConfirmationModal.value = false;
|
||||
if (uuid.value != undefined && route.value != undefined) {
|
||||
isLoading.value = true;
|
||||
await ordersStore.loadOrder(uuid.value, true, contractor, contractors, categories, route, routes);
|
||||
isLoading.value = false;
|
||||
}
|
||||
);
|
||||
|
||||
function confirmOrder() {
|
||||
emit('close');
|
||||
fetch('https://zamowienia.mleczarnia-kuzma.pl/api/zamowienie/' + props.orderUuid, {
|
||||
method: 'PUT'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -36,8 +52,4 @@ function confirmOrder() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</template>
|
||||
147
src/components/ConfirmedForm.vue
Normal file
147
src/components/ConfirmedForm.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<script setup lang="ts">
|
||||
import VueDatePicker from '@vuepic/vue-datepicker'
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { axiosInstance } from '@/main'
|
||||
import { useRoutesStore } from '@/stores/routes.store'
|
||||
|
||||
const ordersStore = useOrdersStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
const contractorsStore = useContractorsStore();
|
||||
const routeStore = useRoutesStore();
|
||||
|
||||
const { order, uuid} = storeToRefs(ordersStore);
|
||||
|
||||
const { categories } = storeToRefs(categoriesStore);
|
||||
|
||||
const { contractor } = storeToRefs(contractorsStore);
|
||||
|
||||
const { route } = storeToRefs(routeStore);
|
||||
|
||||
function cancelOrder(event: Event) {
|
||||
event.preventDefault();
|
||||
axiosInstance.delete('/zamowienie/' + uuid.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="box is-shadowless">
|
||||
<div class="mb-3">
|
||||
<div class="box">
|
||||
<h1 class="title mb-3 is-6"><b>ZAMÓWIENIE</b></h1>
|
||||
<h1 class="subtitle is-6 mb-3" v-if="uuid != null" ><b>{{ uuid }}</b></h1>
|
||||
<div class="field mb-3" v-if="contractor != undefined">
|
||||
<label class="label is-small">Klient</label>
|
||||
<div class="field is-small mb-3">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
:value="contractor.Knt_Nazwa1 + contractor.Knt_Nazwa2 + contractor.Knt_Nazwa3"
|
||||
readonly/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mb-3" v-if="order != undefined">
|
||||
<label class="label is-small">Data dostawy</label>
|
||||
<div class="field is-small">
|
||||
<VueDatePicker
|
||||
v-model="order.MZN_DataDos"
|
||||
:enable-time-picker="false"
|
||||
:clearable="true"
|
||||
input-class-name="input is-small calendar-background is-static"
|
||||
menu-class-name="calendar-background"
|
||||
readonly
|
||||
hide-input-icon/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mb-3" v-if="order != undefined">
|
||||
<label class="label is-small">Data zamówienia</label>
|
||||
<div class="field is-small">
|
||||
<VueDatePicker
|
||||
v-model="order.MZN_DataZam"
|
||||
:enable-time-picker="false"
|
||||
:clearable="true"
|
||||
input-class-name="input is-small calendar-background is-static"
|
||||
menu-class-name="calendar-background"
|
||||
readonly
|
||||
hide-input-icon/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mb-3" v-if="route != undefined">
|
||||
<label class="label is-small">Trasa</label>
|
||||
<div class="field is-small mb-3">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
:value="route.MZT_Nazwa1"
|
||||
readonly/>
|
||||
</div>
|
||||
</div>
|
||||
<button class="button is-danger" @click="cancelOrder">Anuluj zamówienie</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="category in categories" :key="category.Kod">
|
||||
<div class="box mb-3" v-if="category.isVisible">
|
||||
<h1 class="title mb-3 is-6"><b>{{ category.Kod }}</b></h1>
|
||||
<div class="field" v-for="(product) in category.Towary" :key="product.Twr_Nazwa">
|
||||
<div v-if="Number(product.Quantity) > 0" class="mb-3">
|
||||
<label class="label is-small">{{ product.Twr_Nazwa }}</label>
|
||||
<div class="columns is-mobile">
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<p class="control is-expanded">
|
||||
<input class="input is-small is-static" type="text" placeholder="Ilość" :value="product.Quantity + ' ' + product.ChosenOption" readonly>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" v-if="product.ChosenOption == product.Twr_JM">
|
||||
<div class="field">
|
||||
<input
|
||||
class="input is-small is-static"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
:value="product.Twr_Cena + ' PLN'"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" v-else-if="product.ChosenOption == product.Twr_JMZ">
|
||||
<div class="field">
|
||||
<input
|
||||
class="input is-small is-static"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
:value="product.Twr_CenaZ + ' PLN'"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" v-if="product.ChosenOption == product.Twr_JM">
|
||||
<div class="field">
|
||||
<input
|
||||
class="input is-small is-static"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
:value="(Number(product.Twr_Cena) * Number(product.Quantity)).toFixed(2) + ' PLN'"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" v-else-if="product.ChosenOption == product.Twr_JMZ">
|
||||
<div class="field">
|
||||
<input
|
||||
class="input is-small is-static"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
:value="(Number(product.Twr_CenaZ) * Number(product.Quantity)).toFixed(2) + ' PLN'"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
12
src/components/LoadingComponent.vue
Normal file
12
src/components/LoadingComponent.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="box">
|
||||
<div class="box is-skeleton m-3" style="height: 40vh"></div>
|
||||
<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>
|
||||
|
||||
</template>
|
||||
46
src/components/LoginModal.vue
Normal file
46
src/components/LoginModal.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<script setup lang="ts">
|
||||
import { axiosInstance } from '@/main'
|
||||
import type { VueCookies } from 'vue3-cookies/dist/interfaces'
|
||||
import { inject } from 'vue'
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
function sendLogin() {
|
||||
emit('close');
|
||||
axiosInstance.post('/login', {
|
||||
username: 'testowyj',
|
||||
password: 'beihiegei5Fied0b'
|
||||
}, {
|
||||
withCredentials: true
|
||||
});
|
||||
|
||||
const $cookies = inject<VueCookies>('$cookies');
|
||||
console.log($cookies);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="modal is-active">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card p-3">
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">Logowanie</p>
|
||||
<button class="delete" aria-label="close" @click="$emit('close')"></button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<form>
|
||||
|
||||
</form>
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
<div class="buttons">
|
||||
<button class="button is-success" @click="sendLogin">Zaloguj się</button>
|
||||
<button class="button" @click="$emit('close')">Anuluj</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
412
src/components/MainForm.vue
Normal file
412
src/components/MainForm.vue
Normal file
@@ -0,0 +1,412 @@
|
||||
<script setup lang="ts">
|
||||
import VueDatePicker from '@vuepic/vue-datepicker';
|
||||
import { axiosInstance, type Contractor, type OrderProduct, type Route } from '@/main'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { useRoutesStore } from '@/stores/routes.store'
|
||||
|
||||
const categoriesStore = useCategoriesStore();
|
||||
const contractorsStore = useContractorsStore();
|
||||
const ordersStore = useOrdersStore();
|
||||
const siteControlStore = useSiteControlStore();
|
||||
const routesStore = useRoutesStore();
|
||||
|
||||
const { contractor, contractors } = storeToRefs(contractorsStore);
|
||||
const { deliveryDate, uuid, additionalNotes } = storeToRefs(ordersStore);
|
||||
const { categories } = storeToRefs(categoriesStore);
|
||||
const { showConfirmationModal, showCancellationModal, isDarkTheme } = storeToRefs(siteControlStore);
|
||||
const { route, routes } = storeToRefs(routesStore);
|
||||
|
||||
const contractorSearch = ref<string>();
|
||||
const filteredContractors = ref<Array<Contractor>>();
|
||||
const showContractorsDropdown = ref<boolean>(false);
|
||||
const contractorInput = ref(null);
|
||||
|
||||
const routeSearch = ref<string>();
|
||||
const filteredRoutes = ref<Array<Route>>();
|
||||
const showRoutesDropdown = ref<boolean>(false);
|
||||
const routeInput = ref(null);
|
||||
|
||||
const showErrorNotification = ref<boolean>(false);
|
||||
const showSuccessNotification = ref<boolean>(false);
|
||||
const errorNotificationMessage = ref<string>();
|
||||
const successNotificationMessage = ref<string>();
|
||||
|
||||
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 });
|
||||
|
||||
watch(route, (route) => {
|
||||
if(route == undefined) {
|
||||
routeSearch.value = '';
|
||||
} else {
|
||||
routeSearch.value = route.MZT_Nazwa1;
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
function createJSON(event: Event) {
|
||||
event.preventDefault();
|
||||
console.log(deliveryDate.value);
|
||||
if(typeof deliveryDate.value != typeof Date) {
|
||||
deliveryDate.value = new Date(deliveryDate.value as unknown as string);
|
||||
}
|
||||
const json = {
|
||||
MZN_UUID: uuid.value,
|
||||
MZN_DataZam: new Date(Date.now()).toISOString(),
|
||||
MZN_DataDos: deliveryDate.value != undefined ? deliveryDate.value.toISOString().split('T')[0] : null,
|
||||
MZN_PodID: contractor.value?.Knt_KntId,
|
||||
MZN_MZTID: route.value?.MZT_MZTID,
|
||||
MZamElem: new Array<OrderProduct>
|
||||
};
|
||||
|
||||
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 product of category.Towary) {
|
||||
if(product.Quantity != null && product.Quantity != '') {
|
||||
if(isNaN(Number(product.Quantity)) || isNaN(Number(product.Twr_CenaZ)) || isNaN(Number(product.Twr_Cena))
|
||||
|| product.Twr_Cena == "" || product.Twr_CenaZ == "") {
|
||||
showErrorNotification.value=true;
|
||||
errorNotificationMessage.value = "W zamówieniu znajdują się niepoprawne wartości.";
|
||||
return;
|
||||
}
|
||||
product.Twr_Cena = product.Twr_Cena == "" || product.Twr_Cena == null ? product.BasePrice : product.Twr_Cena;
|
||||
product.Twr_CenaZ = product.Twr_CenaZ == "" || product.Twr_CenaZ == null ? product.BasePriceZ : product.Twr_CenaZ;
|
||||
const productObject : OrderProduct = {
|
||||
MZE_TwrId: product.Twr_TwrId,
|
||||
MZE_TwrJm: product.ChosenOption,
|
||||
MZE_TwrCena: product.ChosenOption == product.Twr_JMZ ? product.Twr_CenaZ : product.Twr_Cena,
|
||||
MZE_TwrIlosc: product.Quantity,
|
||||
MZE_TwrNazwa: product.Twr_Nazwa,
|
||||
MZE_TwrKod: product.Twr_Kod,
|
||||
MZE_MZNID: undefined,
|
||||
MZE_MZEID: undefined,
|
||||
MZE_TwrStawka: undefined
|
||||
};
|
||||
json.MZamElem.push(productObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(json.MZamElem.length == 0) {
|
||||
showErrorNotification.value=true;
|
||||
errorNotificationMessage.value = "Zamówienie jest puste.";
|
||||
return;
|
||||
}
|
||||
showErrorNotification.value=false;
|
||||
console.log(json);
|
||||
console.log(JSON.stringify(json));
|
||||
axiosInstance.post('/zamowienie', JSON.stringify(json)).then( response => {
|
||||
uuid.value = response.data.MZN_UUID;
|
||||
showSuccessNotification.value = true;
|
||||
successNotificationMessage.value = "Zamówienie zostało zapisane do bazy danych."
|
||||
});
|
||||
}
|
||||
|
||||
function setConfirmationModal(event : Event) {
|
||||
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;
|
||||
}
|
||||
|
||||
function cancelOrder(event: Event) {
|
||||
event.preventDefault();
|
||||
showCancellationModal.value = true;
|
||||
}
|
||||
|
||||
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 selectContractorFromDropdown(selectedContractor : Contractor) {
|
||||
console.log(selectedContractor);
|
||||
contractor.value = selectedContractor;
|
||||
showContractorsDropdown.value = false;
|
||||
}
|
||||
|
||||
function filterRoutes() {
|
||||
if (routeSearch.value == "") {
|
||||
route.value = undefined;
|
||||
filteredRoutes.value = routes.value;
|
||||
return;
|
||||
}
|
||||
if(routes.value != undefined) {
|
||||
filteredRoutes.value = routes.value.filter(
|
||||
route =>
|
||||
route.MZT_Nazwa1.toLowerCase().includes(routeSearch.value?.toLowerCase() as string)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleRoutesDropdown() {
|
||||
if(!showRoutesDropdown.value) {
|
||||
showRoutesDropdown.value = true;
|
||||
if(routeSearch.value == undefined || routeSearch.value == '') {
|
||||
filteredRoutes.value = routes.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectRouteFromDropdown(selectedRoute : Route) {
|
||||
route.value = selectedRoute;
|
||||
showRoutesDropdown.value = false;
|
||||
}
|
||||
|
||||
function handleClickOutsideDropdown(event : Event) {
|
||||
if(contractorInput.value != null && !contractorInput.value.contains(event.target)){
|
||||
showContractorsDropdown.value = false;
|
||||
}
|
||||
if(routeInput.value != null && !routeInput.value.contains(event.target)){
|
||||
showRoutesDropdown.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(function (){
|
||||
document.addEventListener('click', handleClickOutsideDropdown);
|
||||
});
|
||||
|
||||
onBeforeUnmount( function () {
|
||||
document.removeEventListener('click', handleClickOutsideDropdown);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="box is-shadowless" @submit.prevent="createJSON">
|
||||
<div>
|
||||
<div class="box mb-5">
|
||||
<div class="mb-3">
|
||||
<h1 class="title is-5"><b>ZAMÓWIENIE</b></h1>
|
||||
<h1 class="subtitle is-5" v-if="uuid != undefined" ><b>{{ uuid }}</b></h1>
|
||||
</div>
|
||||
<div class="field mb-3">
|
||||
<label class="label is-small">Klient</label>
|
||||
<div class="field">
|
||||
<div ref="contractorInput" class="dropdown maxwidth"
|
||||
v-bind:class="{'is-active': showContractorsDropdown == true}">
|
||||
<div class="dropdown-trigger maxwidth" @click="toggleContractorsDropdown">
|
||||
<div class="field maxwidth">
|
||||
<p class="control is-expanded has-icons-right is-small maxwidth">
|
||||
<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 class="field mb-3">
|
||||
<label class="label is-small">Data dostawy</label>
|
||||
<div class="field is-small">
|
||||
<VueDatePicker class ="bulma-is-small"
|
||||
v-model="deliveryDate"
|
||||
:enable-time-picker="false"
|
||||
:clearable="true"
|
||||
input-class-name="input is-small calendar-background"
|
||||
menu-class-name="calendar-background"
|
||||
v-bind:dark = "!!window?.matchMedia?.('(prefers-color-scheme:dark)')?.matches"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mb-3">
|
||||
<label class="label is-small">Trasa</label>
|
||||
<div class="field">
|
||||
<div ref="routeInput" class="dropdown maxwidth"
|
||||
v-bind:class="{'is-active': showRoutesDropdown == true}">
|
||||
<div class="dropdown-trigger maxwidth" @click="toggleRoutesDropdown">
|
||||
<div class="field maxwidth">
|
||||
<p class="control is-expanded has-icons-right is-small maxwidth">
|
||||
<input class="input is-small is-expanded maxwidth" type="search"
|
||||
v-model="routeSearch" @input="filterRoutes" />
|
||||
<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="filteredRoutes != undefined && filteredRoutes.length == 0" class="dropdown-item is-clipped">Brak wyników</a>
|
||||
<a class="dropdown-item is-clipped" @click = "selectRouteFromDropdown(dropdownRoute)"
|
||||
v-bind:class = "{'has-background-info' : route == null}">Brak</a>
|
||||
<a v-for="dropdownRoute in filteredRoutes" v-bind:key="dropdownRoute.MZT_MZTID"
|
||||
class="dropdown-item is-clipped" @click = "selectRouteFromDropdown(dropdownRoute)"
|
||||
v-bind:class = "{'has-background-info' : dropdownRoute == route}">
|
||||
{{dropdownRoute.MZT_Nazwa1}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label is-small">Uwagi do zamówienia</label>
|
||||
<textarea
|
||||
v-model="additionalNotes"
|
||||
class="textarea"
|
||||
placeholder="Uwagi do zamówienia"
|
||||
rows="5"
|
||||
></textarea>
|
||||
</div>
|
||||
<button class="button is-info mt-3">Zapisz</button>
|
||||
<button class="button is-success mt-3 ml-3" @click="setConfirmationModal" v-bind:disabled="uuid == undefined">Potwierdź</button>
|
||||
<button class="button is-danger mt-3 ml-3" @click="cancelOrder" v-bind:disabled="uuid == undefined">Anuluj</button>
|
||||
<div v-if="showErrorNotification" class="notification is-danger is-bold mt-3">
|
||||
<button class="delete" @click.prevent="showErrorNotification = false"></button>
|
||||
{{ errorNotificationMessage }}
|
||||
</div>
|
||||
<div v-if="showSuccessNotification" class="notification is-success is-bold mt-3">
|
||||
<button class="delete" @click.prevent="showSuccessNotification = false"></button>
|
||||
{{ successNotificationMessage }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="category in categories" :key="category.Kod">
|
||||
<div class="box mb-3" >
|
||||
<h1 class="title is-5 mb-3 mb-3"><b>{{ category.Kod }}</b></h1>
|
||||
<div class="field" v-for="(product, index) in category.Towary" :key="product.Twr_Nazwa">
|
||||
<label class="label is-small">{{ product.Twr_Nazwa }}</label>
|
||||
<div class="columns is-mobile">
|
||||
<div class="column" v-if="product.ChosenOption == product.Twr_JM">
|
||||
<div class="field has-addons">
|
||||
<p class="control is-expanded">
|
||||
<input
|
||||
class="input is-small is-fullwidth"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
v-model="product.Twr_Cena"
|
||||
v-bind:class="{ 'is-danger has-background-danger-soft': product.Twr_Cena != undefined && (isNaN(Number(product.Twr_Cena)) || product.Twr_Cena == ''),'is-success has-background-success-soft': product.Quantity != undefined && product.Quantity as unknown as string != '' && !isNaN(Number(product.Quantity))}"
|
||||
/>
|
||||
</p>
|
||||
<p class="control">
|
||||
<button class="button is-small is-danger is-outlined" @click.prevent="product.Twr_Cena = product.BasePrice">X</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column" v-else-if="product.ChosenOption == product.Twr_JMZ">
|
||||
<div class="field has-addons">
|
||||
<p class="control is-expanded">
|
||||
<input
|
||||
class="input is-small"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
v-model="product.Twr_CenaZ"
|
||||
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))
|
||||
}"
|
||||
/>
|
||||
</p>
|
||||
<p class="control">
|
||||
<button class="button is-small is-danger is-outlined" @click.prevent="product.Twr_CenaZ = product.BasePriceZ">X</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="field has-addons">
|
||||
<p class="control">
|
||||
<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-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>
|
||||
</select>
|
||||
</span>
|
||||
</p>
|
||||
<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-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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!(index == category.Towary.length - 1)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns mt-1 is-variable is-mobile">
|
||||
<div class = "column is-6">
|
||||
<button class="button is-info is-fullwidth is-large">Zapisz</button>
|
||||
</div>
|
||||
<div class = "is-large column is-6 ml-3">
|
||||
<button class="button is-success is-fullwidth is-large" @click="showConfirmationModal = true">Potwierdź</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<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;
|
||||
}
|
||||
}
|
||||
|
||||
.maxwidth {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
94
src/components/NavBar.vue
Normal file
94
src/components/NavBar.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
import { router } from '@/router/router'
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useUserStore } from '@/stores/user.store'
|
||||
import { axiosInstance } from '@/main'
|
||||
|
||||
const activator = ref(false);
|
||||
|
||||
const siteControlStore = useSiteControlStore();
|
||||
const ordersStore = useOrdersStore();
|
||||
const contractorsStore = useContractorsStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const { username } = storeToRefs(userStore);
|
||||
|
||||
function makeBurger() {
|
||||
activator.value = !activator.value
|
||||
return activator
|
||||
}
|
||||
|
||||
function clickForm() {
|
||||
siteControlStore.switchToForm();
|
||||
if(activator.value) {
|
||||
activator.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function clickOrders() {
|
||||
siteControlStore.switchToOrders();
|
||||
if(activator.value) {
|
||||
activator.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function clickTable() {
|
||||
siteControlStore.switchToTable();
|
||||
if(activator.value) {
|
||||
activator.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function routeLogin() {
|
||||
axiosInstance.post('/logout');
|
||||
router.push("/login");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="navbar has-shadow is-fixed-top" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<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>
|
||||
<h4 v-if="username != undefined" class="subtitle is-4"> {{'- ' + username}}</h4>
|
||||
</a>
|
||||
<button @click="makeBurger" class="button navbar-burger is-pulled-right" data-target="navMenu" v-bind:class="{ 'is-active': activator }">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="navbar-menu" id="navMenu" v-bind:class="{ 'is-active': activator }">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" @click="clickForm">
|
||||
Formularz
|
||||
</a>
|
||||
<a class="navbar-item" @click="clickOrders">
|
||||
Zamówienia
|
||||
</a>
|
||||
<a class="navbar-item" @click="clickTable">
|
||||
Zestawienie
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<button class="button is-info" @click="siteControlStore.newOrder">
|
||||
Nowe Zamówienie
|
||||
</button>
|
||||
<button class="button is-info" @click="routeLogin" >
|
||||
Wyloguj
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
209
src/components/OrdersSelector.vue
Normal file
209
src/components/OrdersSelector.vue
Normal file
@@ -0,0 +1,209 @@
|
||||
<script setup lang="ts">
|
||||
import VueDatePicker from '@vuepic/vue-datepicker';
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
import type { Order } from '@/main'
|
||||
|
||||
const ordersStore = useOrdersStore();
|
||||
const siteControlStore = useSiteControlStore();
|
||||
const searchOrderDate = ref<Array<Date>>([]);
|
||||
const isOutOfBuffer = ref<boolean>(false);
|
||||
const isInBufor = ref<boolean>(false);
|
||||
const { orders, dates } = storeToRefs(ordersStore);
|
||||
const areOrdersLoading = ref<boolean>(false);
|
||||
const { isDarkTheme, isLoading } = storeToRefs(siteControlStore);
|
||||
|
||||
const date = new Date(Date.now());
|
||||
const startDate = new Date(date.getFullYear(), date.getMonth(), (date.getDate() - 2));
|
||||
const endDate = new Date(date.getFullYear()+1, date.getMonth(), date.getDay());
|
||||
searchOrderDate.value?.push(startDate, endDate);
|
||||
|
||||
watch(isInBufor, (val) => {
|
||||
if(val && val == isOutOfBuffer.value) {
|
||||
isOutOfBuffer.value = false;
|
||||
}
|
||||
},{
|
||||
immediate: true
|
||||
});
|
||||
|
||||
watch(isOutOfBuffer, (val) => {
|
||||
if(val && val == isInBufor.value) {
|
||||
isInBufor.value = false;
|
||||
}
|
||||
}, {
|
||||
immediate: true
|
||||
});
|
||||
|
||||
const buffer = computed(()=>{
|
||||
if (!isInBufor.value && !isOutOfBuffer.value) {
|
||||
return null;
|
||||
} else return !!isInBufor.value;
|
||||
});
|
||||
|
||||
const datesWithOrders = computed( ()=>{
|
||||
const datesWithOrders = new Map<Date, Array<Order>>();
|
||||
if (dates.value == undefined || orders.value == undefined) {
|
||||
return datesWithOrders;
|
||||
}
|
||||
for (const date of dates.value) {
|
||||
datesWithOrders.set(date, []);
|
||||
for (const order of orders.value) {
|
||||
if (order.MZN_DataDos == date.toString()) {
|
||||
datesWithOrders.get(date)?.push(order);
|
||||
}
|
||||
}
|
||||
}
|
||||
return datesWithOrders;
|
||||
})
|
||||
|
||||
function viewOrder(order : Order) {
|
||||
order.loading = true;
|
||||
siteControlStore.viewOrder(order.MZN_UUID);
|
||||
}
|
||||
|
||||
async function fetchOrders(event : Event) {
|
||||
event?.preventDefault();
|
||||
areOrdersLoading.value = true;
|
||||
console.log(searchOrderDate.value);
|
||||
|
||||
if(searchOrderDate.value == undefined) {
|
||||
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;
|
||||
}
|
||||
|
||||
fetchOrders(null);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="box is-shadowless">
|
||||
<form class="mb-3">
|
||||
<div class="box">
|
||||
<h1 class="mb-3 title is-5"><b>FILTR ZAMÓWIEŃ</b></h1>
|
||||
<div class="field mb-5">
|
||||
<label class="label is-small">Data zamówienia</label>
|
||||
<div class="field is-small">
|
||||
<VueDatePicker v-model="searchOrderDate"
|
||||
:enable-time-picker="false"
|
||||
:clearable="true"
|
||||
:highlight="dates"
|
||||
input-class-name="input is-small calendar-background"
|
||||
menu-class-name="calendar-background"
|
||||
range/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mb-5">
|
||||
<label class="label is-small">Zamówienie potwierdzone?</label>
|
||||
<div class="control">
|
||||
<label class="checkbox mr-5">
|
||||
<input type="checkbox" v-model="isOutOfBuffer"/>
|
||||
Tak
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-model="isInBufor"/>
|
||||
Nie
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="button is-info is-small is-expanded" @click="fetchOrders" :class="{ 'is-loading': areOrdersLoading }">Pobierz zamówienia</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="box">
|
||||
<h1 class="mb-3 title is-5"><b>ZAMÓWIENIA</b></h1>
|
||||
<div v-for="date in datesWithOrders.keys()" :key="String(date)">
|
||||
<div v-if="datesWithOrders.get(date)?.length != 0">
|
||||
<h1 class="mb-3 subtitle is-6" :class="{'is-skeleton' : areOrdersLoading}">{{ date }}</h1>
|
||||
<div class="columns is-multiline">
|
||||
<template v-for="order in datesWithOrders.get(date)" :key="order.MZN_UUID">
|
||||
<div class="column is-4 mb-3" v-if="order.MZN_DataDos == date.toString()">
|
||||
<div class="box"
|
||||
:class="{'confirmed' : order.MZN_Bufor == 0 && order.MZN_Anulowane != 1,
|
||||
'cancelled' : order.MZN_Anulowane == 1,
|
||||
'is-skeleton' : areOrdersLoading}">
|
||||
<label class="label is-small" :class="{'is-invisible': areOrdersLoading}">Klient</label>
|
||||
<div class="field is-small mb-3" :class="{'is-invisible': areOrdersLoading}">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
:value="order.MZN_PodNazwa1 + order.MZN_PodNazwa2 + order.MZN_PodNazwa3"
|
||||
readonly/>
|
||||
</div>
|
||||
<div class="columns is-mobile field is-small mb-0">
|
||||
<div class="column is-6" :class="{'is-invisible': areOrdersLoading}">
|
||||
<label class="label is-small">Data dostawy</label>
|
||||
<div class="field is-small">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
v-model="order.MZN_DataDos"
|
||||
readonly/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-6">
|
||||
<label class="label is-small" :class="{'is-invisible': areOrdersLoading}">Zamówienie potwierdzone?</label>
|
||||
<div class="field is-small" :class="{'is-invisible': areOrdersLoading}" v-if="order.MZN_Bufor==0">
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
value="Tak"
|
||||
readonly/>
|
||||
</div>
|
||||
<div class="field is-small" :class="{'is-invisible': areOrdersLoading}" v-else>
|
||||
<input class="input is-small is-static"
|
||||
type="text"
|
||||
value="Nie"
|
||||
readonly/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="label is-small mb-5" :class="{'is-invisible': areOrdersLoading}">Produkty</label>
|
||||
<div class="field columns is-multiline is-mobile">
|
||||
<template v-for="product in order.MZamElem" :key="product.MZE_TwrKod">
|
||||
<div class="column is-6 py-0">{{ product.MZE_TwrKod }}</div>
|
||||
<div class="column is-6 py-0">{{Number(product.MZE_TwrIlosc).toFixed(2) + " " + product.MZE_TwrJm}}</div>
|
||||
</template>
|
||||
</div>
|
||||
<button class="button is-info is-small is-expanded" :class="{'is-invisible': areOrdersLoading, 'is-loading': order.loading}" @click="viewOrder(order)">Podgląd</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<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>
|
||||
211
src/components/SummaryComponent.vue
Normal file
211
src/components/SummaryComponent.vue
Normal file
@@ -0,0 +1,211 @@
|
||||
<script setup lang="ts">
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import VueDatePicker from '@vuepic/vue-datepicker'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import type { Product } from '@/main'
|
||||
|
||||
const ordersStore = useOrdersStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
|
||||
const { orders, dates } = storeToRefs(ordersStore);
|
||||
const searchDate = ref<Date>(new Date(Date.now()));
|
||||
const confirmedOrders = ref<boolean>();
|
||||
const isSummed = ref<boolean>(true);
|
||||
const isLoading = ref<boolean>(true);
|
||||
const summedProducts = ref<Array<Product>>([]);
|
||||
const products = ref<Array<Object>>();
|
||||
|
||||
async function fetchOrders() {
|
||||
isLoading.value=true;
|
||||
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);
|
||||
const productsMap = await categoriesStore.sumProductsFromOrders(orders.value);
|
||||
for(const product of productsMap.values()) {
|
||||
if(product.SummedQuantity > 0) {
|
||||
summedProducts.value.push(product);
|
||||
}
|
||||
}
|
||||
await prepareProductsFromOrders();
|
||||
isLoading.value=false;
|
||||
}
|
||||
|
||||
async function prepareProductsFromOrders() {
|
||||
products.value = [];
|
||||
if(orders.value == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(const order of orders.value) {
|
||||
for (const product of order.MZamElem) {
|
||||
const newProduct = {
|
||||
'kod': product.MZE_TwrKod,
|
||||
'nazwa': product.MZE_TwrNazwa,
|
||||
'ilosc': Number(product.MZE_TwrIlosc).toFixed(2),
|
||||
'jm': product.MZE_TwrJm,
|
||||
'cena': Number(product.MZE_TwrCena).toFixed(2),
|
||||
'suma': Number(Number(product.MZE_TwrCena) * Number(product.MZE_TwrIlosc)).toFixed(2),
|
||||
'order': {
|
||||
'uuid': order.MZN_UUID,
|
||||
'nazwaklienta': order.MZN_PodNazwa1 + order.MZN_PodNazwa2 + order.MZN_PodNazwa3
|
||||
}
|
||||
}
|
||||
products.value.push(newProduct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
orders.value = await ordersStore.fetchOrdersByDay(searchDate.value, null);
|
||||
const productsMap = await categoriesStore.sumProductsFromOrders(orders.value);
|
||||
summedProducts.value = [];
|
||||
for(const product of productsMap.values()) {
|
||||
if(product.SummedQuantity > 0) {
|
||||
summedProducts.value.push(product);
|
||||
}
|
||||
}
|
||||
console.log(summedProducts.value);
|
||||
await prepareProductsFromOrders();
|
||||
console.log(products.value);
|
||||
isLoading.value=false;
|
||||
});
|
||||
|
||||
onBeforeUnmount( async function (){
|
||||
const siteControlStore = useSiteControlStore();
|
||||
await siteControlStore.newOrder(false);
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="columns box is-shadowless" style="margin: 0.5rem 0 0; padding: 0; min-height: 100%">
|
||||
<div class="column">
|
||||
<div class="box">
|
||||
<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"
|
||||
:highlight = "dates"
|
||||
/>
|
||||
|
||||
<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="box mt-3">
|
||||
<button class="button is-fullwidth mb-3" @click="isSummed=false">Rozdzielone zamówienia</button>
|
||||
<button class="button is-fullwidth mb-3" @click="isSummed=true">Zsumowane zamówienia</button>
|
||||
<button class="button is-fullwidth" v-print="'#printMe'">Drukuj</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-four-fifths">
|
||||
<div class="box" style="width: 100%; height: 100%; padding: 0">
|
||||
<div style="width: 100%; height: 100%">
|
||||
<div v-if="isLoading == true" class="is-flex is-justify-content-center is-flex-direction-row" style="height: 100%; align-content:space-evenly">
|
||||
<div class="title is-1 has-text-centered element is-loading" style="min-height: 150px; align-self: center;"></div>
|
||||
</div>
|
||||
<DataTable :value="products" class="mb-3" style="padding:0" scrollable id="printMe" rowGroupMode="subheader" groupRowsBy="order.uuid" v-else-if="orders != undefined && orders.length != 0 && !isSummed">
|
||||
<Column field="order.uuid" header="UUID"/>
|
||||
<Column field="kod" header="Indeks" frozen></Column>
|
||||
<Column field="nazwa" header="Nazwa"/>
|
||||
<Column field="ilosc" header="Ilość"/>
|
||||
<Column field="jm" header="JM"/>
|
||||
<Column field="cena" header="Cena"/>
|
||||
<Column field="suma" header="Suma"/>
|
||||
<template #groupheader="slotProps">
|
||||
<span>{{ slotProps.data.order.nazwaklienta }}</span>
|
||||
</template>
|
||||
</DataTable>
|
||||
<DataTable :value="summedProducts" class="mb-3" style="padding:0" scrollable id="printMe" v-else-if="orders != undefined && orders.length != 0 && isSummed">
|
||||
<Column field="Twr_Kod" header="Indeks" frozen></Column>
|
||||
<Column field="Twr_Nazwa" header="Nazwa"/>
|
||||
<Column field="SummedQuantity" header="Ilość">
|
||||
<template #body="slotProps">
|
||||
<span>{{ slotProps.data.SummedQuantity.toFixed(2)}}</span>
|
||||
</template>
|
||||
</Column>
|
||||
<Column field="Twr_JM" header="JM">
|
||||
</Column>
|
||||
<Column field="SummedPrice" header="Suma">
|
||||
<template #body="slotProps">
|
||||
<span>{{ slotProps.data.SummedPrice.toFixed(2)}}</span>
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
<div v-else class="is-flex is-justify-content-center is-flex-direction-row">
|
||||
<p class="title is-1 has-text-centered" style="height: min-content; align-self: center;">Brak zamówień</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@media screen and (min-width: 500px) {
|
||||
.box {
|
||||
--bulma-box-padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 500px) {
|
||||
.box {
|
||||
--bulma-box-padding: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.blackBorder {
|
||||
--bulma-table-cell-border-color : black;
|
||||
}
|
||||
|
||||
.tableOverflow {
|
||||
overflow-x: scroll;
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.test {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
tr th:first-child{
|
||||
border-top-left-radius: 0.75rem;
|
||||
}
|
||||
|
||||
tr th:last-child{
|
||||
border-top-right-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.p-datatable-scrollable {
|
||||
border-top-right-radius: 0.75rem;
|
||||
border-top-left-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.p-datatable-table-container {
|
||||
border-top-right-radius: 0.75rem;
|
||||
border-top-left-radius: 0.75rem;
|
||||
}
|
||||
|
||||
table {
|
||||
border-top-right-radius: 0.75rem;
|
||||
border-top-left-radius: 0.75rem;
|
||||
}
|
||||
|
||||
|
||||
@media print {
|
||||
.dashedBorder{
|
||||
border-style: dotted;
|
||||
border-color: lightgray;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
174
src/main.ts
174
src/main.ts
@@ -1,8 +1,172 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import { createApp, watch } from 'vue'
|
||||
import App from './App.vue';
|
||||
import VueDatePicker from '@vuepic/vue-datepicker';
|
||||
import '@vuepic/vue-datepicker/dist/main.css'
|
||||
import '@vuepic/vue-datepicker/dist/main.css';
|
||||
import ConfirmationModal from '@/components/ConfirmationModal.vue';
|
||||
import NavBar from '@/components/NavBar.vue';
|
||||
import MainForm from '@/components/MainForm.vue';
|
||||
import OrdersSelector from '@/components/OrdersSelector.vue'
|
||||
import ConfirmedForm from '@/components/ConfirmedForm.vue'
|
||||
import LoadingComponent from '@/components/LoadingComponent.vue'
|
||||
import axios from 'axios'
|
||||
import LoginModal from '@/components/LoginModal.vue'
|
||||
import { createPinia, storeToRefs } from 'pinia'
|
||||
import VueCookies from 'vue3-cookies'
|
||||
import { router } from '@/router/router'
|
||||
import { useUserStore } from '@/stores/user.store'
|
||||
import print from 'vue3-print-nb'
|
||||
import CancelationModal from '@/components/CancelationModal.vue'
|
||||
import SummaryComponent from '@/components/SummaryComponent.vue'
|
||||
import PrimeVue from "primevue/config";
|
||||
import Lara from '@primevue/themes/lara';
|
||||
|
||||
const app = createApp(App);
|
||||
const pinia = createPinia();
|
||||
app.use(pinia);
|
||||
app.use(VueCookies);
|
||||
app.use(router);
|
||||
app.use(print);
|
||||
app.use(PrimeVue, {
|
||||
// Default theme configuration
|
||||
theme: {
|
||||
preset: Lara,
|
||||
options: {
|
||||
prefix: 'p',
|
||||
darkModeSelector: 'system',
|
||||
cssLayer: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(localStorage.getItem('piniaState')) {
|
||||
pinia.state.value = JSON.parse(localStorage.getItem('piniaState') as string);
|
||||
}
|
||||
|
||||
watch (
|
||||
() => pinia.state.value,
|
||||
(state) => {
|
||||
localStorage.setItem('piniaState', JSON.stringify(state));
|
||||
},
|
||||
{deep: true}
|
||||
)
|
||||
|
||||
|
||||
export const axiosInstance = axios.create({
|
||||
baseURL: 'https://zamowienia.mleczarnia-kuzma.pl/api',
|
||||
withCredentials: true
|
||||
});
|
||||
|
||||
axiosInstance.interceptors.response.use( (response) => {
|
||||
return response;
|
||||
}, (error) => {
|
||||
if (error.response.status == 401) {
|
||||
const userStore = useUserStore();
|
||||
storeToRefs(userStore).username.value = undefined;
|
||||
router.push('/login');
|
||||
}
|
||||
});
|
||||
|
||||
const app = createApp(App)
|
||||
app.component('VueDatePicker', VueDatePicker);
|
||||
app.mount('#app')
|
||||
app.component('ConfirmationModal', ConfirmationModal);
|
||||
app.component('LoginModal', LoginModal);
|
||||
app.component('NavBar', NavBar);
|
||||
app.component('MainForm', MainForm);
|
||||
app.component('OrdersSelector', OrdersSelector);
|
||||
app.component('ConfirmedForm', ConfirmedForm);
|
||||
app.component('LoadingComponent', LoadingComponent);
|
||||
app.component('CancelationModal', CancelationModal);
|
||||
app.component('SummaryComponent', SummaryComponent);
|
||||
app.mount('#app');
|
||||
|
||||
export interface Category {
|
||||
GIDNumer: number,
|
||||
GrONumer: number,
|
||||
Kod: string,
|
||||
Nazwa: string,
|
||||
Poziom: number,
|
||||
Sciezka: string,
|
||||
Towary: Array<Product>
|
||||
isVisible: boolean
|
||||
}
|
||||
|
||||
export interface Product {
|
||||
Twr_Cena: string,
|
||||
Twr_CenaZ: string,
|
||||
Twr_JM: string,
|
||||
Twr_JMPrzelicznikL: string,
|
||||
Twr_JMPrzelicznikM: string,
|
||||
Twr_JMZ: string,
|
||||
Twr_Kod: string,
|
||||
Twr_Nazwa: string,
|
||||
Twr_NieAktywny: number,
|
||||
Twr_Stawka: string,
|
||||
Twr_TwGGIDNumer: number,
|
||||
Twr_TwrId: number,
|
||||
Options: Array<string>,
|
||||
ChosenOption: string,
|
||||
Quantity: string,
|
||||
BasePrice: string,
|
||||
BasePriceZ: string,
|
||||
SummedQuantity: number,
|
||||
SummedPrice: number
|
||||
}
|
||||
|
||||
export interface Contractor {
|
||||
Knt_Email: string,
|
||||
Knt_KntId: number,
|
||||
Knt_KodPocztowy: string,
|
||||
Knt_Miasto: string,
|
||||
Knt_Nazwa1: string,
|
||||
Knt_Nazwa2: string,
|
||||
Knt_Nazwa3: string,
|
||||
Knt_Nieaktywny: number,
|
||||
Knt_NipE: string,
|
||||
Knt_NrDomu: string,
|
||||
Knt_OpiekunId: number,
|
||||
Knt_OpiekunTyp: number,
|
||||
Knt_Ulica: string,
|
||||
Knt_Wojewodztwo: string
|
||||
}
|
||||
|
||||
export interface Order {
|
||||
loading: boolean
|
||||
MZN_Bufor: number,
|
||||
MZN_Anulowane: number,
|
||||
MZN_DataDos: string,
|
||||
MZN_DataZam: string,
|
||||
MZN_MZNID: number,
|
||||
MZN_OpeID: number,
|
||||
MZN_PodID: number,
|
||||
MZN_PodKodPocztowy: string,
|
||||
MZN_PodMiasto: string,
|
||||
MZN_PodNazwa1: string,
|
||||
MZN_PodNazwa2: string,
|
||||
MZN_PodNazwa3: string,
|
||||
MZN_PodNipE: string,
|
||||
MZN_PodNrDomu: string,
|
||||
MZN_PodUlica: string,
|
||||
MZN_PodWojewodztwo: string,
|
||||
MZN_TypDokumentu: number,
|
||||
MZN_UUID: string,
|
||||
MZN_Uwagi: string,
|
||||
MZN_MZTID: number,
|
||||
MZamElem: Array<OrderProduct>
|
||||
}
|
||||
|
||||
export interface OrderProduct {
|
||||
MZE_MZEID: number | undefined,
|
||||
MZE_MZNID: number | undefined,
|
||||
MZE_TwrCena: string,
|
||||
MZE_TwrId: number,
|
||||
MZE_TwrIlosc: string,
|
||||
MZE_TwrJm: string,
|
||||
MZE_TwrNazwa: string,
|
||||
MZE_TwrKod: string,
|
||||
MZE_TwrStawka: string | undefined,
|
||||
}
|
||||
|
||||
export interface Route {
|
||||
MZT_MZTID: number,
|
||||
MZT_Nazwa1: string
|
||||
}
|
||||
|
||||
|
||||
15
src/router/router.ts
Normal file
15
src/router/router.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
|
||||
import { MainView, LoginView, SummaryView, OrdersView } from '@/views'
|
||||
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
linkActiveClass: 'active',
|
||||
routes: [
|
||||
{ path: '/', component: MainView },
|
||||
{ path: '/login', component: LoginView },
|
||||
{ path: '/summary', component: SummaryView, },
|
||||
{ path: '/orders', component: OrdersView}
|
||||
]
|
||||
});
|
||||
|
||||
62
src/stores/categories.store.ts
Normal file
62
src/stores/categories.store.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { Category, Order, Product } from '@/main'
|
||||
import { ref } from 'vue'
|
||||
import { axiosInstance } from '@/main'
|
||||
|
||||
export const useCategoriesStore = defineStore('categories', () => {
|
||||
const categories = ref<Array<Category>>([]);
|
||||
|
||||
async function fetchCategories() {
|
||||
const response = await axiosInstance.get('/towary', {withCredentials: true});
|
||||
categories.value = response.data;
|
||||
|
||||
if(categories.value != undefined) {
|
||||
for (const category of categories.value) {
|
||||
for (const product of category.Towary) {
|
||||
product.Options = new Array(product.Twr_JM);
|
||||
product.ChosenOption = product.Twr_JM;
|
||||
product.BasePrice = product.Twr_Cena;
|
||||
product.BasePriceZ = product.Twr_CenaZ;
|
||||
product.SummedQuantity = 0;
|
||||
product.SummedPrice = 0;
|
||||
if (product.Twr_JMZ != null) {
|
||||
product.Options.push(product.Twr_JMZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function sumProductsFromOrders(orders : Array<Order>) {
|
||||
const productsMap = new Map<string, Product>();
|
||||
|
||||
await fetchCategories();
|
||||
|
||||
if(categories.value != undefined) {
|
||||
for (const category of categories.value) {
|
||||
for (const product of category.Towary) {
|
||||
productsMap.set(product.Twr_TwrId.toString(), product);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(orders != undefined) {
|
||||
for (const order of orders) {
|
||||
for (const product of order.MZamElem) {
|
||||
const mapProduct = productsMap.get(String(product.MZE_TwrId));
|
||||
if (product.MZE_TwrJm == mapProduct?.Twr_JM) {
|
||||
mapProduct.SummedQuantity += Number(product.MZE_TwrIlosc);
|
||||
mapProduct.SummedPrice += (Number(product.MZE_TwrCena) * Number(product.MZE_TwrIlosc));
|
||||
}
|
||||
else if (product.MZE_TwrJm == mapProduct?.Twr_JMZ) {
|
||||
mapProduct.SummedQuantity += (Number(product.MZE_TwrIlosc) * Number(mapProduct.Twr_JMPrzelicznikM))/Number(mapProduct.Twr_JMPrzelicznikL);
|
||||
mapProduct.SummedPrice += (Number(product.MZE_TwrCena) * Number(product.MZE_TwrIlosc));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return productsMap;
|
||||
}
|
||||
|
||||
return {categories, fetchCategories, sumProductsFromOrders}
|
||||
})
|
||||
21
src/stores/contractors.store.ts
Normal file
21
src/stores/contractors.store.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { Contractor } from '@/main'
|
||||
import { ref } from 'vue'
|
||||
import { axiosInstance } from '@/main'
|
||||
|
||||
|
||||
export const useContractorsStore = defineStore('contractors', () => {
|
||||
const contractors = ref<Array<Contractor>>([]);
|
||||
contractors.value=[];
|
||||
const contractor = ref<Contractor>();
|
||||
|
||||
async function fetchContractors() {
|
||||
const response = await axiosInstance.get('/kontrahenci', {withCredentials: true});
|
||||
console.log(response);
|
||||
console.log(contractors.value);
|
||||
contractors.value = [];
|
||||
contractors.value.push(...response.data);
|
||||
}
|
||||
|
||||
return {contractors, contractor, fetchContractors}
|
||||
})
|
||||
114
src/stores/orders.store.ts
Normal file
114
src/stores/orders.store.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { Category, Contractor, Order, Route } from '@/main'
|
||||
import { type Ref, ref } from 'vue'
|
||||
import { axiosInstance } from '@/main'
|
||||
|
||||
export const useOrdersStore = defineStore('orders', () => {
|
||||
const orders = ref<Array<Order>>();
|
||||
const dates = ref<Date[]>();
|
||||
const order = ref<Order>();
|
||||
const uuid = ref<string>();
|
||||
const deliveryDate = ref<Date>();
|
||||
const orderDate = ref<Date>();
|
||||
const additionalNotes = ref<string>();
|
||||
|
||||
async function fetchOrders() {
|
||||
const response = await axiosInstance.get('/zamowienia', {withCredentials: true});
|
||||
const ordersTemp : Array<Order> = response.data;
|
||||
await getOrderDates();
|
||||
return ordersTemp;
|
||||
}
|
||||
|
||||
async function fetchOrdersByBuffer(inBuffer : boolean | null) {
|
||||
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;
|
||||
await getOrderDates();
|
||||
return ordersTemp;
|
||||
}
|
||||
|
||||
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;
|
||||
await getOrderDates();
|
||||
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;
|
||||
await getOrderDates();
|
||||
return ordersTemp;
|
||||
}
|
||||
|
||||
async function getOrderDates() {
|
||||
const tempDates = new Array<Date>();
|
||||
tempDates.push(...await fetchDates(0));
|
||||
tempDates.push(...await fetchDates(1));
|
||||
tempDates.push(...await fetchDates(2));
|
||||
dates.value = tempDates;
|
||||
console.log(dates.value);
|
||||
}
|
||||
|
||||
async function fetchDates(offset : number) {
|
||||
const date = new Date(Date.now());
|
||||
const urlString = "/kalendarz/" + date.getFullYear() + '-' + Number(date.getMonth() + offset);
|
||||
const response = await axiosInstance.get(urlString, {withCredentials: true});
|
||||
const datesTemp :Array<Date> = response.data;
|
||||
return datesTemp;
|
||||
}
|
||||
|
||||
async function loadOrder(uuidString: string, confirmed: boolean, contractor: Ref<Contractor|undefined>, contractors: Ref<Array<Contractor>>, categories: Ref<Array<Category>>, route: Ref<Route|undefined>, routes: Ref<Array<Route>|undefined>) {
|
||||
const response = await axiosInstance.get('/zamowienie/' + uuidString);
|
||||
const tempOrder = response.data;
|
||||
console.log(tempOrder);
|
||||
|
||||
if(confirmed) {
|
||||
tempOrder.MZN_Bufor = 0;
|
||||
}
|
||||
|
||||
contractor.value = <Contractor>contractors.value?.find((contractor) => contractor.Knt_KntId == tempOrder.MZN_PodID);
|
||||
route.value = <Route>routes.value?.find((route) => route.MZT_MZTID == tempOrder.MZN_MZTID);
|
||||
deliveryDate.value = new Date(tempOrder.MZN_DataDos);
|
||||
orderDate.value = new Date(tempOrder.MZN_DataZam);
|
||||
uuid.value = uuidString;
|
||||
order.value = tempOrder;
|
||||
additionalNotes.value = tempOrder.MZN_Uwagi;
|
||||
|
||||
if(categories.value == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(const orderProduct of tempOrder.MZamElem){
|
||||
for(const category of categories.value) {
|
||||
const product = category.Towary.find(product => (product.Twr_TwrId == orderProduct.MZE_TwrId));
|
||||
if(product != undefined && orderProduct.MZE_TwrCena != null) {
|
||||
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.ChosenOption = orderProduct.MZE_TwrJm;
|
||||
category.isVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {orders, order, uuid, deliveryDate, orderDate, dates, additionalNotes, fetchOrders, loadOrder, fetchOrdersByDay, fetchOrdersByBuffer, fetchOrdersByDateStartAndEnd, fetchDates, getOrderDates}
|
||||
})
|
||||
17
src/stores/routes.store.ts
Normal file
17
src/stores/routes.store.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { Route } from '@/main'
|
||||
import { ref } from 'vue'
|
||||
import { axiosInstance } from '@/main'
|
||||
|
||||
export const useRoutesStore = defineStore('routes', () => {
|
||||
const routes = ref<Array<Route>>();
|
||||
const route = ref<Route>();
|
||||
|
||||
async function fetchRoutes() {
|
||||
const response = await axiosInstance.get('/trasy', {withCredentials: true});
|
||||
routes.value = [];
|
||||
routes.value.push(...response.data);
|
||||
}
|
||||
|
||||
return {routes, route, fetchRoutes};
|
||||
});
|
||||
83
src/stores/siteControl.store.ts
Normal file
83
src/stores/siteControl.store.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { defineStore, storeToRefs } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import type { Order } from '@/main'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import { router } from '@/router/router'
|
||||
import { useRoutesStore } from '@/stores/routes.store'
|
||||
|
||||
export const useSiteControlStore = defineStore('siteControl', () => {
|
||||
const shownComponent = ref<string>("mainForm");
|
||||
const showConfirmationModal = ref<boolean>(false);
|
||||
const showCancellationModal = ref<boolean>(false);
|
||||
const isDarkTheme = ref<boolean>(false);
|
||||
const isLoading = ref<boolean>(true);
|
||||
|
||||
|
||||
async function switchToForm() {
|
||||
await router.push("/");
|
||||
}
|
||||
|
||||
async function switchToOrders() {
|
||||
await router.push("/orders");
|
||||
// const orderStore = useOrdersStore();
|
||||
// const { orders } = storeToRefs(orderStore);
|
||||
// isLoading.value = true;
|
||||
// const date = new Date(Date.now());
|
||||
// const startDate = new Date(date.getFullYear(), date.getMonth(), (date.getDate() - 2));
|
||||
// const endDate = new Date(date.getFullYear()+1, date.getMonth(), date.getDay());
|
||||
// orders.value = await orderStore.fetchOrdersByDateStartAndEnd(startDate, endDate, null);
|
||||
// console.log(orders.value);
|
||||
// isLoading.value = false;
|
||||
}
|
||||
|
||||
async function switchToTable() {
|
||||
// const ordersStore = useOrdersStore();
|
||||
// const { orders } = storeToRefs(ordersStore);
|
||||
// orders.value = await ordersStore.fetchOrdersByDay(new Date(Date.now()), null);
|
||||
await router.push("/summary");
|
||||
}
|
||||
|
||||
function checkTheme() {
|
||||
isDarkTheme.value = !!window?.matchMedia?.('(prefers-color-scheme:dark)')?.matches;
|
||||
}
|
||||
|
||||
async function viewOrder(uuid : string) {
|
||||
const orderStore = useOrdersStore();
|
||||
const contractorsStore = useContractorsStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
const routeStore = useRoutesStore();
|
||||
shownComponent.value = "mainForm";
|
||||
isLoading.value = true;
|
||||
await categoriesStore.fetchCategories();
|
||||
const { contractor, contractors } = storeToRefs(contractorsStore);
|
||||
const { categories } = storeToRefs(categoriesStore);
|
||||
const { route, routes } = storeToRefs( routeStore );
|
||||
await orderStore.loadOrder(uuid, false, contractor, contractors, categories, route, routes);
|
||||
isLoading.value=false;
|
||||
await router.push("/");
|
||||
}
|
||||
|
||||
async function newOrder(redirect : boolean) {
|
||||
const ordersStore = useOrdersStore();
|
||||
const contractorsStore = useContractorsStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
const routeStore = useRoutesStore();
|
||||
const { order, uuid, deliveryDate, orderDate } = storeToRefs(ordersStore);
|
||||
const { contractor } = storeToRefs(contractorsStore);
|
||||
const { route } = storeToRefs(routeStore);
|
||||
contractor.value = undefined;
|
||||
order.value = undefined;
|
||||
uuid.value = undefined;
|
||||
deliveryDate.value = undefined;
|
||||
orderDate.value = undefined;
|
||||
route.value = undefined;
|
||||
await categoriesStore.fetchCategories();
|
||||
if (redirect) {
|
||||
await router.push("/");
|
||||
}
|
||||
}
|
||||
|
||||
return {isLoading, showConfirmationModal, showCancellationModal, isDarkTheme, shownComponent, switchToForm, switchToOrders, switchToTable, checkTheme, viewOrder, newOrder};
|
||||
})
|
||||
10
src/stores/user.store.ts
Normal file
10
src/stores/user.store.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const username = ref<string>();
|
||||
const logoutButtonText = ref<string>();
|
||||
|
||||
return {username, logoutButtonText};
|
||||
})
|
||||
78
src/views/LoginView.vue
Normal file
78
src/views/LoginView.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<script setup lang="ts">
|
||||
import { Form, Field } from 'vee-validate';
|
||||
import * as Yup from 'yup';
|
||||
import { axiosInstance } from '@/main'
|
||||
import { router } from '@/router/router'
|
||||
import { useUserStore } from '@/stores/user.store'
|
||||
import { getActivePinia, storeToRefs } from 'pinia'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
|
||||
const schema = Yup.object().shape({
|
||||
username: Yup.string().required('Nazwa użytkownika jest wymagana'),
|
||||
password: Yup.string().required('Hasło jest wymagane')
|
||||
});
|
||||
|
||||
async function onSubmit(values : any, { setErrors } : any) {
|
||||
const { username, password } = values;
|
||||
|
||||
const body = await axiosInstance.post('/login', {
|
||||
username: username,
|
||||
password: password
|
||||
}).catch ((error) => {
|
||||
if(error.response.status == 401) {
|
||||
setErrors({ apiError: "unauthorized" })
|
||||
}
|
||||
});
|
||||
if(body != undefined && body.status == 200) {
|
||||
const userStore = useUserStore();
|
||||
const siteControlStore = useSiteControlStore();
|
||||
const { username } = storeToRefs(userStore);
|
||||
username.value = body.data.displayName;
|
||||
await siteControlStore.newOrder(true);
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container is-flex is-justify-content-space-evenly is-align-items-center" style="min-height: 100vh;">
|
||||
<div class="box" style="width: 75%">
|
||||
<h1 class="title is-3 mb-3">Login</h1>
|
||||
<Form @submit="onSubmit" :validation-schema="schema" v-slot="{ errors, isSubmitting }">
|
||||
<div class="form-group">
|
||||
<div class="field mb-3">
|
||||
<label class="label is-small">Nazwa użytkownika</label>
|
||||
<div class="field is-small mb-3">
|
||||
<Field class="input is-small"
|
||||
type="text"
|
||||
name="username"
|
||||
:class="{ 'is-danger': errors.username }"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="has-text-danger">{{errors.username}}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="field mb-3">
|
||||
<label class="label is-small">Hasło</label>
|
||||
<div class="field is-small mb-3">
|
||||
<Field class="input is-small"
|
||||
type="password"
|
||||
name="password"
|
||||
:class="{ 'is-danger': errors.password }"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="has-text-danger">{{errors.password}}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="button is-info" :disabled="isSubmitting">
|
||||
<span v-show="isSubmitting" class="spinner-border spinner-border-sm mr-1"></span>
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="errors.apiError" class="has-text-danger mt-3 mb-3">Hasło lub nazwa użytkownika jest niepoprawna.</div>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
64
src/views/MainView.vue
Normal file
64
src/views/MainView.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template class="has-navbar-fixed-top">
|
||||
<NavBar/>
|
||||
<div v-if="isLoading">
|
||||
<LoadingComponent/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<MainForm
|
||||
v-if="order == undefined || order.MZN_Bufor==1"
|
||||
/>
|
||||
<ConfirmedForm v-else-if="order.MZN_Bufor==0"/>
|
||||
|
||||
</div>
|
||||
<ConfirmationModal v-show="showConfirmationModal" @close="showConfirmationModal = false"></ConfirmationModal>
|
||||
<CancelationModal v-show="showCancellationModal" @close="showCancellationModal = false"></CancelationModal>
|
||||
<!-- <button class="button" @click="test">test</button>-->
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import '@/assets/base.css'
|
||||
import { useContractorsStore } from '@/stores/contractors.store'
|
||||
import { getActivePinia, storeToRefs } from 'pinia'
|
||||
import { useCategoriesStore } from '@/stores/categories.store'
|
||||
import { useOrdersStore } from '@/stores/orders.store'
|
||||
import { useSiteControlStore } from '@/stores/siteControl.store'
|
||||
import { useUserStore } from '@/stores/user.store'
|
||||
import { useRoutesStore } from '@/stores/routes.store'
|
||||
|
||||
const contractorsStore = useContractorsStore();
|
||||
const categoriesStore = useCategoriesStore();
|
||||
const ordersStore = useOrdersStore();
|
||||
const siteControlStore = useSiteControlStore();
|
||||
const userStore = useUserStore();
|
||||
const routesStore = useRoutesStore();
|
||||
const contractors = storeToRefs(contractorsStore).contractors;
|
||||
const contractor = storeToRefs(contractorsStore).contractor;
|
||||
const categories = storeToRefs(categoriesStore).categories;
|
||||
const { uuid, order } = storeToRefs(ordersStore);
|
||||
const { username } = storeToRefs(userStore);
|
||||
const { showConfirmationModal, showCancellationModal, isLoading, shownComponent } = storeToRefs(siteControlStore);
|
||||
|
||||
|
||||
async function fetchData() {
|
||||
//await categoriesStore.fetchCategories();
|
||||
await contractorsStore.fetchContractors();
|
||||
await routesStore.fetchRoutes();
|
||||
//siteControlStore.newOrder(false);
|
||||
isLoading.value = false;
|
||||
}
|
||||
siteControlStore.checkTheme();
|
||||
fetchData();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media screen and (min-width: 500px) {
|
||||
.box {
|
||||
--bulma-box-padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 500px) {
|
||||
.box {
|
||||
--bulma-box-padding: 0.75rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
12
src/views/OrdersView.vue
Normal file
12
src/views/OrdersView.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NavBar/>
|
||||
<OrdersSelector class="box is-shadowless"/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
8
src/views/SummaryView.vue
Normal file
8
src/views/SummaryView.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import SummaryComponent from '@/components/SummaryComponent.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NavBar/>
|
||||
<SummaryComponent/>
|
||||
</template>
|
||||
4
src/views/index.ts
Normal file
4
src/views/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { default as LoginView } from "./LoginView.vue";
|
||||
export { default as MainView } from "./MainView.vue";
|
||||
export { default as SummaryView } from "./SummaryView.vue"
|
||||
export { default as OrdersView } from "./OrdersView.vue"
|
||||
30
srg
30
srg
@@ -1,30 +0,0 @@
|
||||
<div class="columns is-mobile">
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<input
|
||||
class="input is-normal"
|
||||
type="text"
|
||||
placeholder="Kwota"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="field has-addons">
|
||||
<p class="control">
|
||||
<span class="select is-small">
|
||||
<select>
|
||||
<option v-for="option in towar.Options" :key="option">{{option}}</option>
|
||||
</select>
|
||||
</span>
|
||||
</p>
|
||||
<p class="control is-expanded">
|
||||
<input class="input" type="text" placeholder="Amount of money">
|
||||
</p>
|
||||
<p class="control">
|
||||
<button class="button">
|
||||
Transfer
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -7,5 +7,8 @@
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
],
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,18 @@ import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import {PrimeVueResolver} from '@primevue/auto-import-resolver';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
Components({
|
||||
resolvers: [
|
||||
PrimeVueResolver()
|
||||
]
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
Reference in New Issue
Block a user