Start implementation of branches, new form element tabledropdown, model improvements
This commit is contained in:
130
frontend/src/views/falukant/BranchView.vue
Normal file
130
frontend/src/views/falukant/BranchView.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div>
|
||||
<StatusBar />
|
||||
<h2>{{ $t('falukant.branch.title') }}</h2>
|
||||
|
||||
<!-- Branch Selection Section -->
|
||||
<div class="branch-selection">
|
||||
<h3>{{ $t('falukant.branch.selection.title') }}</h3>
|
||||
<div>
|
||||
<FormattedDropdown :options="branches" :columns="branchColumns" v-model="selectedBranch"
|
||||
:placeholder="$t('falukant.branch.selection.placeholder')" />
|
||||
</div>
|
||||
<div>
|
||||
<button @click="createBranch">{{ $t('falukant.branch.actions.create') }}</button>
|
||||
<button @click="upgradeBranch" :disabled="!selectedBranch">
|
||||
{{ $t('falukant.branch.actions.upgrade') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Director Info Section -->
|
||||
<div class="director-info">
|
||||
<h3>{{ $t('falukant.branch.director.title') }}</h3>
|
||||
<p v-if="selectedBranch">
|
||||
{{ $t('falukant.branch.director.info', { branchName: selectedBranch.cityName }) }}
|
||||
</p>
|
||||
<p v-else>{{ $t('falukant.branch.director.noSelection') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Sale Section -->
|
||||
<div class="sale-section">
|
||||
<h3>{{ $t('falukant.branch.sale.title') }}</h3>
|
||||
<p>{{ $t('falukant.branch.sale.info') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Production Section -->
|
||||
<div class="production-section">
|
||||
<h3>{{ $t('falukant.branch.production.title') }}</h3>
|
||||
<p>{{ $t('falukant.branch.production.info') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StatusBar from '@/components/falukant/StatusBar.vue';
|
||||
import FormattedDropdown from '@/components/form/FormattedDropdown.vue';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
|
||||
export default {
|
||||
name: "BranchView",
|
||||
components: {
|
||||
StatusBar,
|
||||
FormattedDropdown,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedBranch: null,
|
||||
branches: [],
|
||||
branchColumns: [
|
||||
{ field: "cityName", label: this.$t('falukant.branch.columns.city') },
|
||||
{ field: "type", label: this.$t('falukant.branch.columns.type') },
|
||||
],
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
await this.loadBranches();
|
||||
const branchId = this.$route.params.branchId;
|
||||
console.log('route params:', this.$route.params, branchId);
|
||||
if (branchId) {
|
||||
console.log('branch selected');
|
||||
this.selectedBranch = this.branches.find(branch => branch.id === parseInt(branchId)) || null;
|
||||
} else {
|
||||
console.log('main branch selected');
|
||||
this.selectMainBranch();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async loadBranches() {
|
||||
try {
|
||||
const branchesResult = await apiClient.get('/api/falukant/branches');
|
||||
this.branches = branchesResult.data.map((branch) => ({
|
||||
id: branch.id,
|
||||
cityName: branch.region.name,
|
||||
type: this.$t(`falukant.branch.types.${branch.branchType.labelTr}`),
|
||||
isMainBranch: branch.isMainBranch,
|
||||
}));
|
||||
// Wenn keine selectedBranch gesetzt ist, versuche die Main Branch zu wählen
|
||||
if (!this.selectedBranch) {
|
||||
this.selectMainBranch();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading branches:', error);
|
||||
}
|
||||
},
|
||||
selectMainBranch() {
|
||||
const main = this.branches.find(b => b.isMainBranch) || null;
|
||||
if (main !== this.selectedBranch) {
|
||||
this.selectedBranch = main;
|
||||
console.log("Main branch selected:", this.selectedBranch);
|
||||
}
|
||||
},
|
||||
createBranch() {
|
||||
alert(this.$t('falukant.branch.actions.createAlert'));
|
||||
},
|
||||
upgradeBranch() {
|
||||
if (this.selectedBranch) {
|
||||
alert(
|
||||
this.$t('falukant.branch.actions.upgradeAlert', { branchId: this.selectedBranch.id })
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.branch-selection,
|
||||
.director-info,
|
||||
.sale-section,
|
||||
.production-section {
|
||||
border: 1px solid #ccc;
|
||||
margin: 10px 0;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 5px;
|
||||
}
|
||||
</style>
|
||||
118
frontend/src/views/falukant/CreateView.vue
Normal file
118
frontend/src/views/falukant/CreateView.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>{{ $t('falukant.create.title') }}</h2>
|
||||
<form @submit.prevent="createFalukant">
|
||||
<label>{{ $t('falukant.create.gender') }}</label>
|
||||
<select v-model="falukant.gender" required @change="randomFirstName">
|
||||
<option value="male">{{ $t('falukant.create.male') }}</option>
|
||||
<option value="female">{{ $t('falukant.create.female') }}</option>
|
||||
</select>
|
||||
<div></div>
|
||||
<label>{{ $t('falukant.create.firstname') }}</label>
|
||||
<input type="text" v-model="falukant.firstname" required>
|
||||
<button @click="randomFirstName" type="button">{{ $t('falukant.create.random') }}</button>
|
||||
<label>{{ $t('falukant.create.lastname') }}</label>
|
||||
<input type="text" v-model="falukant.lastname" required>
|
||||
<button @click="randomLastName" type="button">{{ $t('falukant.create.random') }}</button>
|
||||
<button type="submit">{{ $t('falukant.create.submit') }}</button>
|
||||
</form>
|
||||
<img :src="falukant.gender == 'male' ? '/images/mascot/mascot_male.png' : '/images/mascot/mascot_female.png'"
|
||||
class="mascot-image" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
|
||||
export default {
|
||||
name: 'FalukantCreateView',
|
||||
data() {
|
||||
return {
|
||||
falukant: {
|
||||
gender: 'male',
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
try {
|
||||
const falukantUser = await apiClient.get('/api/falukant/user');
|
||||
if (falukantUser.data) {
|
||||
this.$router.push({ name: 'FalukantOverview' });
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
}
|
||||
await this.randomFirstName();
|
||||
await this.randomLastName();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['createFalukant']),
|
||||
async createFalukant() {
|
||||
const newUser = await apiClient.post('/api/falukant/user', this.falukant);
|
||||
console.log(newUser);
|
||||
this.$router.push({ name: 'FalukantOverview' });
|
||||
},
|
||||
async randomFirstName() {
|
||||
const randomNameResult = await apiClient.get('/api/falukant/name/randomfirstname/' + this.falukant.gender);
|
||||
this.falukant.firstname = randomNameResult.data.name;
|
||||
console.log(this.falukant, randomNameResult);
|
||||
},
|
||||
async randomLastName() {
|
||||
const randomNameResult = await apiClient.get('/api/falukant/name/randomlastname');
|
||||
this.falukant.lastname = randomNameResult.data.name;
|
||||
console.log(this.falukant, randomNameResult);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
form {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
row-gap: 15px;
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
border: 1px solid #ccc;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
label {
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
select,
|
||||
input {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
button {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
button[type="submit"] {
|
||||
grid-column: 1 / -1;
|
||||
justify-self: start;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.mascot-image {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
height: calc(100vh - 400px);
|
||||
max-height: 100%;
|
||||
min-height: 150px;
|
||||
width: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
</style>
|
||||
187
frontend/src/views/falukant/OverviewView.vue
Normal file
187
frontend/src/views/falukant/OverviewView.vue
Normal file
@@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<div>
|
||||
<StatusBar />
|
||||
<h2>{{ $t('falukant.overview.title') }}</h2>
|
||||
<div class="overviewcontainer">
|
||||
<div>
|
||||
<h3>{{ $t('falukant.overview.metadata.title') }}</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ $t('falukant.overview.metadata.name') }}</td>
|
||||
<td>{{ falukantUser?.character.definedFirstName.name }} {{
|
||||
falukantUser?.character.definedLastName.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('falukant.overview.metadata.money') }}</td>
|
||||
<td>{{ falukantUser?.money }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('falukant.overview.metadata.age') }}</td>
|
||||
<td>{{ falukantUser?.character.age }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('falukant.overview.metadata.mainbranch') }}</td>
|
||||
<td>{{ falukantUser?.mainBranchRegion.name }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<h3>{{ $t('falukant.overview.productions.title') }}</h3>
|
||||
</div>
|
||||
<div>
|
||||
<h3>{{ $t('falukant.overview.stock.title') }}</h3>
|
||||
</div>
|
||||
<div>
|
||||
<h3>{{ $t('falukant.overview.branches.title') }}</h3>
|
||||
<table>
|
||||
<tr v-for="branch in falukantUser?.branches">
|
||||
<td><span @click="openBranch(branch.id)" class="link">{{ branch.region.name }}</span></td>
|
||||
<td>{{ $t(`falukant.overview.branches.level.${branch.branchType.labelTr}`) }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="imagecontainer">
|
||||
<div :style="getAvatarStyle" class="avatar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import StatusBar from '@/components/falukant/StatusBar.vue';
|
||||
|
||||
const AVATAR_POSITIONS = {
|
||||
male: {
|
||||
width: 195,
|
||||
height: 300,
|
||||
positions: {
|
||||
"0-1": { x: 161, y: 28 },
|
||||
"2-3": { x: 802, y: 28 },
|
||||
"4-6": { x: 1014, y: 28 },
|
||||
"7-10": { x: 800, y: 368 },
|
||||
"11-13": { x: 373, y: 368 },
|
||||
"14-16": { x: 1441, y: 28 },
|
||||
"17-20": { x: 1441, y: 368 },
|
||||
"21-30": { x: 1014, y: 368 },
|
||||
"31-45": { x: 1227, y: 368 },
|
||||
"45-55": { x: 803, y: 687 },
|
||||
"55+": { x: 1441, y: 687 },
|
||||
},
|
||||
},
|
||||
female: {
|
||||
width: 223,
|
||||
height: 298,
|
||||
positions: {
|
||||
"0-1": { x: 302, y: 66 },
|
||||
"2-3": { x: 792, y: 66 },
|
||||
"4-6": { x: 62, y: 66 },
|
||||
"7-10": { x: 1034, y: 66 },
|
||||
"11-13": { x: 1278, y: 66 },
|
||||
"14-16": { x: 303, y: 392 },
|
||||
"17-20": { x: 1525, y: 392 },
|
||||
"21-30": { x: 1278, y: 392 },
|
||||
"31-45": { x: 547, y: 718 },
|
||||
"45-55": { x: 1034, y: 718 },
|
||||
"55+": { x: 1525, y: 718 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'FalukantOverviewView',
|
||||
data() {
|
||||
return {
|
||||
falukantUser: null,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
StatusBar,
|
||||
},
|
||||
async mounted() {
|
||||
await this.fetchFalukantUser();
|
||||
if (this.socket) {
|
||||
this.socket.on("falukantUserUpdated", this.fetchFalukantUser);
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (this.socket) {
|
||||
this.socket.off("falukantUserUpdated", this.fetchFalukantUser);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getAvatarStyle() {
|
||||
if (!this.falukantUser) return {};
|
||||
const { gender, age } = this.falukantUser.character;
|
||||
const imageUrl = `/images/falukant/avatar/${gender}.png`;
|
||||
const ageGroup = this.getAgeGroup(age);
|
||||
const genderData = AVATAR_POSITIONS[gender] || {};
|
||||
const position = genderData.positions?.[ageGroup] || { x: 0, y: 0 };
|
||||
const width = genderData.width || 100;
|
||||
const height = genderData.height || 100;
|
||||
return {
|
||||
backgroundImage: `url(${imageUrl})`,
|
||||
backgroundPosition: `-${position.x}px -${position.y}px`,
|
||||
backgroundSize: "1792px 1024px",
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getAgeGroup(age) {
|
||||
if (age <= 1) return "0-1";
|
||||
if (age <= 3) return "2-3";
|
||||
if (age <= 6) return "4-6";
|
||||
if (age <= 10) return "7-10";
|
||||
if (age <= 13) return "11-13";
|
||||
if (age <= 16) return "14-16";
|
||||
if (age <= 20) return "17-20";
|
||||
if (age <= 30) return "21-30";
|
||||
if (age <= 45) return "31-45";
|
||||
if (age <= 55) return "45-55";
|
||||
return "55+";
|
||||
},
|
||||
async fetchFalukantUser() {
|
||||
const falukantUser = await apiClient.get('/api/falukant/user');
|
||||
if (!falukantUser.data) {
|
||||
this.$router.push({ name: 'FalukantCreate' });
|
||||
return;
|
||||
}
|
||||
this.falukantUser = falukantUser.data;
|
||||
},
|
||||
openBranch(branchId) {
|
||||
this.$router.push({ name: 'BranchView', params: { branchId: branchId } });
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.overviewcontainer {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-gap: 5px;
|
||||
}
|
||||
|
||||
.overviewcontainer>div {
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.imagecontainer {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user