Files
yourpart3/frontend/src/views/falukant/NobilityView.vue

180 lines
5.9 KiB
Vue

<template>
<div class="contenthidden">
<StatusBar />
<div class="contentscroll">
<h2>{{ $t('falukant.nobility.title') }}</h2>
<SimpleTabs v-model="activeTab" :tabs="tabs" />
<!-- OVERVIEW -->
<div v-if="activeTab === 'overview'">
<div class="nobility-section">
<p>
<strong>
{{ $t(`falukant.titles.${gender}.${current.labelTr}`) }}
</strong>
</p>
</div>
</div>
<!-- ADVANCE -->
<div v-else-if="activeTab === 'advance'">
<div class="advance-section" v-if="next && next.labelTr">
<p>
{{ $t('falukant.nobility.nextTitle') }}:
<strong>{{ $t(`falukant.titles.${gender}.${next.labelTr}`) }}</strong>
</p>
<ul class="prerequisites" v-if="next.requirements && next.requirements.length > 0">
<li v-for="req in next.requirements" :key="req.titleId">
{{ $t(`falukant.nobility.requirement.${req.requirementType}`, { amount: formatCost(req.requirementValue) }) }}
</li>
</ul>
<button v-if="canAdvance" @click="applyAdvance" class="button" :disabled="isAdvancing">
<span v-if="!isAdvancing">{{ $t('falukant.nobility.advance.confirm') }}</span>
<span v-else>{{ $t('falukant.nobility.advance.processing') }}</span>
</button>
<p v-else-if="nextAdvanceAt" class="cooldown-message">
{{ $t('falukant.nobility.cooldown', { date: formatDate(nextAdvanceAt) }) }}
</p>
</div>
<div v-else class="advance-section">
<p style="color: red;">Fehler: Keine nächste Titel-Information verfügbar. Bitte Seite neu laden.</p>
</div>
</div>
</div>
</div>
</template>
<script>
import StatusBar from '@/components/falukant/StatusBar.vue';
import SimpleTabs from '@/components/SimpleTabs.vue';
import apiClient from '@/utils/axios.js';
import { mapState } from 'vuex';
export default {
name: 'NobilityView',
components: { StatusBar, SimpleTabs },
data() {
return {
activeTab: 'overview',
tabs: [
{ value: 'overview', label: 'falukant.nobility.tabs.overview' },
{ value: 'advance', label: 'falukant.nobility.tabs.advance' }
],
current: { labelTr: '', requirements: [], charactersWithNobleTitle: [] },
next: { labelTr: '', requirements: [] },
nextAdvanceAt: null,
isAdvancing: false
};
},
computed: {
...mapState(['socket', 'falukantData']),
gender() {
return this.current.charactersWithNobleTitle[0]?.gender || 'male';
},
canAdvance() {
if (!this.next) return false;
if (!this.nextAdvanceAt) return true;
const now = new Date();
const nextDate = new Date(this.nextAdvanceAt);
return nextDate <= now;
}
},
async mounted() {
await this.loadNobility();
this.setupSocketEvents();
},
beforeUnmount() {
if (this.socket) {
this.socket.off('falukantUpdateStatus', this.loadNobility);
}
},
methods: {
setupSocketEvents() {
if (this.socket) {
this.socket.on('falukantUpdateStatus', (data) => {
this.handleEvent({ event: 'falukantUpdateStatus', ...data });
});
} else {
setTimeout(() => this.setupSocketEvents(), 1000);
}
},
handleEvent(eventData) {
switch (eventData.event) {
case 'falukantUpdateStatus':
this.loadNobility();
break;
}
},
async loadNobility() {
try {
const { data } = await apiClient.get('/api/falukant/nobility');
this.current = data.current || { labelTr: '', requirements: [], charactersWithNobleTitle: [] };
this.next = data.next || { labelTr: '', requirements: [] };
this.nextAdvanceAt = data.nextAdvanceAt || null;
} catch (err) {
console.error('Error loading nobility:', err);
}
},
async applyAdvance() {
if (!this.canAdvance || this.isAdvancing) return;
this.isAdvancing = true;
try {
await apiClient.post('/api/falukant/nobility');
await this.loadNobility();
} catch (err) {
console.error('Error advancing nobility:', err);
} finally {
this.isAdvancing = false;
}
},
handleDaemonMessage(evt) {
if (evt.data === 'ping') return;
const msg = JSON.parse(evt.data);
if (['nobilityChange', 'moneyChange'].includes(msg.event)) this.loadNobility();
},
formatCost(val) {
return new Intl.NumberFormat(navigator.language, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(val);
},
formatDate(isoString) {
const d = new Date(isoString);
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const dateOnly = new Date(d.getFullYear(), d.getMonth(), d.getDate());
// Wenn das Datum heute ist oder in der Zukunft liegt, zeige auch die Uhrzeit
if (dateOnly.getTime() >= today.getTime()) {
return d.toLocaleString(navigator.language, {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
// Ansonsten nur das Datum
return d.toLocaleDateString();
}
}
};
</script>
<style scoped lang="scss">
h2 { padding-top: 20px; }
.nobility-section,
.advance-section {
border: 1px solid #ccc;
border-radius: 4px;
margin: 10px 0;
padding: 10px;
}
.prerequisites {
list-style: disc inside;
margin-bottom: 1rem;
}
.cooldown-message {
color: #666;
font-style: italic;
margin-top: 1rem;
}
</style>