Compare commits
	
		
			41 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d6750c015f | |||
| 7a00b146bd | |||
| 424aae99a0 | |||
| 0ccb091125 | |||
| 1c9e824459 | |||
| cd92389110 | |||
| 2fcf4fa9f2 | |||
| df969e35a7 | |||
| 42f101b505 | |||
| d6384abed3 | |||
| 8be432c150 | |||
| 51ef4b0691 | |||
| a073e88632 | |||
| 4234c1dd80 | |||
| 41c13f208c | |||
| 4be55d4a4a | |||
| f636540034 | |||
| df0bbe8e3f | |||
| 2689f227b7 | |||
| 81d7b1f832 | |||
| 9a060b8464 | |||
| 406cfebb93 | |||
| ba5e4a5376 | |||
| 2d0d27b502 | |||
| eeac03235b | |||
| 8140233e3a | |||
| d7e28cd926 | |||
| ce89b79074 | |||
| feee47f464 | |||
| ff3b22fb1b | |||
| bbec759b08 | |||
| 200242252c | |||
| 673eb10b7b | |||
| 15271a873b | |||
| dce8e294c5 | |||
| 2a06bb27ab | |||
| 87c8579e9e | |||
| 93c015fcb7 | |||
| 2fecc061e2 | |||
| a289c8dd0f | |||
| a3ec0fa06d | 
							
								
								
									
										31
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /* 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'] | ||||
|     ColumnGroup: typeof import('primevue/columngroup')['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'] | ||||
|     Row: typeof import('primevue/row')['default'] | ||||
|     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> | ||||
|   | ||||
							
								
								
									
										1326
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1326
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										21
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								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", | ||||
|     "bulma": "^1.0.1", | ||||
|     "axios": "^1.7.2", | ||||
|     "bulma": "^1.0.3", | ||||
|     "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", | ||||
| @@ -31,9 +41,10 @@ | ||||
|     "eslint-plugin-vue": "^9.23.0", | ||||
|     "npm-run-all2": "^6.1.2", | ||||
|     "prettier": "^3.2.5", | ||||
|     "sass": "^1.77.2", | ||||
|     "sass": "^1.83.1", | ||||
|     "typescript": "~5.4.0", | ||||
|     "vite": "^5.2.8", | ||||
|     "vue-tsc": "^2.0.11" | ||||
|     "unplugin-vue-components": "^0.27.3", | ||||
|     "vite": "^5.4.11", | ||||
|     "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 '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; | ||||
							
								
								
									
										57
									
								
								src/components/CancelationModal.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/components/CancelationModal.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| <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' | ||||
| import { ref } from 'vue' | ||||
|  | ||||
| const ordersStore = useOrdersStore(); | ||||
| const siteControlStore = useSiteControlStore(); | ||||
| const contractorStore = useContractorsStore(); | ||||
| const categoriesStore = useCategoriesStore(); | ||||
|  | ||||
| const { uuid } = storeToRefs(ordersStore); | ||||
| const { showCancellationModal, isLoading } = storeToRefs(siteControlStore); | ||||
| const cancellationReason = ref<string>(""); | ||||
|  | ||||
| async function cancelOrder() { | ||||
|   showCancellationModal.value = false; | ||||
|   // console.log(cancellationReason.value); | ||||
|   axiosInstance.delete('/zamowienie/' + uuid.value, { | ||||
|     data: { | ||||
|       MZN_AnulowanePowod: cancellationReason.value | ||||
|     } | ||||
|   }); | ||||
|   siteControlStore.newOrder("/orders"); | ||||
| } | ||||
| </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"> | ||||
|           <div>Czy napewno chcesz anulować zamówienie? Czynności tej nie można odwrócić.</div> | ||||
|           <p class="control is-expanded" style="margin-top: 20px"> | ||||
|             <input class="input is-small" type="text" v-model="cancellationReason"  placeholder="Powód anulowania" > | ||||
|           </p> | ||||
|         </section> | ||||
|         <footer class="modal-card-foot"> | ||||
|  | ||||
|           <div class="buttons"> | ||||
| <!--            <button class="button is-success" @click="cancelOrder" v-bind:disabled="cancellationReason == undefined || cancellationReason == ''">Tak</button>--> | ||||
|             <button class="button is-success" :disabled="cancellationReason.length<3" @click="cancelOrder">Tak</button> | ||||
|             <button class="button" @click="$emit('close')">Nie</button> | ||||
|           </div> | ||||
|         </footer> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| @@ -1,17 +1,38 @@ | ||||
| <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' | ||||
| import {  ref } from 'vue' | ||||
|  | ||||
| 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); | ||||
| const isOrderConfirmed = ref(true) | ||||
|  | ||||
| async function confirmOrder() { | ||||
|   isOrderConfirmed.value = false; | ||||
|   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); | ||||
|     ordersStore.orderToClone = false | ||||
|     isLoading.value = false; | ||||
|   } | ||||
| ); | ||||
|  | ||||
| function confirmOrder() { | ||||
|   emit('close'); | ||||
|   fetch('https://zamowienia.mleczarnia-kuzma.pl/api/zamowienie/' + props.orderUuid, { | ||||
|     method: 'PUT' | ||||
|   }); | ||||
|   isOrderConfirmed.value = true; | ||||
| } | ||||
| </script> | ||||
|  | ||||
| @@ -29,15 +50,11 @@ function confirmOrder() { | ||||
|         </section> | ||||
|         <footer class="modal-card-foot"> | ||||
|           <div class="buttons"> | ||||
|             <button class="button is-success" @click="confirmOrder">Tak</button> | ||||
|             <button class="button is-success" @click="confirmOrder"  :disabled="!isOrderConfirmed">Tak</button> | ||||
|             <button class="button" @click="$emit('close')">Nie</button> | ||||
|           </div> | ||||
|         </footer> | ||||
|       </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 { useRoutesStore } from '@/stores/routes.store' | ||||
| import { useSiteControlStore } from '@/stores/siteControl.store' | ||||
|  | ||||
| const ordersStore = useOrdersStore(); | ||||
| const categoriesStore = useCategoriesStore(); | ||||
| const contractorsStore = useContractorsStore(); | ||||
| const routeStore = useRoutesStore(); | ||||
| const siteControlStore = useSiteControlStore(); | ||||
|  | ||||
| const { order, uuid} = storeToRefs(ordersStore); | ||||
|  | ||||
| const { categories } = storeToRefs(categoriesStore); | ||||
|  | ||||
| const { contractor } = storeToRefs(contractorsStore); | ||||
|  | ||||
| const { route } = storeToRefs(routeStore); | ||||
|  | ||||
| const { showCancellationModal } = storeToRefs(siteControlStore); | ||||
|  | ||||
| function cancelOrder(event: Event) { | ||||
|   event.preventDefault(); | ||||
|   // axiosInstance.delete('/zamowienie/' + uuid.value); | ||||
|   showCancellationModal.value = true; | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
|   <form class="box  is-shadowless"> | ||||
|     <div class="mb-3  "> | ||||
|       <div class="box" :class="{'cancelled' : order.MZN_Anulowane == 1}"> | ||||
|         <div class="mb-3"> | ||||
|           <h1 class="title is-5" v-if="order != undefined"><b>ZAMÓWIENIE NR {{ order.MZN_MZNID }}</b><b | ||||
|             v-if="order.MZN_Anulowane == 1">, ZAMÓWIENIE ANULOWANE</b></h1> | ||||
|         </div> | ||||
|         <div class="field mb-3" v-if="contractor != undefined"> | ||||
|           <label class="label is-small">Klient</label> | ||||
|           <div class="field is-small mb-3"> | ||||
|             <p class="mb-3 is-size-7"> | ||||
|               {{ contractor.Knt_Nazwa1 + contractor.Knt_Nazwa2 + contractor.Knt_Nazwa3 }} | ||||
|             </p> | ||||
|           </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"> | ||||
|             <p class="mb-3 is-size-7"> | ||||
|               {{route.MZT_Nazwa1}} | ||||
|             </p> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="field mb-3" v-if="order != undefined && order.MZN_Uwagi != undefined"> | ||||
|           <label class="label is-small">Uwagi do zamówienia</label> | ||||
|           <p  class="mb-3 is-size-7"> | ||||
|             {{ order.MZN_Uwagi }} | ||||
|           </p> | ||||
|         </div> | ||||
|         <button v-if="order.MZN_Anulowane==0" 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 " :class="{'cancelled' : order.MZN_Anulowane == 1}" 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 is-size-7"> | ||||
|                     {{ product.Quantity + ' ' + product.ChosenOption }} | ||||
|                   </p> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="column" v-if="product.ChosenOption == product.Twr_JM"> | ||||
|                 <div class="field"> | ||||
|                   <p class="mb-3 is-size-7"> | ||||
|                     {{ product.Twr_Cena }} PLN | ||||
|                   </p> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="column" v-else-if="product.ChosenOption == product.Twr_JMZ"> | ||||
|                 <div class="field"> | ||||
|                   <p class="mb-3 is-size-7"> | ||||
|                     {{ product.Twr_CenaZ }} PLN | ||||
|                   </p> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="column" v-if="product.ChosenOption == product.Twr_JM"> | ||||
|                 <div class="field"> | ||||
|                   <p class="mb-3 is-size-7"> | ||||
|                     {{ (Number(product.Twr_Cena) * Number(product.Quantity)).toFixed(2) }} PLN | ||||
|                   </p> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="column" v-else-if="product.ChosenOption == product.Twr_JMZ"> | ||||
|                 <div class="field"> | ||||
|                   <p class="mb-3 is-size-7"> | ||||
|                     {{ (Number(product.Twr_CenaZ) * Number(product.Quantity)).toFixed(2) }} PLN | ||||
|                   </p> | ||||
|  | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </form> | ||||
| </template> | ||||
| <style> | ||||
| .cancelled { | ||||
|   --bulma-box-background-color: var(--bulma-danger-soft) | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										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> | ||||
							
								
								
									
										475
									
								
								src/components/MainForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										475
									
								
								src/components/MainForm.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,475 @@ | ||||
| <script setup lang="ts"> | ||||
| import VueDatePicker from '@vuepic/vue-datepicker' | ||||
| import { axiosInstance, type Contractor, type Order, 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 { computed, 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, order, 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 invoices = ref(); | ||||
| const documentType = ref<number>() | ||||
|  | ||||
| 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 }); | ||||
|  | ||||
| const totalAmountUnpaid = computed(() => { | ||||
|   let total = 0; | ||||
|   let totalPaid = 0; | ||||
|   for(let invoice of invoices.value) { | ||||
|     total += Number(invoice.BZd_KwotaSys); | ||||
|     totalPaid += Number(invoice.BZd_KwotaRozSys); | ||||
|   } | ||||
|   return (total - totalPaid).toFixed(2); | ||||
| }); | ||||
|  | ||||
| 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, | ||||
|     MZN_Uwagi: additionalNotes.value, | ||||
|     MZN_TypDokumentu: documentType.value, | ||||
|     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; | ||||
|     order.value = {} as Order; | ||||
|     order.value.MZN_MZNID = response.data.MZN_MZNID; | ||||
|     order.value.MZN_Bufor = 1; | ||||
|     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; | ||||
|   fetchInvoices(); | ||||
| } | ||||
|  | ||||
| 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; | ||||
|   } | ||||
| } | ||||
|  | ||||
| async function fetchInvoices() { | ||||
|   const response = await axiosInstance.get('/zaleglosci/' + contractor.value?.Knt_KntId); | ||||
|   invoices.value = response.data; | ||||
|  | ||||
| } | ||||
|  | ||||
| onMounted(function (){ | ||||
|   document.addEventListener('click', handleClickOutsideDropdown); | ||||
|   console.log(order) | ||||
|   if(contractor.value != undefined) { | ||||
|     fetchInvoices(); | ||||
|   } | ||||
|   if(order.value != undefined) { | ||||
|     documentType.value = order.value.MZN_TypDokumentu === 306 ? 306 : 301 | ||||
|   }else documentType.value = 301 | ||||
|    console.log(documentType.value) | ||||
|  | ||||
| }); | ||||
|  | ||||
| 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" v-if="order == undefined"><b>NOWE ZAMÓWIENIE</b></h1> | ||||
|           <h1 class="title is-5" v-else-if="!ordersStore.orderToClone"><b>ZAMÓWIENIE NR {{order.MZN_MZNID}}</b></h1> | ||||
|           <h1 class="title is-5" v-else-if="ordersStore.orderToClone"><b>DUPLIKACJA ZAMÓWIENIA NR {{order.MZN_MZNID}}</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"> | ||||
|           <DataTable :value="invoices" scrollable v-if="invoices != undefined && invoices.length > 0"> | ||||
|             <Column field="BZd_NumerPelny" header="Numer faktury" frozen/> | ||||
|             <Column field="BZd_DataDok" header="Data"/> | ||||
|             <Column field="BZd_Termin" header="Termin zapłaty"/> | ||||
|             <Column field="BZd_KwotaSys" header="Kwota faktury"/> | ||||
|             <Column field="BZd_KwotaRozSys" header="Kwota rozliczona"/> | ||||
|             <ColumnGroup type="footer"> | ||||
|               <Row> | ||||
|                 <Column footer="Kwota zadłużenia" :colspan="4" footerStyle="text-align:right" /> | ||||
|                 <Column :footer="totalAmountUnpaid" /> | ||||
|               </Row> | ||||
|             </ColumnGroup> | ||||
|           </DataTable> | ||||
|           <span v-else>Brak nierozliczonych faktur</span> | ||||
|         </div> | ||||
|         <div class="field mb-3"> | ||||
|           <div> | ||||
|             <label class="label is-small">Dokument WZ</label> | ||||
|             <input | ||||
|               v-model="documentType" | ||||
|               type="checkbox" | ||||
|               :true-value="306" | ||||
|               :false-value="301"> | ||||
|           </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(null)" | ||||
|                      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> | ||||
| <!--TODO intesting part                 --> | ||||
|                 <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"> | ||||
|       <div 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> | ||||
|       </div> | ||||
|       <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> | ||||
							
								
								
									
										227
									
								
								src/components/OrdersSelector.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								src/components/OrdersSelector.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | ||||
| <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 { addDays, 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())); | ||||
| const endDate = new Date(date.getFullYear(), date.getMonth()+1, date.getDate()); | ||||
| 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, clone: boolean) { | ||||
|   order.loading = true; | ||||
|   siteControlStore.viewOrder(order.MZN_UUID, clone); | ||||
| } | ||||
| function documnetType(order : Order):string { | ||||
|   if(order.MZN_TypDokumentu == 306) return ". Dokument WZ" | ||||
|   else return "" | ||||
| } | ||||
|  | ||||
| async function fetchOrders(event : Event | null) { | ||||
|   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(addDays(searchOrderDate.value[0], 1), addDays(searchOrderDate.value[1], 1), buffer.value); | ||||
|   } | ||||
|   areOrdersLoading.value = false; | ||||
|   console.log("orders"); | ||||
|   console.log(orders.value); | ||||
| } | ||||
|  | ||||
| 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" | ||||
|                            format="dd/MM/yyyy" | ||||
|                             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" :class="{'is-invisible': areOrdersLoading}">Zamówienie nr {{order.MZN_MZNID}}{{documnetType(order)}}  </label> | ||||
|                   <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> | ||||
|                   <div v-if=" order.MZN_Uwagi != null && order.MZN_Uwagi != ''"> | ||||
|                     <label class="label is-small" :class="{'is-invisible': areOrdersLoading} ">Uwagi</label> | ||||
|                     <div class="field is-small mb-3" :class="{'is-invisible': areOrdersLoading}"> | ||||
|                     <span v-if=" order.MZN_Uwagi != null && order.MZN_Uwagi != ''"> | ||||
|                       {{ order.MZN_Uwagi }} | ||||
|                     </span> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                   <label class="label is-small mb-4" :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 mr-2" :class="{'is-invisible': areOrdersLoading, 'is-loading': order.loading}" @click="viewOrder(order, false)">Podgląd</button> | ||||
|                   <button class="button is-info is-small is-expanded mr-2" :class="{'is-invisible': areOrdersLoading}" @click="viewOrder(order, true)">Duplikuj</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> | ||||
							
								
								
									
										412
									
								
								src/components/SummaryComponent.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										412
									
								
								src/components/SummaryComponent.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,412 @@ | ||||
| <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, watch } from 'vue' | ||||
| import { useCategoriesStore } from '@/stores/categories.store' | ||||
| import type { Order, OrderProduct, Product } from '@/main' | ||||
| import { useRoutesStore } from '@/stores/routes.store' | ||||
| import { bool } from 'yup' | ||||
|  | ||||
| const ordersStore = useOrdersStore() | ||||
| const categoriesStore = useCategoriesStore() | ||||
| const routeStore = useRoutesStore() | ||||
|  | ||||
| const { orders, dates } = storeToRefs(ordersStore) | ||||
| const { routes } = storeToRefs(routeStore) | ||||
| const searchDate = ref<Date>(new Date(Date.now())) | ||||
| const confirmedOrders = ref<boolean>() | ||||
| const isSummed = ref<boolean>(true) | ||||
| const nipGrouped = ref(false) | ||||
| const isLoading = ref<boolean>(true) | ||||
| const summedProducts = ref<Array<Product>>([]) | ||||
| const products = ref<Array<Object>>() | ||||
| const ordersByRoute = ref<Map<string, Array<Order>>>(new Map<string, Array<Order>>()) | ||||
| const orderByRouteAndNipRef = ref<Map<string, Map<number, { | ||||
|   orders: Order[]; | ||||
|   products: OrderProduct[] | ||||
| }>>>(new Map<string, Map<number, { orders: Order[]; products: OrderProduct[] }>>) | ||||
| const activeButton = ref(null) | ||||
|  | ||||
| const watchSearchDate = watch(searchDate, async (oldSearchDate, newSeatchDate) => { | ||||
|   if (oldSearchDate != newSeatchDate) { | ||||
|     await fetchOrders() | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const watchConfirmedOrders = watch(confirmedOrders, async (oldConfirmedOrders, newConfirmedOrders) => { | ||||
|   if (oldConfirmedOrders != newConfirmedOrders) { | ||||
|     await fetchOrders() | ||||
|   } | ||||
| }) | ||||
| const setActive = (button) => { | ||||
|   activeButton.value = button; | ||||
|  | ||||
|   if (button === 'separate') { | ||||
|     isSummed.value = false; | ||||
|     nipGrouped.value = false; | ||||
|   } else if (button === 'grouped') { | ||||
|     isSummed.value = false; | ||||
|     nipGrouped.value = true; | ||||
|   } else if (button === 'summed') { | ||||
|     isSummed.value = true; | ||||
|     nipGrouped.value = false; | ||||
|   } | ||||
| }; | ||||
| async function fetchOrders() { | ||||
|   isLoading.value = true | ||||
|   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) ? false : null) | ||||
|   const productsMap = await categoriesStore.sumProductsFromOrders(orders.value) | ||||
|   summedProducts.value = [] | ||||
|   for (const product of productsMap.values()) { | ||||
|     if (product.SummedQuantity > 0) { | ||||
|       summedProducts.value.push(product) | ||||
|     } | ||||
|   } | ||||
|   await prepareProductsFromOrders() | ||||
|  | ||||
|   isLoading.value = false | ||||
| } | ||||
|  | ||||
| function addRoutes() { | ||||
|   for (const route of routes.value) { | ||||
|     ordersByRoute.value.set(route.MZT_Nazwa1, []) | ||||
|     } | ||||
|   ordersByRoute.value.set('brak', []) | ||||
| } | ||||
| function updateProducts(order: UnwrapRefSimple<Order> | UnwrapRefSimple<UnwrapRefSimple<Order>>) { | ||||
|   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.products.push(newProduct) | ||||
|   } | ||||
| } | ||||
| function prepareProductsFromOrders() { | ||||
|   products.value = [] | ||||
|   if (orders.value == undefined || routes.value == undefined) { | ||||
|     return | ||||
|   } | ||||
|   addRoutes() | ||||
|   for (const order of orders.value) { | ||||
|     order.products = [] | ||||
|     updateProducts(order) | ||||
|       const routeName = routes.value.find( route => { | ||||
|         return route.MZT_MZTID == order.MZN_MZTID | ||||
|       })?.MZT_Nazwa1; | ||||
|  | ||||
|       ordersByRoute.value.get(routeName != undefined ? routeName : "brak")?.push(order); | ||||
|   } | ||||
|   console.log(orders.value) | ||||
|   console.log(ordersByRoute.value) | ||||
|   groupByNip() | ||||
| } | ||||
|  | ||||
| function groupByNip() { | ||||
|   const orderByRouteAndNip = new Map<string, Map<number, { orders: Order[]; products: OrderProduct[] }>>() | ||||
|  | ||||
|   for (const [route, orders] of ordersByRoute.value) { | ||||
|     const ordersByNip = new Map<number, { orders: Order[]; products: OrderProduct[] }>() | ||||
|  | ||||
|     for (const order of orders) { | ||||
|       if (!ordersByNip.has(order.MZN_PodNipE)) { | ||||
|         ordersByNip.set(order.MZN_PodNipE, { orders: [], products: [] }) | ||||
|       } | ||||
|       const entry = ordersByNip.get(order.MZN_PodNipE) | ||||
|       entry.orders.push(order) | ||||
|  | ||||
|       for (const element of order.MZamElem) { | ||||
|         const existingProduct = entry.products.find(p => p.MZE_TwrId === element.MZE_TwrId) | ||||
|         if (existingProduct) { | ||||
|           existingProduct.MZE_TwrCena =String(Number(existingProduct.MZE_TwrCena).toFixed(2)) | ||||
|           existingProduct.MZE_TwrIlosc = String( | ||||
|             Number(Number(existingProduct.MZE_TwrIlosc) + Number(element.MZE_TwrIlosc)).toFixed(2) | ||||
|           ) | ||||
|           existingProduct.suma = Number(Number(existingProduct.MZE_TwrIlosc) * Number(existingProduct.MZE_TwrCena)).toFixed(2) | ||||
|         } else { | ||||
|           element.MZE_TwrCena = String(Number(element.MZE_TwrCena).toFixed(2)) | ||||
|           element.MZE_TwrIlosc = String(Number(element.MZE_TwrIlosc).toFixed(2)) | ||||
|           element.suma = Number(Number(element.MZE_TwrIlosc )*Number(element.MZE_TwrCena)).toFixed(2) | ||||
|           entry.products.push(element) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     orderByRouteAndNip.set(route, ordersByNip) | ||||
|   } | ||||
|   orderByRouteAndNipRef.value = orderByRouteAndNip | ||||
|   console.log(orderByRouteAndNip) | ||||
|  | ||||
| } | ||||
|  | ||||
| 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; | ||||
|  | ||||
|   console.log(ordersByRoute.value) | ||||
| }); | ||||
|  | ||||
|  | ||||
| onBeforeUnmount(async function() { | ||||
|     const siteControlStore = useSiteControlStore(); | ||||
|     await siteControlStore.newOrder(null); | ||||
| }) | ||||
|  | ||||
| function documnetType(order : Order):string { | ||||
|   if(order.MZN_TypDokumentu == 306) return ". Dokument WZ" | ||||
|   else return "" | ||||
| } | ||||
|  function ifOneWZExists(orders: Array<UnwrapRefSimple<Order>> ):string { | ||||
|    for (const order of orders) { | ||||
|      console.log(order.MZN_TypDokumentu); | ||||
|      if (order.MZN_TypDokumentu === 306) return ". Dokument WZ"; // ❗ PRZERYWA funkcję natychmiast | ||||
|    } | ||||
|    return "" | ||||
|  } | ||||
|  | ||||
| function hasNonEmptyUwagi(item: any): boolean { | ||||
|   let found = false; | ||||
|   item.orders.forEach(order => { | ||||
|     if(order.MZN_Uwagi) { | ||||
|       found = true; | ||||
|     } | ||||
|   }) | ||||
|  | ||||
|   return found; | ||||
| } | ||||
|  | ||||
| </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> | ||||
|       </div> | ||||
|       <div class="box mt-3"> | ||||
|  | ||||
|         <button | ||||
|           class="button is-fullwidth mb-3" | ||||
|           :class="{ 'is-active': activeButton === 'grouped' }" | ||||
|           @click="setActive('grouped')" | ||||
|         > | ||||
|           Zamówienia pogrupowane po NIP | ||||
|         </button> | ||||
|  | ||||
|         <button | ||||
|           class="button is-fullwidth mb-3" | ||||
|           :class="{ 'is-active': activeButton === 'separate' }" | ||||
|           @click="setActive('separate')" | ||||
|         > | ||||
|           Rozdzielone zamówienia | ||||
|         </button> | ||||
|  | ||||
|  | ||||
|         <button | ||||
|           class="button is-fullwidth mb-3" | ||||
|           :class="{ 'is-active': activeButton === 'summed' }" | ||||
|           @click="setActive('summed')" | ||||
|         > | ||||
|           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> | ||||
|           <div v-else-if="orders != undefined && orders.length != 0 && !isSummed" id="printMe"> | ||||
|             <div v-for="route in routes" :key="route.MZT_MZTID"> | ||||
|               <div v-if="route.MZT_Nazwa1 != undefined && ordersByRoute != undefined && ordersByRoute.has(route.MZT_Nazwa1)"> | ||||
|                 <div v-if=" | ||||
|                 //@ts-ignore | ||||
|                 ordersByRoute.has(route.MZT_Nazwa1) && ordersByRoute?.get(route.MZT_Nazwa1) != undefined && ordersByRoute?.get(route.MZT_Nazwa1).length > 0" | ||||
|                      style="page-break-after: always;"> | ||||
|                   <h1 class="is-size-2 is-fullwidth has-text-centered">{{ | ||||
|                     //@ts-ignore | ||||
|                       route.MZT_Nazwa1 + ' ' + ordersByRoute?.get(route.MZT_Nazwa1)[0].MZN_DataDos | ||||
|                     }}</h1> | ||||
|  | ||||
|                   <div v-if="!nipGrouped" v-for="order of ordersByRoute.get(route.MZT_Nazwa1)" :key="order.MZN_MZNID" | ||||
|                        class="pb-4" style="display: block; page-break-inside: avoid;"> | ||||
|                     <p class="is-size-6 px-2">NIP {{order.MZN_PodNipE}}</p> | ||||
|                     <p class="is-size-6 px-2">{{order.MZN_PodNazwa1 + order.MZN_PodNazwa2 + order.MZN_PodNazwa3}}</p> | ||||
|                     <p class="is-size-5 px-2">ZAMÓWIENIE NR {{order.MZN_MZNID}}{{documnetType(order)}}</p> | ||||
|                     <DataTable :value="order.products" class="mb-3" style="padding:0" scrollable> | ||||
|                       <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"/> | ||||
|                     </DataTable> | ||||
|                     <div v-if="order.MZN_Uwagi != undefined"> | ||||
|                       <p class="is-size-6 px-2">Uwagi</p> | ||||
|                       <p class="is-size-6 px-2">{{order.MZN_Uwagi}}</p> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                   <div v-else-if="nipGrouped" | ||||
|                        v-for="[nip, item] in Array.from(orderByRouteAndNipRef.get(route.MZT_Nazwa1) || new Map())" | ||||
|                        :key="nip" class="pb-4" style="display: block; page-break-inside: avoid;"> | ||||
|  | ||||
|                     <p class="is-size-5 px-2">NIP: {{ nip }}</p> | ||||
|  | ||||
|                     <p class="is-size-6 px-2"> | ||||
|                       {{ item.orders[0].MZN_PodNazwa1 + item.orders[0].MZN_PodNazwa2 + item.orders[0].MZN_PodNazwa3 | ||||
|                       }}</p> | ||||
|                     <p class="is-size-5 px-2" | ||||
|                        v-if="orderByRouteAndNipRef.get(route.MZT_Nazwa1)?.get(nip)?.orders?.length > 1 "> | ||||
|                       ZAMÓWIENIA NR | ||||
|                       <span | ||||
|                         v-for="(orderByNip, index) in orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders">{{ orderByNip.MZN_MZNID }}<span | ||||
|                           v-if="index !== orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders.length - 1">, </span> | ||||
|                       </span> | ||||
|                       <span>{{ifOneWZExists(orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders)}}</span> | ||||
|                     </p> | ||||
|                     <p class="is-size-5 px-2" | ||||
|                        v-else> | ||||
|                       ZAMÓWIENIE NR | ||||
|                       <span | ||||
|                         v-for="(orderByNip, index) in orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders">{{orderByNip.MZN_MZNID}}<span | ||||
|                           v-if="index !== orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders.length - 1">, </span> | ||||
|                       </span><span>{{ifOneWZExists(orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).orders)}}</span> | ||||
|  | ||||
|                     </p> | ||||
|                     <DataTable :value="orderByRouteAndNipRef.get(route.MZT_Nazwa1).get(nip).products" | ||||
|                                class="mb-3" style="padding:0" scrollable> | ||||
|                       <Column field="MZE_TwrKod" header="Indeks" frozen></Column> | ||||
|                       <Column field="MZE_TwrNazwa" header="Nazwa" /> | ||||
|                       <Column field="MZE_TwrIlosc" header="Ilość" /> | ||||
|                       <Column field="MZE_TwrJm" header="JM" /> | ||||
|                       <Column field="MZE_TwrCena" header="Cena" /> | ||||
|                       <Column field="suma" header="Suma" /> | ||||
|                     </DataTable> | ||||
|                     <div > | ||||
|                       <p v-if="hasNonEmptyUwagi(item)"  class="is-size-6 px-2">Uwagi</p> | ||||
|                       <p v-for="order in item.orders" class="is-size-6 px-2">{{ order.MZN_Uwagi }}</p> | ||||
|                     </div> | ||||
|                   </div> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|           </div> | ||||
|           <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" style="height: 100%"> | ||||
|             <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 scoped> | ||||
|   @media screen and (min-width: 500px) { | ||||
|     .box { | ||||
|       --bulma-box-padding: 1.5rem; | ||||
|     } | ||||
|   } | ||||
|   @media screen and (max-width: 500px) { | ||||
|     .box { | ||||
|       --bulma-box-padding: 0.75rem; | ||||
|     } | ||||
|   } | ||||
|   .is-active { | ||||
|     background-color: #66d1ff; | ||||
|     color: white; | ||||
|   } | ||||
|   .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> | ||||
							
								
								
									
										212
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										212
									
								
								src/main.ts
									
									
									
									
									
								
							| @@ -1,8 +1,210 @@ | ||||
| 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} | ||||
| ) | ||||
| const currentUrl = window.location.href | ||||
|  | ||||
| export const baseURL = currentUrl.includes("localhost") | ||||
|   ? "https://zamowienia-test.mleczarnia-kuzma.pl/api" | ||||
|   : currentUrl.substring(0, currentUrl.lastIndexOf("/") ) + "/api" ; | ||||
|  | ||||
| export const axiosInstance = axios.create({ | ||||
|   baseURL: baseURL, | ||||
|   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>, | ||||
|   products: any | ||||
| } | ||||
|  | ||||
| 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>, | ||||
|   products: any | ||||
| } | ||||
|  | ||||
| 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, | ||||
|   suma?: number | ||||
| } | ||||
|  | ||||
| export interface Route { | ||||
|   MZT_MZTID: number, | ||||
|   MZT_Nazwa1: string | ||||
| } | ||||
|  | ||||
| export function addDays(date : Date, days : number) { | ||||
|   const result = new Date(date); | ||||
|   result.setDate(result.getDate() + days); | ||||
|   return result; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										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}, | ||||
|   ] | ||||
| }); | ||||
|  | ||||
							
								
								
									
										63
									
								
								src/stores/categories.store.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/stores/categories.store.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| 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_JMPrzelicznikL)/Number(mapProduct.Twr_JMPrzelicznikM)); | ||||
|  | ||||
|             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} | ||||
| }) | ||||
							
								
								
									
										122
									
								
								src/stores/orders.store.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/stores/orders.store.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| 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>(); | ||||
|   const orderToClone = ref<boolean>(); | ||||
|  | ||||
|   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]; | ||||
|     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 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>(); | ||||
|     for (let i = 0; i <= 11; i++) { | ||||
|       tempDates.push(...await fetchDates(i)); | ||||
|     } | ||||
|     dates.value = tempDates; | ||||
|     console.log(dates.value); | ||||
|   } | ||||
|  | ||||
|   async function fetchDates(offset : number) { | ||||
|     const date = new Date(Date.now()); | ||||
|     date.setMonth(offset ); | ||||
|     const urlString = "/kalendarz/" + Number(date.getFullYear()) + "-" + Number(date.getMonth()+1); | ||||
|     const response = await axiosInstance.get(urlString, {withCredentials: true}); | ||||
|     const datesTemp :Array<Date> = response.data; | ||||
|     return datesTemp; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   function updateStores(contractor: Ref<Contractor | undefined>, contractors: Ref<Array<Contractor>>, tempOrder, route: Ref<Route | undefined>, routes: Ref<Array<Route> | undefined>, uuidString: string) { | ||||
|     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) | ||||
|     if(!orderToClone.value) { | ||||
|       uuid.value = uuidString | ||||
|     }else { | ||||
|       uuid.value = undefined | ||||
|     } | ||||
|     order.value = tempOrder | ||||
|     additionalNotes.value = tempOrder.MZN_Uwagi | ||||
|   } | ||||
|  | ||||
|   function setOrderQuantities(tempOrder, categories: Ref<Array<Category>>) { | ||||
|     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 | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   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; | ||||
|     updateStores(contractor, contractors, tempOrder, route, routes, uuidString) | ||||
|     if(categories.value == undefined) return; | ||||
|     setOrderQuantities(tempOrder, categories) | ||||
|   } | ||||
|  | ||||
|   return {orders,orderToClone, 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}; | ||||
| }); | ||||
							
								
								
									
										72
									
								
								src/stores/siteControl.store.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/stores/siteControl.store.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| 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); | ||||
|  | ||||
|   const orderStore = useOrdersStore(); | ||||
|   const contractorsStore = useContractorsStore(); | ||||
|   const categoriesStore = useCategoriesStore(); | ||||
|   const routeStore = useRoutesStore(); | ||||
|  | ||||
|  | ||||
|   async function switchToForm() { | ||||
|     await router.push("/"); | ||||
|   } | ||||
|  | ||||
|   async function switchToOrders() { | ||||
|     await router.push("/orders"); | ||||
|      } | ||||
|  | ||||
|   async function switchToTable() { | ||||
|     await router.push("/summary"); | ||||
|   } | ||||
|  | ||||
|   function checkTheme() { | ||||
|     isDarkTheme.value = !!window?.matchMedia?.('(prefers-color-scheme:dark)')?.matches; | ||||
|   } | ||||
|  | ||||
|   async function viewOrder(uuid : string, clone:boolean ) { | ||||
|     shownComponent.value = "mainForm"; | ||||
|     isLoading.value = true; | ||||
|     await categoriesStore.fetchCategories(); | ||||
|     const { contractor, contractors } = storeToRefs(contractorsStore); | ||||
|     const { categories } = storeToRefs(categoriesStore); | ||||
|     const { route, routes } = storeToRefs( routeStore ); | ||||
|     orderStore.orderToClone = clone; | ||||
|     await orderStore.loadOrder(uuid, false, contractor, contractors, categories, route, routes); | ||||
|     isLoading.value=false; | ||||
|     await router.push("/"); | ||||
|     window.scrollTo(0,0); | ||||
|   } | ||||
|  | ||||
|   async function newOrder(redirect : string) { | ||||
|     const { order, uuid, deliveryDate, orderDate, additionalNotes } = storeToRefs(orderStore); | ||||
|     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; | ||||
|     additionalNotes.value = undefined; | ||||
|     await categoriesStore.fetchCategories(); | ||||
|     if (redirect) | ||||
|     { | ||||
|       await router.push(redirect); | ||||
|       window.scrollTo(0,0); | ||||
|     } | ||||
|   } | ||||
|   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("/"); | ||||
|   } | ||||
|  | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
|   <div class="container is-flex is-justify-content-space-evenly is-align-items-center" style="min-height: calc(100vh - 3.5rem)"> | ||||
|     <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> | ||||
							
								
								
									
										63
									
								
								src/views/MainView.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/views/MainView.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| <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 || ordersStore.orderToClone" | ||||
|       /> | ||||
|       <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