- Introduced a new 'sleep' boolean field in the Production model to indicate if production is suspended. - Updated FalukantService to include 'sleep' in the production attributes. - Enhanced MessagesDialog and ProductionSection components to display the production status and handle branch names. - Added corresponding translations for 'status', 'sleep', and 'active' in both German and English locale files.
208 lines
7.8 KiB
Vue
208 lines
7.8 KiB
Vue
<template>
|
|
<div class="production-section">
|
|
<div v-if="productions && productions.length > 0">
|
|
<h4>{{ $t('falukant.branch.production.current') }}</h4>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>{{ $t('falukant.branch.production.product') }}</th>
|
|
<th>{{ $t('falukant.branch.production.quantity') }}</th>
|
|
<th>{{ $t('falukant.branch.production.ending') }}</th>
|
|
<th>{{ $t('falukant.branch.production.remainingTime') }}</th>
|
|
<th>{{ $t('falukant.branch.production.status') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="production in productions" :key="production.id">
|
|
<td>{{ $t(`falukant.product.${production.productType.labelTr}`) }}</td>
|
|
<td>{{ production.quantity }}</td>
|
|
<td>{{ calculateEndDateTime(production.startTimestamp, production.productType.productionTime) }}</td>
|
|
<td>{{ production.sleep ? '-' : calculateRemainingTime(production.startTimestamp, production.productType.productionTime) + ' s' }}</td>
|
|
<td>
|
|
<span v-if="production.sleep" class="production-sleep">{{ $t('falukant.branch.production.sleep') }}</span>
|
|
<span v-else>{{ $t('falukant.branch.production.active') }}</span>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div v-if="(!productions || productions.length < 2)">
|
|
<div>
|
|
<label for="product">{{ $t('falukant.branch.production.selectProduct') }}</label>
|
|
<select name="product" id="product" v-model="selectedProduct">
|
|
<option v-for="product in products" :key="product.id" :value="product.id">
|
|
{{ $t(`falukant.product.${product.labelTr}`) }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label for="quantity">{{ $t('falukant.branch.production.quantity') }}</label>
|
|
<input type="number" id="quantity" v-model.number="productionQuantity" min="1" max="200"/>
|
|
</div>
|
|
<div>
|
|
<p>
|
|
{{ $t('falukant.branch.production.storageAvailable') }}:
|
|
<strong>{{ freeStorage }}</strong>
|
|
</p>
|
|
<p>{{ $t('falukant.branch.production.cost') }}:
|
|
<strong>{{ calculateProductionCost() }}</strong>
|
|
</p>
|
|
<p>{{ $t('falukant.branch.production.duration') }}:
|
|
<strong>{{ calculateProductionDuration(selectedProduct) }}</strong>
|
|
</p>
|
|
<p>{{ $t('falukant.branch.production.revenue') }}:
|
|
<strong>{{ calculateProductionRevenue() }}</strong>
|
|
</p>
|
|
</div>
|
|
<button @click="startProduction" :disabled="!selectedProduct || productionQuantity < 1">
|
|
{{ $t('falukant.branch.production.start') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import apiClient from '@/utils/axios.js';
|
|
export default {
|
|
name: "ProductionSection",
|
|
props: {
|
|
branchId: { type: Number, required: true },
|
|
products: { type: Array, required: true },
|
|
},
|
|
data() {
|
|
return {
|
|
productions: [],
|
|
selectedProduct: null,
|
|
productionQuantity: 1,
|
|
currentTime: Date.now(),
|
|
timer: null,
|
|
currentStorage: 0,
|
|
maxStorage: 0,
|
|
};
|
|
},
|
|
computed: {
|
|
freeStorage() {
|
|
const diff = this.maxStorage - this.currentStorage;
|
|
return diff > 0 ? diff : 0;
|
|
},
|
|
},
|
|
async mounted() {
|
|
await this.loadProductions();
|
|
await this.loadStorage();
|
|
this.timer = setInterval(() => {
|
|
this.currentTime = Date.now();
|
|
}, 1000);
|
|
},
|
|
beforeUnmount() {
|
|
if (this.timer) {
|
|
clearInterval(this.timer);
|
|
this.timer = null;
|
|
}
|
|
},
|
|
methods: {
|
|
async loadProductions() {
|
|
try {
|
|
const response = await apiClient.get(`/api/falukant/branches/${this.branchId}`);
|
|
this.productions = response.data.productions.sort((a, b) => {
|
|
const endTimeA = new Date(a.startTimestamp).getTime() + a.productType.productionTime * 60 * 1000;
|
|
const endTimeB = new Date(b.startTimestamp).getTime() + b.productType.productionTime * 60 * 1000;
|
|
return endTimeA - endTimeB;
|
|
});
|
|
} catch (error) {
|
|
console.error('Error loading productions:', error);
|
|
}
|
|
},
|
|
async loadStorage() {
|
|
try {
|
|
const { data } = await apiClient.get(`/api/falukant/storage/${this.branchId}`);
|
|
this.currentStorage = data.totalUsedCapacity;
|
|
this.maxStorage = data.maxCapacity;
|
|
} catch (error) {
|
|
console.error('Error loading storage for production section:', error);
|
|
}
|
|
},
|
|
calculateProductionCost() {
|
|
if (!this.products) return 0;
|
|
const product = this.products.find(p => p.id === this.selectedProduct);
|
|
return product ? 6 * product.category * this.productionQuantity : 0;
|
|
},
|
|
calculateProductionDuration(productId) {
|
|
if (!this.products || !productId) return 0;
|
|
const product = this.products.find(p => p.id === productId);
|
|
if (!product) return 0;
|
|
const totalMinutes = product.productionTime * 60;
|
|
return (totalMinutes / 60).toFixed(2).replace('.', ':');
|
|
},
|
|
calculateProductionRevenue() {
|
|
if (!this.selectedProduct || !this.products) return 0;
|
|
const product = this.products.find(p => p.id === this.selectedProduct);
|
|
if (!product) return 0;
|
|
const revenue = this.calculateProductRevenue(product).absolute * this.productionQuantity;
|
|
return revenue.toFixed(2).toLocaleString();
|
|
},
|
|
calculateEndDateTime(startTimestamp, productionTime) {
|
|
const start = new Date(startTimestamp);
|
|
const end = new Date(start.getTime() + productionTime * 60 * 1000);
|
|
return end.toLocaleString();
|
|
},
|
|
calculateRemainingTime(startTimestamp, productionTime) {
|
|
const start = new Date(startTimestamp).getTime();
|
|
const end = start + productionTime * 60 * 1000;
|
|
const secondsLeft = Math.max(Math.floor((end - this.currentTime) / 1000), 0);
|
|
return secondsLeft;
|
|
},
|
|
async startProduction() {
|
|
if (this.selectedProduct && this.productionQuantity > 0) {
|
|
this.productionQuantity = Math.min(this.productionQuantity, 200);
|
|
let productionQuantity = this.productionQuantity;
|
|
while (productionQuantity > 0) {
|
|
const sendQuantitiy = Math.min(productionQuantity, 100);
|
|
productionQuantity -= sendQuantitiy;
|
|
try {
|
|
await apiClient.post(`/api/falukant/production`, {
|
|
branchId: this.branchId,
|
|
productId: this.selectedProduct,
|
|
quantity: sendQuantitiy,
|
|
});
|
|
this.loadProductions();
|
|
} catch (error) {
|
|
alert(this.$t(`falukant.branch.production.error${error.response.data.error}`));
|
|
}
|
|
}
|
|
}
|
|
},
|
|
calculateProductRevenue(product) {
|
|
if (!product.knowledges || product.knowledges.length === 0) {
|
|
return { absolute: 0, perMinute: 0 };
|
|
}
|
|
const knowledgeFactor = product.knowledges[0].knowledge || 0;
|
|
const maxPrice = product.sellCost;
|
|
const minPrice = maxPrice * 0.6;
|
|
const revenuePerUnit = minPrice + (maxPrice - minPrice) * (knowledgeFactor / 100);
|
|
const perMinute = product.productionTime > 0 ? revenuePerUnit / product.productionTime : 0;
|
|
return {
|
|
absolute: revenuePerUnit.toFixed(2),
|
|
perMinute: perMinute.toFixed(2),
|
|
};
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.production-section {
|
|
border: 1px solid #ccc;
|
|
margin: 10px 0;
|
|
border-radius: 4px;
|
|
padding: 10px;
|
|
}
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
th, td {
|
|
padding: 8px;
|
|
border: 1px solid #ddd;
|
|
}
|
|
</style>
|
|
|