301 lines
12 KiB
Vue
301 lines
12 KiB
Vue
<template>
|
|
<div class="contenthidden">
|
|
<StatusBar />
|
|
<div class="contentscroll">
|
|
<h2>{{ $t('falukant.education.title') }}</h2>
|
|
<SimpleTabs v-model="activeTab" :tabs="tabs" />
|
|
|
|
<!-- SELF -->
|
|
<div v-if="activeTab === 'self'">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>{{ $t('falukant.education.table.article') }}</th>
|
|
<th>{{ $t('falukant.education.table.knowledge') }}</th>
|
|
<th>{{ $t('falukant.education.table.activity') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="product in products" :key="product.id">
|
|
<td>{{ $t(`falukant.product.${product.labelTr}`) }}</td>
|
|
<td>{{ product.knowledges[0].knowledge }} %</td>
|
|
<td>
|
|
<button
|
|
v-if="ownRunningEducations.length === 0"
|
|
@click="learnItem(product.id, 'self')"
|
|
>
|
|
{{ $t('falukant.education.learn') }}
|
|
({{ formatCost(getSelfCost(product.knowledges[0].knowledge)) }})
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div>
|
|
<button
|
|
v-if="ownRunningEducations.length === 0"
|
|
@click="learnAll('self')"
|
|
>
|
|
{{ $t('falukant.education.learnAll') }}
|
|
({{ formatCost(getSelfAllCost()) }})
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- CHILDREN -->
|
|
<div v-else-if="activeTab === 'children'">
|
|
<div>
|
|
<select v-model="activeChild">
|
|
<option v-for="child in children" :key="child.id" :value="child.id">
|
|
{{ child.name }} ({{ child.age }})
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<table v-if="activeChild">
|
|
<thead>
|
|
<tr>
|
|
<th>{{ $t('falukant.education.table.article') }}</th>
|
|
<th>{{ $t('falukant.education.table.knowledge') }}</th>
|
|
<th>{{ $t('falukant.education.table.activity') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="product in products" :key="product.id">
|
|
<td>{{ $t(`falukant.product.${product.labelTr}`) }}</td>
|
|
<td>{{ getChildKnowledge(product.id) }} %</td>
|
|
<td>
|
|
<button
|
|
v-if="childNotInLearning()"
|
|
@click="learnItem(product.id, 'children', activeChild)"
|
|
>
|
|
{{ $t('falukant.education.learn') }}
|
|
({{ formatCost(getChildCost(product.id)) }})
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div>
|
|
<button
|
|
v-if="childrenRunningEducations.length === 0"
|
|
@click="learnAll('children', activeChild)"
|
|
>
|
|
{{ $t('falukant.education.learnAll') }}
|
|
({{ formatCost(getChildrenAllCost(activeChild)) }})
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- DIRECTOR -->
|
|
<div v-else-if="activeTab === 'director'">
|
|
<div>
|
|
<select v-model="activeDirector">
|
|
<option v-for="director in directors" :key="director.id" :value="director.id">
|
|
{{ director.character.nobleTitle.tr }}
|
|
{{ director.character.definedFirstName.name }}
|
|
{{ director.character.definedLastName.name }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<table v-if="activeDirector">
|
|
<thead>
|
|
<tr>
|
|
<th>{{ $t('falukant.education.table.article') }}</th>
|
|
<th>{{ $t('falukant.education.table.knowledge') }}</th>
|
|
<th>{{ $t('falukant.education.table.activity') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="product in products" :key="product.id">
|
|
<td>{{ $t(`falukant.product.${product.labelTr}`) }}</td>
|
|
<td>{{ getDirectorKnowledge(product.id) }} %</td>
|
|
<td>
|
|
<button
|
|
v-if="directorNotInLearning()"
|
|
@click="learnItem(product.id, 'director', getDirectorCharacterId())"
|
|
>
|
|
{{ $t('falukant.education.learn') }}
|
|
({{ formatCost(getDirectorCost(product.id)) }})
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div v-if="activeDirector">
|
|
<button
|
|
v-if="directorNotInLearning()"
|
|
@click="learnAll('director', getDirectorCharacterId())"
|
|
>
|
|
{{ $t('falukant.education.learnAll') }}
|
|
({{ formatCost(getDirectorAllCost(getDirectorCharacterId())) }})
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import StatusBar from '@/components/falukant/StatusBar.vue';
|
|
import MessageDialog from '@/dialogues/standard/MessageDialog.vue';
|
|
import ErrorDialog from '@/dialogues/standard/ErrorDialog.vue';
|
|
import apiClient from '@/utils/axios.js';
|
|
import SimpleTabs from '@/components/SimpleTabs.vue'
|
|
|
|
const KNOWLEDGE_MAX = 99;
|
|
|
|
const COST_CONFIG = {
|
|
one: { min: 50, max: 5000 },
|
|
all: { min: 400, max: 40000 }
|
|
};
|
|
|
|
export default {
|
|
name: 'EducationView',
|
|
components: { StatusBar, MessageDialog, ErrorDialog, SimpleTabs },
|
|
data() {
|
|
return {
|
|
activeTab: 'self',
|
|
tabs: [
|
|
{ value: 'self', label: 'falukant.education.self.title' },
|
|
{ value: 'children', label: 'falukant.education.children.title' },
|
|
{ value: 'director', label: 'falukant.education.director.title' }
|
|
],
|
|
products: [],
|
|
ownRunningEducations: [],
|
|
childrenRunningEducations: [],
|
|
directorRunningEducations: [],
|
|
directors: [],
|
|
activeDirector: null,
|
|
children: [],
|
|
activeChild: null,
|
|
}
|
|
},
|
|
async mounted() {
|
|
await this.loadProducts();
|
|
await this.loadEducations();
|
|
await this.loadDirectors();
|
|
await this.loadChildren();
|
|
},
|
|
methods: {
|
|
// Basis-Funktion: lineare Interpolation
|
|
computeCost(knowledgePercent, type = 'one') {
|
|
const cfg = COST_CONFIG[type];
|
|
const f = Math.min(Math.max(knowledgePercent, 0), KNOWLEDGE_MAX) / KNOWLEDGE_MAX;
|
|
return cfg.min + (cfg.max - cfg.min) * f;
|
|
},
|
|
formatCost(value) {
|
|
return Math.round(value).toLocaleString(this.$i18n.locale || 'de-DE');
|
|
},
|
|
|
|
// SELF
|
|
getSelfCost(knowledge) {
|
|
return this.computeCost(knowledge, 'one');
|
|
},
|
|
getSelfAllCost() {
|
|
const avg = this.products.reduce((sum, p) => sum + (p.knowledges[0].knowledge||0), 0) / this.products.length;
|
|
return this.computeCost(avg, 'all');
|
|
},
|
|
|
|
// CHILD
|
|
getChildKnowledge(productId) {
|
|
const child = this.children.find(c => c.id === this.activeChild);
|
|
if (!child?.knowledge) return 0;
|
|
const e = child.knowledge.find(k => k.id === productId);
|
|
return e ? e.knowledge : 0;
|
|
},
|
|
getChildCost(productId) {
|
|
return this.computeCost(this.getChildKnowledge(productId), 'one');
|
|
},
|
|
getChildrenAllCost(childId) {
|
|
const child = this.children.find(c => c.id === childId);
|
|
const avg = (child.knowledge || []).reduce((s,k) => s + k.knowledge, 0) / (child.knowledge?.length||1);
|
|
return this.computeCost(avg, 'all');
|
|
},
|
|
childNotInLearning() {
|
|
const child = this.children.find(c => c.id === this.activeChild);
|
|
return !this.childrenRunningEducations.some(e => e.learningCharacter.id === child.id);
|
|
},
|
|
|
|
// DIRECTOR
|
|
getDirectorKnowledge(productId) {
|
|
const dir = this.directors.find(d => d.id === this.activeDirector);
|
|
const know = dir?.character?.knowledges?.find(k => k.productId === productId);
|
|
return know ? know.knowledge : 0;
|
|
},
|
|
getDirectorCost(productId) {
|
|
return this.computeCost(this.getDirectorKnowledge(productId), 'one');
|
|
},
|
|
getDirectorAllCost(dirCharId) {
|
|
const dir = this.directors.find(d => d.character.id === dirCharId);
|
|
const avg = (dir.character.knowledges || []).reduce((s,k) => s + k.knowledge, 0) / (dir.character.knowledges.length||1);
|
|
return this.computeCost(avg, 'all');
|
|
},
|
|
getDirectorCharacterId() {
|
|
return this.directors.find(d => d.id === this.activeDirector)?.character?.id;
|
|
},
|
|
directorNotInLearning() {
|
|
const dirCharId = this.getDirectorCharacterId();
|
|
return !this.directorRunningEducations.some(e => e.learningCharacter.id === dirCharId);
|
|
},
|
|
|
|
// Laden & Aktionen
|
|
async loadProducts() {
|
|
const r = await apiClient.get('/api/falukant/products');
|
|
this.products = r.data;
|
|
},
|
|
async loadEducations() {
|
|
const r = await apiClient.get('/api/falukant/education');
|
|
this.ownRunningEducations = r.data.filter(e => e.recipient.tr === 'self');
|
|
this.childrenRunningEducations = r.data.filter(e => e.recipient.tr === 'children');
|
|
this.directorRunningEducations = r.data.filter(e => e.recipient.tr === 'director');
|
|
},
|
|
async loadDirectors() {
|
|
const r = await apiClient.get('/api/falukant/directors');
|
|
this.directors = r.data;
|
|
this.activeDirector = this.directors[0]?.id;
|
|
},
|
|
async loadChildren() {
|
|
const r = await apiClient.get('/api/falukant/family/children');
|
|
this.children = r.data;
|
|
this.activeChild = this.children[0]?.id;
|
|
},
|
|
|
|
async learnItem(item, student, studentId) {
|
|
await apiClient.post('/api/falukant/education', { item, student, studentId });
|
|
await this.loadEducations();
|
|
},
|
|
async learnAll(student, studentId) {
|
|
await apiClient.post('/api/falukant/education', { item: 'all', student, studentId });
|
|
await this.loadEducations();
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
h2 {
|
|
padding-top: 20px;
|
|
}
|
|
|
|
.simple-tabs {
|
|
display: flex;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.simple-tab {
|
|
padding: 0.5rem 1rem;
|
|
background: #fff;
|
|
border: none;
|
|
cursor: pointer;
|
|
transition: background 0.2s;
|
|
}
|
|
.simple-tab.active {
|
|
background: #F9A22C;
|
|
color: #000;
|
|
}
|
|
.tab-content {
|
|
margin-top: 1rem;
|
|
}
|
|
</style>
|