Add NPC creation and titles retrieval functionality in Admin module
- Implemented createNPCs method in AdminController to handle NPC creation with specified parameters including region, age, title, and count. - Added getTitlesOfNobility method in AdminController to retrieve available titles for users. - Updated adminRouter to include new routes for creating NPCs and fetching titles. - Enhanced navigationController and frontend localization files to support new NPC creation feature. - Introduced corresponding UI components and routes for NPC management in the admin interface.
This commit is contained in:
@@ -113,6 +113,27 @@
|
||||
"errorSaveConnection": "Die Verbindung konnte nicht gespeichert werden.",
|
||||
"errorDeleteConnection": "Die Verbindung konnte nicht gelöscht werden.",
|
||||
"confirmDeleteConnection": "Verbindung wirklich löschen?"
|
||||
},
|
||||
"createNPC": {
|
||||
"title": "NPCs erstellen",
|
||||
"region": "Stadt",
|
||||
"allRegions": "Alle Städte",
|
||||
"ageRange": "Altersbereich",
|
||||
"to": "bis",
|
||||
"years": "Jahre",
|
||||
"titleRange": "Titel-Bereich",
|
||||
"count": "Anzahl",
|
||||
"create": "NPCs erstellen",
|
||||
"creating": "Erstelle...",
|
||||
"result": "Ergebnis",
|
||||
"createdCount": "{count} NPCs wurden erstellt.",
|
||||
"age": "Alter",
|
||||
"errorLoadingRegions": "Fehler beim Laden der Städte.",
|
||||
"errorLoadingTitles": "Fehler beim Laden der Titel.",
|
||||
"errorCreating": "Fehler beim Erstellen der NPCs.",
|
||||
"invalidAgeRange": "Ungültiger Altersbereich.",
|
||||
"invalidTitleRange": "Ungültiger Titel-Bereich.",
|
||||
"invalidCount": "Ungültige Anzahl (1-100)."
|
||||
}
|
||||
},
|
||||
"chatrooms": {
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
"logentries": "Log-Einträge",
|
||||
"edituser": "Benutzer bearbeiten",
|
||||
"database": "Datenbank",
|
||||
"mapEditor": "Karteneditor"
|
||||
"mapEditor": "Karteneditor",
|
||||
"createNPC": "NPCs erstellen"
|
||||
},
|
||||
"minigames": "Minispiele",
|
||||
"m-minigames": {
|
||||
|
||||
@@ -140,6 +140,27 @@
|
||||
"errorAddingStock": "Error adding warehouse.",
|
||||
"stockAdded": "Warehouse successfully added.",
|
||||
"invalidStockData": "Please enter valid warehouse type and quantity."
|
||||
},
|
||||
"createNPC": {
|
||||
"title": "Create NPCs",
|
||||
"region": "City",
|
||||
"allRegions": "All Cities",
|
||||
"ageRange": "Age Range",
|
||||
"to": "to",
|
||||
"years": "years",
|
||||
"titleRange": "Title Range",
|
||||
"count": "Count",
|
||||
"create": "Create NPCs",
|
||||
"creating": "Creating...",
|
||||
"result": "Result",
|
||||
"createdCount": "{count} NPCs have been created.",
|
||||
"age": "Age",
|
||||
"errorLoadingRegions": "Error loading cities.",
|
||||
"errorLoadingTitles": "Error loading titles.",
|
||||
"errorCreating": "Error creating NPCs.",
|
||||
"invalidAgeRange": "Invalid age range.",
|
||||
"invalidTitleRange": "Invalid title range.",
|
||||
"invalidCount": "Invalid count (1-100)."
|
||||
}
|
||||
},
|
||||
"chatrooms": {
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
"logentries": "Log entries",
|
||||
"edituser": "Edit user",
|
||||
"database": "Database",
|
||||
"mapEditor": "Map editor"
|
||||
"mapEditor": "Map editor",
|
||||
"createNPC": "Create NPCs"
|
||||
},
|
||||
"minigames": "Mini games",
|
||||
"m-minigames": {
|
||||
|
||||
@@ -5,6 +5,7 @@ import UserRightsView from '../views/admin/UserRightsView.vue';
|
||||
import ForumAdminView from '../dialogues/admin/ForumAdminView.vue';
|
||||
import AdminFalukantEditUserView from '../views/admin/falukant/EditUserView.vue';
|
||||
import AdminFalukantMapRegionsView from '../views/admin/falukant/MapRegionsView.vue';
|
||||
import AdminFalukantCreateNPCView from '../views/admin/falukant/CreateNPCView.vue';
|
||||
import AdminMinigamesView from '../views/admin/MinigamesView.vue';
|
||||
import AdminTaxiToolsView from '../views/admin/TaxiToolsView.vue';
|
||||
import AdminUsersView from '../views/admin/UsersView.vue';
|
||||
@@ -66,6 +67,12 @@ const adminRoutes = [
|
||||
component: AdminFalukantMapRegionsView,
|
||||
meta: { requiresAuth: true }
|
||||
},
|
||||
{
|
||||
path: '/admin/falukant/create-npc',
|
||||
name: 'AdminFalukantCreateNPCView',
|
||||
component: AdminFalukantCreateNPCView,
|
||||
meta: { requiresAuth: true }
|
||||
},
|
||||
{
|
||||
path: '/admin/minigames/match3',
|
||||
name: 'AdminMinigames',
|
||||
|
||||
289
frontend/src/views/admin/falukant/CreateNPCView.vue
Normal file
289
frontend/src/views/admin/falukant/CreateNPCView.vue
Normal file
@@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<div class="create-npc-view">
|
||||
<h1>{{ $t('admin.falukant.createNPC.title') }}</h1>
|
||||
|
||||
<div class="form-section">
|
||||
<div class="form-group">
|
||||
<label>{{ $t('admin.falukant.createNPC.region') }}:</label>
|
||||
<div class="region-selection">
|
||||
<label>
|
||||
<input type="checkbox" v-model="allRegions" @change="onAllRegionsChange" />
|
||||
{{ $t('admin.falukant.createNPC.allRegions') }}
|
||||
</label>
|
||||
<select v-model="selectedRegionIds" multiple :disabled="allRegions" class="form-select" size="10">
|
||||
<option v-for="region in regions" :key="region.id" :value="region.id">
|
||||
{{ region.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('admin.falukant.createNPC.ageRange') }}:</label>
|
||||
<div class="age-range">
|
||||
<input type="number" v-model.number="minAge" min="0" max="100" class="form-input" />
|
||||
<span>{{ $t('admin.falukant.createNPC.to') }}</span>
|
||||
<input type="number" v-model.number="maxAge" min="0" max="100" class="form-input" />
|
||||
<span>{{ $t('admin.falukant.createNPC.years') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('admin.falukant.createNPC.titleRange') }}:</label>
|
||||
<div class="title-range">
|
||||
<select v-model.number="minTitleId" class="form-select">
|
||||
<option v-for="title in titles" :key="title.id" :value="title.id">
|
||||
{{ $t(`falukant.titles.male.${title.labelTr}`) }} (ID: {{ title.id }})
|
||||
</option>
|
||||
</select>
|
||||
<span>{{ $t('admin.falukant.createNPC.to') }}</span>
|
||||
<select v-model.number="maxTitleId" class="form-select">
|
||||
<option v-for="title in titles" :key="title.id" :value="title.id">
|
||||
{{ $t(`falukant.titles.male.${title.labelTr}`) }} (ID: {{ title.id }})
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('admin.falukant.createNPC.count') }}:</label>
|
||||
<input type="number" v-model.number="count" min="1" max="100" class="form-input" />
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button @click="createNPCs" :disabled="creating" class="btn btn-primary">
|
||||
{{ creating ? $t('admin.falukant.createNPC.creating') : $t('admin.falukant.createNPC.create') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ergebnis-Anzeige -->
|
||||
<div v-if="result" class="result-section">
|
||||
<h2>{{ $t('admin.falukant.createNPC.result') }}</h2>
|
||||
<p>{{ $t('admin.falukant.createNPC.createdCount', { count: result.count }) }}</p>
|
||||
<div v-if="result.npcs && result.npcs.length > 0" class="npcs-list">
|
||||
<div v-for="npc in result.npcs" :key="npc.id" class="npc-item">
|
||||
{{ $t(`falukant.titles.${npc.gender}.${npc.title}`) }} {{ npc.firstName }} {{ npc.lastName }}
|
||||
({{ $t('admin.falukant.createNPC.age') }}: {{ npc.age }}, {{ $t('admin.falukant.createNPC.region') }}: {{ npc.region }})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="error" class="error-message">
|
||||
{{ error }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import apiClient from '@/utils/axios.js';
|
||||
|
||||
export default {
|
||||
name: 'AdminFalukantCreateNPCView',
|
||||
data() {
|
||||
return {
|
||||
regions: [],
|
||||
titles: [],
|
||||
selectedRegionIds: [],
|
||||
allRegions: true,
|
||||
minAge: 0,
|
||||
maxAge: 100,
|
||||
minTitleId: 1,
|
||||
maxTitleId: 19,
|
||||
count: 1,
|
||||
creating: false,
|
||||
result: null,
|
||||
error: null
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
await this.loadRegions();
|
||||
await this.loadTitles();
|
||||
},
|
||||
methods: {
|
||||
async loadRegions() {
|
||||
try {
|
||||
const response = await apiClient.get('/api/admin/falukant/regions');
|
||||
this.regions = response.data || [];
|
||||
} catch (error) {
|
||||
console.error('Error loading regions:', error);
|
||||
this.error = this.$t('admin.falukant.createNPC.errorLoadingRegions');
|
||||
}
|
||||
},
|
||||
async loadTitles() {
|
||||
try {
|
||||
const response = await apiClient.get('/api/admin/falukant/titles');
|
||||
this.titles = response.data || [];
|
||||
if (this.titles.length > 0) {
|
||||
this.minTitleId = this.titles[0].id;
|
||||
this.maxTitleId = this.titles[this.titles.length - 1].id;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading titles:', error);
|
||||
this.error = this.$t('admin.falukant.createNPC.errorLoadingTitles');
|
||||
}
|
||||
},
|
||||
onAllRegionsChange() {
|
||||
if (this.allRegions) {
|
||||
this.selectedRegionIds = [];
|
||||
}
|
||||
},
|
||||
async createNPCs() {
|
||||
if (this.creating) return;
|
||||
|
||||
// Validierung
|
||||
if (this.minAge < 0 || this.maxAge < 0 || this.minAge > this.maxAge) {
|
||||
this.error = this.$t('admin.falukant.createNPC.invalidAgeRange');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.minTitleId > this.maxTitleId) {
|
||||
this.error = this.$t('admin.falukant.createNPC.invalidTitleRange');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.count < 1 || this.count > 100) {
|
||||
this.error = this.$t('admin.falukant.createNPC.invalidCount');
|
||||
return;
|
||||
}
|
||||
|
||||
this.creating = true;
|
||||
this.error = null;
|
||||
this.result = null;
|
||||
|
||||
try {
|
||||
const response = await apiClient.post('/api/admin/falukant/npcs/create', {
|
||||
regionIds: this.allRegions ? null : this.selectedRegionIds,
|
||||
minAge: this.minAge,
|
||||
maxAge: this.maxAge,
|
||||
minTitleId: this.minTitleId,
|
||||
maxTitleId: this.maxTitleId,
|
||||
count: this.count
|
||||
});
|
||||
|
||||
this.result = response.data;
|
||||
} catch (error) {
|
||||
console.error('Error creating NPCs:', error);
|
||||
this.error = error.response?.data?.error || this.$t('admin.falukant.createNPC.errorCreating');
|
||||
} finally {
|
||||
this.creating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.create-npc-view {
|
||||
padding: 20px;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
background: #f5f5f5;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.region-selection {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.region-selection label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.form-select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.form-select[multiple] {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.age-range,
|
||||
.title-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
padding: 8px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background-color: #218838;
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
background-color: #6c757d;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.result-section {
|
||||
background: #d4edda;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.npcs-list {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.npc-item {
|
||||
padding: 8px;
|
||||
background: white;
|
||||
margin-bottom: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background: #f8d7da;
|
||||
color: #721c24;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user