Updated Shipping Note

This commit is contained in:
Luca Haid
2025-03-20 14:09:23 +01:00
parent 438cd85d5f
commit b293167527
4 changed files with 82 additions and 30 deletions
@@ -21,6 +21,7 @@ Vue.component('warehouse-shipping-note-modal', {
textElements: [], textElements: [],
hoursEntries: [], hoursEntries: [],
}, },
hoursLoading: false,
geoAddr: '', geoAddr: '',
positionsConfig: { positionsConfig: {
customOrdering: 'article', customOrdering: 'article',
@@ -112,6 +113,7 @@ Vue.component('warehouse-shipping-note-modal', {
<h4 class="text-center">Stunden</h4> <h4 class="text-center">Stunden</h4>
<tt-positions-manager <tt-positions-manager
ref="hoursManager" ref="hoursManager"
:submit-loading="hoursLoading"
@updateField-userId="updateCarId" @updateField-userId="updateCarId"
@updateField-carId="updateKilometer" @updateField-carId="updateKilometer"
:config="hoursConfig" v-model="shippingNote.hoursEntries" sm row/> :config="hoursConfig" v-model="shippingNote.hoursEntries" sm row/>
@@ -145,6 +147,7 @@ Vue.component('warehouse-shipping-note-modal', {
this.shippingNote.deliveryAddressPLZ = address["postcode"]; this.shippingNote.deliveryAddressPLZ = address["postcode"];
this.shippingNote.deliveryAddressCity = address["village"] ?? address.city ?? address["town"]; this.shippingNote.deliveryAddressCity = address["village"] ?? address.city ?? address["town"];
this.updateKilometer().then();
} }
}, },
methods: { methods: {
@@ -166,15 +169,19 @@ Vue.component('warehouse-shipping-note-modal', {
}, },
async updateCarId(userId) { async updateCarId(userId) {
if (!userId) return this.$refs.hoursManager.updateField('carId', null); if (!userId) return this.$refs.hoursManager.updateField('carId', null);
this.hoursLoading = true;
const {data} = await axios.get(window.TT_CONFIG["BASE_PATH"] + '/WarehouseShippingNote/timerecordingCarForUser?userId=' + userId); const {data} = await axios.get(window.TT_CONFIG["BASE_PATH"] + '/WarehouseShippingNote/timerecordingCarForUser?userId=' + userId);
if (data.status === 'USER_NO_CAR') this.$refs.hoursManager.updateField('carId', null); if (data.status === 'USER_NO_CAR') this.$refs.hoursManager.updateField('carId', null);
else this.$refs.hoursManager.updateField('carId', data.id); else this.$refs.hoursManager.updateField('carId', data.id);
this.hoursLoading = false;
}, },
async updateKilometer(carId) { async updateKilometer(carId) {
if (!carId) return this.$refs.hoursManager.updateField('kilometerCount', null); if (!carId) return this.$refs.hoursManager.updateField('kilometerCount', null);
this.hoursLoading = true;
const delAddr = this.shippingNote.deliveryAddressLine + ' ' + this.shippingNote.deliveryAddressPLZ + ' ' + this.shippingNote.deliveryAddressCity; const delAddr = this.shippingNote.deliveryAddressLine + ' ' + this.shippingNote.deliveryAddressPLZ + ' ' + this.shippingNote.deliveryAddressCity;
const {data} = await axios.get(window.TT_CONFIG["BASE_PATH"] + '/WarehouseShippingNote/getDistance?from=Xinon%20GmbH&to=' + delAddr); const {data} = await axios.get(window.TT_CONFIG["BASE_PATH"] + '/WarehouseShippingNote/getDistance?from=Xinon%20GmbH&to=' + delAddr);
this.$refs.hoursManager.updateField('kilometerCount', data.distance); this.$refs.hoursManager.updateField('kilometerCount', data.distance);
this.hoursLoading = false;
} }
} }
}) })
@@ -346,3 +346,23 @@ td {
vertical-align: top !important; vertical-align: top !important;
text-align: center; text-align: center;
} }
/* tt-button */
.spinner {
display: inline-block;
width: 11px;
height: 11px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.btn-loading {
cursor: not-allowed;
opacity: 0.7;
}
+29 -8
View File
@@ -4,39 +4,60 @@ Vue.component('tt-button', {
template: ` template: `
<div> <div>
<template v-if="href"> <template v-if="href">
<a :href="href" class="btn" :class="buttonClasses" onclick="typeof confirmText === 'string' ? confirm(confirmText) : true"> <a :href="href" class="btn" :class="buttonClasses" @click="handleClick">
<template v-if="loading">
<span class="spinner"></span>
</template>
<template v-else>
<i v-if="icon" :class="icon"></i> <i v-if="icon" :class="icon"></i>
{{text}} {{text}}
</template>
</a> </a>
</template> </template>
<template v-else> <template v-else>
<button @click="$emit('click')" class="btn" :class="buttonClasses"> <button @click="handleClick" class="btn" :class="buttonClasses" :disabled="loading">
<template v-if="loading">
<span class="spinner"></span>
</template>
<template v-else>
<i v-if="icon" :class="icon"></i> <i v-if="icon" :class="icon"></i>
{{text}} {{text}}
</template>
</button> </button>
</template> </template>
</div> </div>
`, props: { `,
props: {
sm: {type: Boolean, default: false}, sm: {type: Boolean, default: false},
icon: {type: String, required: false}, icon: {type: String, required: false},
text: {type: String, required: false}, text: {type: String, required: false},
href: {type: String, required: false}, href: {type: String, required: false},
additionalClass: {type: String, required: false}, additionalClass: {type: String, required: false},
// TODO: maybe instead of browser confirmation add a custom beautiful confirmation dialog
confirmText: {type: String, required: false}, confirmText: {type: String, required: false},
}, computed: { loading: {type: Boolean, default: false},
},
computed: {
buttonClasses() { buttonClasses() {
const classes = { const classes = {
'btn-sm': this.sm, 'btn-sm': this.sm,
'btn-loading': this.loading
} }
if (!this.additionalClass) return classes if (this.additionalClass) {
this.additionalClass.split(' ').forEach(className => {
for (const className of this.additionalClass.split(' ')) {
classes[className] = true classes[className] = true
})
} }
return classes return classes
} }
},
methods: {
handleClick(event) {
if (this.loading) return event.preventDefault();
if (typeof this.confirmText === 'string' && !confirm(this.confirmText)) return event.preventDefault();
this.$emit('click', event)
}
} }
}) })
@@ -35,6 +35,7 @@ Vue.component('tt-positions-manager',
value: {type: [Array, String], required: false}, value: {type: [Array, String], required: false},
config: {type: Object, required: true}, config: {type: Object, required: true},
groupMode: {type: Boolean, default: false}, groupMode: {type: Boolean, default: false},
submitLoading: {type: Boolean, default: false}
}, },
data() { data() {
return { return {
@@ -98,7 +99,10 @@ Vue.component('tt-positions-manager',
</template> </template>
</template> </template>
<div class="button-wrapper"> <div class="button-wrapper">
<tt-button @click="saveEntry" sm :additional-class="selectedIndex === null ? 'btn-primary' : 'btn-success'" <tt-button @click="saveEntry"
sm
:loading="submitLoading"
:additional-class="selectedIndex === null ? 'btn-primary' : 'btn-success'"
:text="selectedIndex === null ? 'Hinzufügen' : 'Aktualisieren'"/> :text="selectedIndex === null ? 'Hinzufügen' : 'Aktualisieren'"/>
</div> </div>
</div> </div>