Merge branch 'WarehouseShippingNote/add-loader' into 'master'

Updated Shipping Note

See merge request fronk/thetool!1125
This commit is contained in:
Luca Haid
2025-03-20 13:18:57 +00:00
4 changed files with 82 additions and 30 deletions

View File

@@ -21,6 +21,7 @@ Vue.component('warehouse-shipping-note-modal', {
textElements: [],
hoursEntries: [],
},
hoursLoading: false,
geoAddr: '',
positionsConfig: {
customOrdering: 'article',
@@ -112,6 +113,7 @@ Vue.component('warehouse-shipping-note-modal', {
<h4 class="text-center">Stunden</h4>
<tt-positions-manager
ref="hoursManager"
:submit-loading="hoursLoading"
@updateField-userId="updateCarId"
@updateField-carId="updateKilometer"
: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.deliveryAddressCity = address["village"] ?? address.city ?? address["town"];
this.updateKilometer().then();
}
},
methods: {
@@ -166,15 +169,19 @@ Vue.component('warehouse-shipping-note-modal', {
},
async updateCarId(userId) {
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);
if (data.status === 'USER_NO_CAR') this.$refs.hoursManager.updateField('carId', null);
else this.$refs.hoursManager.updateField('carId', data.id);
this.hoursLoading = false;
},
async updateKilometer(carId) {
if (!carId) return this.$refs.hoursManager.updateField('kilometerCount', null);
this.hoursLoading = true;
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);
this.$refs.hoursManager.updateField('kilometerCount', data.distance);
this.hoursLoading = false;
}
}
})

View File

@@ -345,4 +345,24 @@ td {
.tt-table-header {
vertical-align: top !important;
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;
}

View File

@@ -1,42 +1,63 @@
// noinspection JSCheckFunctionSignatures
Vue.component('tt-button', {
//language=Vue
template: `
<div>
<template v-if="href">
<a :href="href" class="btn" :class="buttonClasses" onclick="typeof confirmText === 'string' ? confirm(confirmText) : true">
<i v-if="icon" :class="icon"></i>
{{text}}
</a>
</template>
<template v-else>
<button @click="$emit('click')" class="btn" :class="buttonClasses">
<i v-if="icon" :class="icon"></i>
{{text}}
</button>
</template>
</div>
`, props: {
sm: {type: Boolean, default: false},
icon: {type: String, required: false},
text: {type: String, required: false},
href: {type: String, required: false},
template: `
<div>
<template v-if="href">
<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>
{{text}}
</template>
</a>
</template>
<template v-else>
<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>
{{text}}
</template>
</button>
</template>
</div>
`,
props: {
sm: {type: Boolean, default: false},
icon: {type: String, required: false},
text: {type: String, required: false},
href: {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},
}, computed: {
confirmText: {type: String, required: false},
loading: {type: Boolean, default: false},
},
computed: {
buttonClasses() {
const classes = {
'btn-sm': this.sm,
'btn-loading': this.loading
}
if (!this.additionalClass) return classes
for (const className of this.additionalClass.split(' ')) {
classes[className] = true
if (this.additionalClass) {
this.additionalClass.split(' ').forEach(className => {
classes[className] = true
})
}
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)
}
}
})
})

View File

@@ -35,6 +35,7 @@ Vue.component('tt-positions-manager',
value: {type: [Array, String], required: false},
config: {type: Object, required: true},
groupMode: {type: Boolean, default: false},
submitLoading: {type: Boolean, default: false}
},
data() {
return {
@@ -98,7 +99,10 @@ Vue.component('tt-positions-manager',
</template>
</template>
<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'"/>
</div>
</div>