Implemented houses

This commit is contained in:
Torsten Schulz
2025-05-08 17:38:51 +02:00
parent b15d93a798
commit a9e6c82275
17 changed files with 1129 additions and 156 deletions

View File

@@ -0,0 +1,259 @@
<template>
<div class="houseView">
<StatusBar />
<h2>{{ $t('falukant.house.title') }}</h2>
<div class="existingHouse">
<div :style="houseStyle(picturePosition)" class="house"></div>
<div class="statusreport">
<h3>{{ $t('falukant.house.statusreport') }}</h3>
<table>
<thead>
<tr>
<th>{{ $t('falukant.house.element') }}</th>
<th>{{ $t('falukant.house.state') }}</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="status, index in status">
<td>{{ $t(`falukant.house.status.${index}`) }}</td>
<td>{{ status }} %</td>
<td><button v-if="status < 100">{{ $t('falukant.house.renovate') }} ({{
$t('falukant.house.cost') }}: {{ getRenovationCost(index, status) }}</button></td>
</tr>
<tr>
<td>{{ $t('falukant.house.worth') }}</td>
<td>{{ getWorth(status) }}</td>
<td><button @click="sellHouse">{{ $t('falukant.house.sell') }}</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="buyablehouses">
<h3>{{ $t('falukant.house.buyablehouses') }}</h3>
<div style="overflow:auto">
<div style="display: flex; flex-direction: row" v-for="house in buyableHouses">
<div style="width:100px; height:100px; display: hidden;">
<div :style="houseStyle(house.houseType.position)" class="housePreview buyableHouseInfo"></div>
</div>
<div class="buyableHouseInfo">
<h4 style="display: inline;">{{ $t('falukant.house.statusreport') }}</h4>
<table>
<tbody>
<template v-for="value, key in house">
<tr v-if="key != 'houseType' && key != 'id'">
<td>{{ $t(`falukant.house.status.${key}`) }}</td>
<td>{{ value }} %</td>
</tr>
</template>
</tbody>
</table>
</div>
<div>
{{ $t('falukant.house.price') }}: {{ buyCost(house) }}
</div>
<div>
<button @click="buyHouse(house.id)">{{ $t('falukant.house.buy') }}</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import StatusBar from '@/components/falukant/StatusBar.vue';
import apiClient from '@/utils/axios.js';
import { mapState } from "vuex";
export default {
name: 'HouseView',
components: {
StatusBar
},
data() {
return {
houseTypes: [],
userHouse: {},
houseType: {},
status: {},
buyableHouses: [],
picturePosition: 0,
}
},
methods: {
async loadHouseTypes() {
try {
const houseTypesResult = await apiClient.get('/api/falukant/houses/types');
this.houseTypes = houseTypesResult.data;
} catch (error) {
}
},
async loadUserHouse() {
try {
const userHouseResult = await apiClient.get('/api/falukant/houses');
Object.assign(this.userHouse, userHouseResult.data);
const { houseType, ...houseStatus } = this.userHouse;
this.status = houseStatus;
this.picturePosition = parseInt(houseType.position);
this.houseType = houseType;
} catch (error) {
console.error('Fehler beim Laden des Hauses:', error);
this.userHouse = null;
this.status = null;
}
},
async loadBuyableHouses() {
try {
const buyableHousesResult = await apiClient.get('/api/falukant/houses/buyable');
this.buyableHouses = buyableHousesResult.data;
} catch (error) {
console.error('Fehler beim Laden der kaufbaren Häuser:', error);
}
},
houseStyle(housePosition) {
const columns = 3;
const spriteSize = 341; // Breite & Höhe eines einzelnen Hauses
let calculatePosition = Math.max(housePosition - 1, 0);
const x = (calculatePosition % columns) * spriteSize;
const y = Math.floor(calculatePosition / columns) * spriteSize;
return {
backgroundImage: 'url("/images/falukant/houses.png")',
backgroundPosition: `-${x}px -${y}px`,
backgroundSize: `${columns * spriteSize}px auto`, // z.B. 1023px auto
};
},
buyCost(house) {
const houseQuality = (house.roofCondition + house.windowCondition + house.floorCondition + house.wallCondition) / 4;
return (house.houseType.cost / 100 * houseQuality).toFixed(2);
},
getWorth() {
const house = {...this.userHouse, houseType: this.houseType};
const buyWorth = this.buyCost(house);
return (buyWorth * 0.8).toFixed(2);
},
async buyHouse(houseId) {
try {
const response = await apiClient.post('/api/falukant/houses',
{
houseId: houseId,
}
);
this.$router.push({ name: 'HouseView' });
} catch (error) {
console.error('Fehler beim Kaufen des Hauses:', error);
}
},
async getHouseData() {
await this.loadUserHouse();
await this.loadBuyableHouses();
}
},
computed: {
...mapState(['socket', 'daemonSocket']),
getHouseStyle() {
if (!this.userHouse || this.userHouse.position === undefined || this.userHouse.position === null) {
return {};
}
return this.houseStyle(this.userHouse.position);
},
getHouseType(position) {
const houseType = this.houseTypes[position];
return houseType;
},
getHouseStatus(position) {
const houseStatus = this.houseStatuses[position];
return houseStatus;
},
getRenovationCost(index, status) {
const houseType = this.houseTypes[position];
const renovationCost = houseType.renovationCosts[status];
return renovationCost;
},
},
created() {
},
async mounted() {
this.loadHouseTypes();
await this.getHouseData();
if (this.socket) {
this.socket.on("falukantHouseUpdate", this.getHouseData);
}
if (this.daemonSocket) {
this.daemonSocket.addEventListener("message", this.handleDaemonSocketMessage);
}
},
beforeUnmount() {
if (this.socket) {
this.socket.off("falukantHouseUpdate", this.fetchStatus);
}
if (this.daemonSocket) {
this.daemonSocket.removeEventListener("message", this.handleDaemonSocketMessage);
}
},
watch: {
}
}
</script>
<style lang="scss" scoped>
h2 {
padding-top: 20px;
}
.existingHouse {
display: block;
width: auto;
height: 255px;
}
Element {
background-position: 71px 54px;
}
.house {
border: 1px solid #ccc;
border-radius: 4px;
background-repeat: no-repeat;
image-rendering: crisp-edges;
transform: scale(0.7);
transform-origin: top left;
display: inline-block;
overflow: hidden;
width: 341px;
height: 341px;
}
.statusreport {
display: inline-block;
vertical-align: top;
height: 250px;
}
.buyableHouseInfo {
vertical-align: top;
}
.housePreview {
transform: scale(0.2);
width: 341px;
height: 341px;
transform-origin: top left;
}
.houseView {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
.buyablehouses {
display: flex;
flex-direction: column;
overflow: hidden;
}
</style>