We can add weapons and equipment
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"bamort/character"
|
||||
"bamort/config"
|
||||
"bamort/database"
|
||||
"bamort/equipment"
|
||||
"bamort/gsmaster"
|
||||
"bamort/importer"
|
||||
"bamort/logger"
|
||||
@@ -73,6 +74,7 @@ func main() {
|
||||
// Register your module routes
|
||||
gsmaster.RegisterRoutes(protected)
|
||||
character.RegisterRoutes(protected)
|
||||
equipment.RegisterRoutes(protected)
|
||||
maintenance.RegisterRoutes(protected)
|
||||
importer.RegisterRoutes(protected)
|
||||
pdfrender.RegisterRoutes(protected)
|
||||
|
||||
@@ -77,3 +77,66 @@ func DeleteAusruestung(c *gin.Context) {
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Ausruestung deleted successfully"})
|
||||
}
|
||||
|
||||
/*
|
||||
Endpoints for Managing Weapons (Waffen)
|
||||
*/
|
||||
|
||||
func CreateWaffe(c *gin.Context) {
|
||||
var waffe models.EqWaffe
|
||||
if err := c.ShouldBindJSON(&waffe); err != nil {
|
||||
respondWithError(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&waffe).Error; err != nil {
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to create Waffe")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, waffe)
|
||||
}
|
||||
|
||||
func ListWaffen(c *gin.Context) {
|
||||
characterID := c.Param("character_id")
|
||||
|
||||
var waffen []models.EqWaffe
|
||||
if err := database.DB.Where("character_id = ?", characterID).Find(&waffen).Error; err != nil {
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to retrieve Waffen")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, waffen)
|
||||
}
|
||||
|
||||
func UpdateWaffe(c *gin.Context) {
|
||||
waffeID := c.Param("waffe_id")
|
||||
var waffe models.EqWaffe
|
||||
|
||||
if err := database.DB.First(&waffe, waffeID).Error; err != nil {
|
||||
respondWithError(c, http.StatusNotFound, "Waffe not found")
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&waffe); err != nil {
|
||||
respondWithError(c, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.DB.Save(&waffe).Error; err != nil {
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to update Waffe")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, waffe)
|
||||
}
|
||||
|
||||
func DeleteWaffe(c *gin.Context) {
|
||||
waffeID := c.Param("waffe_id")
|
||||
if err := database.DB.Delete(&models.EqWaffe{}, waffeID).Error; err != nil {
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to delete Waffe")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Waffe deleted successfully"})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package equipment
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RegisterRoutes(r *gin.RouterGroup) {
|
||||
// Equipment (Ausrüstung) routes
|
||||
equipGrp := r.Group("/equipment")
|
||||
equipGrp.POST("", CreateAusruestung)
|
||||
equipGrp.GET("/character/:character_id", ListAusruestung)
|
||||
equipGrp.PUT("/:ausruestung_id", UpdateAusruestung)
|
||||
equipGrp.DELETE("/:ausruestung_id", DeleteAusruestung)
|
||||
|
||||
// Weapon (Waffen) routes
|
||||
weaponGrp := r.Group("/weapons")
|
||||
weaponGrp.POST("", CreateWaffe)
|
||||
weaponGrp.GET("/character/:character_id", ListWaffen)
|
||||
weaponGrp.PUT("/:waffe_id", UpdateWaffe)
|
||||
weaponGrp.DELETE("/:waffe_id", DeleteWaffe)
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<div class="fullwidth-container">
|
||||
<div class="header-section">
|
||||
<h2>{{ $t('EquipmentView') }}</h2>
|
||||
<button @click="openAddEquipmentDialog" class="btn-add-equipment">
|
||||
{{ $t('equipment.add') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="cd-list">
|
||||
<table class="cd-table">
|
||||
<thead>
|
||||
@@ -11,11 +18,12 @@
|
||||
<th>{{ $t('equipment.amount') }}</th>
|
||||
<th>{{ $t('equipment.contained_in') }}</th>
|
||||
<th>{{ $t('equipment.bonus') }}</th>
|
||||
<th>{{ $t('equipment.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="equipment in character.ausruestung">
|
||||
<tr>
|
||||
<template v-if="character.ausruestung && character.ausruestung.length > 0">
|
||||
<tr v-for="equipment in character.ausruestung" :key="equipment.id">
|
||||
<td>{{ equipment.name || '-' }}</td>
|
||||
<td>{{ equipment.beschreibung || '-' }}</td>
|
||||
<td>{{ equipment.gewicht || '-' }}</td>
|
||||
@@ -23,20 +31,366 @@
|
||||
<td>{{ equipment.anzahl || '-' }}</td>
|
||||
<td>{{ equipment.beinhaltet_in || '-' }}</td>
|
||||
<td>{{ equipment.bonus || '-' }}</td>
|
||||
<td class="action-cell">
|
||||
<button @click="deleteEquipment(equipment)" class="btn-delete" title="Löschen">
|
||||
🗑️
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template v-else>
|
||||
<tr>
|
||||
<td colspan="8" class="empty-state">{{ $t('equipment.noEquipment') }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div> <!--- end cd-list-->
|
||||
</div> <!--- end character -datasheet-->
|
||||
</div>
|
||||
|
||||
<!-- Dialog für Ausrüstung hinzufügen -->
|
||||
<div v-if="showAddDialog" class="modal-overlay" @click.self="closeDialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>{{ $t('equipment.addEquipment') }}</h3>
|
||||
<button @click="closeDialog" class="close-button">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>{{ $t('equipment.search') }}:</label>
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="$t('equipment.searchPlaceholder')"
|
||||
@input="filterEquipment"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="isLoading" class="loading">{{ $t('equipment.loading') }}</div>
|
||||
|
||||
<div v-else-if="filteredMasterEquipment.length > 0" class="equipment-list">
|
||||
<div
|
||||
v-for="equipment in filteredMasterEquipment"
|
||||
:key="equipment.id"
|
||||
class="equipment-item"
|
||||
:class="{ selected: selectedEquipment && selectedEquipment.id === equipment.id }"
|
||||
@click="selectEquipment(equipment)"
|
||||
>
|
||||
<div class="equipment-name">{{ equipment.name }}</div>
|
||||
<div class="equipment-details">
|
||||
{{ equipment.beschreibung || '-' }} |
|
||||
{{ equipment.weight }}kg |
|
||||
{{ equipment.value || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="no-results">
|
||||
{{ searchQuery ? $t('equipment.noResults') : $t('equipment.noMasterData') }}
|
||||
</div>
|
||||
|
||||
<div v-if="selectedEquipment" class="selected-equipment-details">
|
||||
<h4>{{ $t('equipment.selectedEquipment') }}</h4>
|
||||
<p><strong>{{ $t('equipment.name') }}:</strong> {{ selectedEquipment.name }}</p>
|
||||
<p><strong>{{ $t('equipment.description') }}:</strong> {{ selectedEquipment.beschreibung || '-' }}</p>
|
||||
<p><strong>{{ $t('equipment.weight') }}:</strong> {{ selectedEquipment.weight }}kg</p>
|
||||
<p><strong>{{ $t('equipment.value') }}:</strong> {{ selectedEquipment.value || '-' }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('equipment.amount') }}:</label>
|
||||
<input v-model.number="equipmentAmount" type="number" min="1" value="1" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button @click="closeDialog" class="btn-cancel">{{ $t('equipment.cancel') }}</button>
|
||||
<button
|
||||
@click="addEquipment"
|
||||
class="btn-confirm"
|
||||
:disabled="!selectedEquipment || isSubmitting"
|
||||
>
|
||||
{{ isSubmitting ? $t('equipment.adding') : $t('equipment.add') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
.fullwidth-container {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.btn-add-equipment {
|
||||
padding: 8px 16px;
|
||||
background: #1da766;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-add-equipment:hover {
|
||||
background: #16a085;
|
||||
}
|
||||
|
||||
.cd-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.cd-table th,
|
||||
.cd-table td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.cd-table th {
|
||||
background-color: #1da766;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
padding: 2rem !important;
|
||||
}
|
||||
|
||||
.action-cell {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.2rem;
|
||||
padding: 4px 8px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-delete:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
animation: modalSlideIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9) translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 20px;
|
||||
border-bottom: 2px solid #1da766;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin: 0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 28px;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 15px 20px;
|
||||
border-top: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.equipment-list {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.equipment-item {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #eee;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.equipment-item:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.equipment-item.selected {
|
||||
background: #e8f5e9;
|
||||
border-left: 3px solid #1da766;
|
||||
}
|
||||
|
||||
.equipment-name {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.equipment-details {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.no-results {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.selected-equipment-details {
|
||||
background: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.selected-equipment-details h4 {
|
||||
margin-top: 0;
|
||||
color: #1da766;
|
||||
}
|
||||
|
||||
.selected-equipment-details p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
padding: 8px 20px;
|
||||
background: #1da766;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-confirm:hover:not(:disabled) {
|
||||
background: #16a085;
|
||||
}
|
||||
|
||||
.btn-confirm:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
padding: 8px 20px;
|
||||
background: #6c757d;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-cancel:hover {
|
||||
background: #5a6268;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
import API from '@/utils/api'
|
||||
|
||||
export default {
|
||||
name: "EquipmentView",
|
||||
props: {
|
||||
@@ -44,6 +398,114 @@ name: "EquipmentView",
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAddDialog: false,
|
||||
isLoading: false,
|
||||
isSubmitting: false,
|
||||
masterEquipment: [],
|
||||
filteredMasterEquipment: [],
|
||||
selectedEquipment: null,
|
||||
searchQuery: '',
|
||||
equipmentAmount: 1
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$api = API
|
||||
},
|
||||
methods: {
|
||||
async openAddEquipmentDialog() {
|
||||
this.showAddDialog = true
|
||||
this.isLoading = true
|
||||
|
||||
try {
|
||||
const response = await this.$api.get('/api/maintenance/equipment')
|
||||
this.masterEquipment = response.data || []
|
||||
this.filteredMasterEquipment = this.masterEquipment
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Ausrüstungs-Stammdaten:', error)
|
||||
alert(this.$t('equipment.loadError') + ': ' + (error.response?.data?.error || error.message))
|
||||
} finally {
|
||||
this.isLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
filterEquipment() {
|
||||
const query = this.searchQuery.toLowerCase().trim()
|
||||
if (!query) {
|
||||
this.filteredMasterEquipment = this.masterEquipment
|
||||
} else {
|
||||
this.filteredMasterEquipment = this.masterEquipment.filter(equipment =>
|
||||
equipment.name.toLowerCase().includes(query) ||
|
||||
(equipment.beschreibung && equipment.beschreibung.toLowerCase().includes(query))
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
selectEquipment(equipment) {
|
||||
this.selectedEquipment = equipment
|
||||
},
|
||||
|
||||
async addEquipment() {
|
||||
if (!this.selectedEquipment) {
|
||||
alert(this.$t('equipment.pleaseSelect'))
|
||||
return
|
||||
}
|
||||
|
||||
this.isSubmitting = true
|
||||
|
||||
try {
|
||||
const equipmentData = {
|
||||
character_id: this.character.id,
|
||||
name: this.selectedEquipment.name,
|
||||
beschreibung: this.selectedEquipment.beschreibung || '',
|
||||
gewicht: this.selectedEquipment.weight || 0,
|
||||
wert: this.selectedEquipment.value || 0,
|
||||
anzahl: this.equipmentAmount,
|
||||
bonus: this.selectedEquipment.bonus || 0,
|
||||
beinhaltet_in: '',
|
||||
contained_in: 0,
|
||||
container_type: ''
|
||||
}
|
||||
|
||||
await this.$api.post('/api/equipment', equipmentData)
|
||||
|
||||
alert(this.$t('equipment.addSuccess'))
|
||||
this.closeDialog()
|
||||
this.$emit('character-updated')
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Hinzufügen der Ausrüstung:', error)
|
||||
alert(this.$t('equipment.addError') + ': ' + (error.response?.data?.error || error.message))
|
||||
} finally {
|
||||
this.isSubmitting = false
|
||||
}
|
||||
},
|
||||
|
||||
async deleteEquipment(equipment) {
|
||||
if (!confirm(this.$t('equipment.confirmDelete').replace('{name}', equipment.name))) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$api.delete(`/api/equipment/${equipment.id}`)
|
||||
alert(this.$t('equipment.deleteSuccess'))
|
||||
this.$emit('character-updated')
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen der Ausrüstung:', error)
|
||||
alert(this.$t('equipment.deleteError') + ': ' + (error.response?.data?.error || error.message))
|
||||
}
|
||||
},
|
||||
|
||||
closeDialog() {
|
||||
this.showAddDialog = false
|
||||
this.selectedEquipment = null
|
||||
this.searchQuery = ''
|
||||
this.equipmentAmount = 1
|
||||
this.filteredMasterEquipment = []
|
||||
this.masterEquipment = []
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<div class="cd-view">
|
||||
<div class="header-section">
|
||||
<h2>{{ $t('WeaponView') }}</h2>
|
||||
<button @click="openAddWeaponDialog" class="btn-add-weapon">
|
||||
{{ $t('weapon.add') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="cd-list">
|
||||
<table class="cd-table">
|
||||
<thead>
|
||||
@@ -11,33 +18,493 @@
|
||||
<th>{{ $t('weapon.amount') }}</th>
|
||||
<th>{{ $t('weapon.contained_in') }}</th>
|
||||
<th>{{ $t('weapon.bonus') }}</th>
|
||||
<th>{{ $t('weapon.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="weapon in character.waffen">
|
||||
<template v-if="character.waffen && character.waffen.length > 0">
|
||||
<tr v-for="weapon in character.waffen" :key="weapon.id">
|
||||
<td>{{ weapon.name || '-' }}<span v-if="weapon.ist_magisch" class="magic-indicator">*</span></td>
|
||||
<td>{{ weapon.beschreibung || '-' }}</td>
|
||||
<td>{{ weapon.gewicht || '-' }}</td>
|
||||
<td>{{ weapon.wert || '-' }}</td>
|
||||
<td>{{ weapon.anzahl || '-' }}</td>
|
||||
<td>{{ weapon.beinhaltet_in || '-' }}</td>
|
||||
<td>{{ weapon.anb || '-' }}/{{ weapon.abwb || '-' }}</td>
|
||||
<td class="action-cell">
|
||||
<button @click="editWeapon(weapon)" class="btn-edit" title="Bearbeiten">
|
||||
✏️
|
||||
</button>
|
||||
<button @click="deleteWeapon(weapon)" class="btn-delete" title="Löschen">
|
||||
🗑️
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template v-else>
|
||||
<tr>
|
||||
<td>{{ weapon.name || '-' }}</td>
|
||||
<td>{{ weapon.description || '-' }}</td>
|
||||
<td>{{ weapon.weight || '-' }}</td>
|
||||
<td>{{ weapon.value || '-' }}</td>
|
||||
<td>{{ weapon.amount || '-' }}</td>
|
||||
<td>{{ weapon.contained_in || '-' }}</td>
|
||||
<td>{{ weapon.Anb || '-' }}/{{ weapon.Abwb || '-' }}</td>
|
||||
<td colspan="8" class="empty-state">{{ $t('weapon.noWeapons') }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div> <!--- end cd-list-->
|
||||
</div> <!--- end character -datasheet-->
|
||||
</div>
|
||||
|
||||
<!-- Dialog für Waffe hinzufügen -->
|
||||
<div v-if="showAddDialog" class="modal-overlay" @click.self="closeDialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>{{ $t('weapon.addWeapon') }}</h3>
|
||||
<button @click="closeDialog" class="close-button">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.search') }}:</label>
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="$t('weapon.searchPlaceholder')"
|
||||
@input="filterWeapons"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="isLoading" class="loading">{{ $t('weapon.loading') }}</div>
|
||||
|
||||
<div v-else-if="filteredMasterWeapons.length > 0" class="weapon-list">
|
||||
<div
|
||||
v-for="weapon in filteredMasterWeapons"
|
||||
:key="weapon.id"
|
||||
class="weapon-item"
|
||||
:class="{ selected: selectedWeapon && selectedWeapon.id === weapon.id }"
|
||||
@click="selectWeapon(weapon)"
|
||||
>
|
||||
<div class="weapon-name">{{ weapon.name }}</div>
|
||||
<div class="weapon-details">
|
||||
{{ weapon.damage || '-' }} |
|
||||
{{ weapon.weight }}kg |
|
||||
{{ weapon.value || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="no-results">
|
||||
{{ searchQuery ? $t('weapon.noResults') : $t('weapon.noMasterData') }}
|
||||
</div>
|
||||
|
||||
<div v-if="selectedWeapon" class="selected-weapon-details">
|
||||
<h4>{{ $t('weapon.selectedWeapon') }}</h4>
|
||||
<p><strong>{{ $t('weapon.name') }}:</strong> {{ selectedWeapon.name }}</p>
|
||||
<p><strong>{{ $t('weapon.damage') }}:</strong> {{ selectedWeapon.damage || '-' }}</p>
|
||||
<p><strong>{{ $t('weapon.weight') }}:</strong> {{ selectedWeapon.weight }}kg</p>
|
||||
<p><strong>{{ $t('weapon.value') }}:</strong> {{ selectedWeapon.value || '-' }}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.amount') }}:</label>
|
||||
<input v-model.number="weaponAmount" type="number" min="1" value="1" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button @click="closeDialog" class="btn-cancel">{{ $t('weapon.cancel') }}</button>
|
||||
<button
|
||||
@click="addWeapon"
|
||||
class="btn-confirm"
|
||||
:disabled="!selectedWeapon || isSubmitting"
|
||||
>
|
||||
{{ isSubmitting ? $t('weapon.adding') : $t('weapon.add') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dialog für Waffe bearbeiten -->
|
||||
<div v-if="showEditDialog" class="modal-overlay" @click.self="closeEditDialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>{{ $t('weapon.editWeapon') }}</h3>
|
||||
<button @click="closeEditDialog" class="close-button">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.name') }}:</label>
|
||||
<input v-model="editingWeapon.name" type="text" disabled />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.description') }}:</label>
|
||||
<textarea v-model="editingWeapon.beschreibung" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" v-model="editingWeapon.ist_magisch" />
|
||||
{{ $t('weapon.magical') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.amount') }}:</label>
|
||||
<input v-model.number="editingWeapon.anzahl" type="number" min="1" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.value') }}:</label>
|
||||
<input v-model.number="editingWeapon.wert" type="number" min="0" step="0.01" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.attackBonus') }} (Anb):</label>
|
||||
<input v-model.number="editingWeapon.anb" type="number" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.defenseBonus') }} (Abwb):</label>
|
||||
<input v-model.number="editingWeapon.abwb" type="number" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{ $t('weapon.damageBonus') }} (Schb):</label>
|
||||
<input v-model.number="editingWeapon.schb" type="number" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button @click="closeEditDialog" class="btn-cancel">{{ $t('weapon.cancel') }}</button>
|
||||
<button
|
||||
@click="saveWeapon"
|
||||
class="btn-confirm"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
{{ isSubmitting ? $t('weapon.saving') : $t('weapon.save') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
.cd-view {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.btn-add-weapon {
|
||||
padding: 8px 16px;
|
||||
background: #1da766;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-add-weapon:hover {
|
||||
background: #16a085;
|
||||
}
|
||||
|
||||
.cd-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.cd-table th,
|
||||
.cd-table td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.cd-table th {
|
||||
background-color: #1da766;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
padding: 2rem !important;
|
||||
}
|
||||
|
||||
.magic-indicator {
|
||||
color: #9c27b0;
|
||||
font-weight: bold;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.action-cell {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-edit {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.2rem;
|
||||
padding: 4px 8px;
|
||||
margin-right: 8px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-edit:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.2rem;
|
||||
padding: 4px 8px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-delete:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-row .form-group {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-group textarea {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
resize: vertical;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
animation: modalSlideIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes modalSlideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9) translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 20px;
|
||||
border-bottom: 2px solid #1da766;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin: 0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 28px;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 15px 20px;
|
||||
border-top: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.weapon-list {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.weapon-item {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #eee;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.weapon-item:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.weapon-item.selected {
|
||||
background: #e8f5e9;
|
||||
border-left: 3px solid #1da766;
|
||||
}
|
||||
|
||||
.weapon-name {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.weapon-details {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.no-results {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.selected-weapon-details {
|
||||
background: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.selected-weapon-details h4 {
|
||||
margin-top: 0;
|
||||
color: #1da766;
|
||||
}
|
||||
|
||||
.selected-weapon-details p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
padding: 8px 20px;
|
||||
background: #1da766;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-confirm:hover:not(:disabled) {
|
||||
background: #16a085;
|
||||
}
|
||||
|
||||
.btn-confirm:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
padding: 8px 20px;
|
||||
background: #6c757d;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-cancel:hover {
|
||||
background: #5a6268;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
import API from '@/utils/api'
|
||||
|
||||
export default {
|
||||
name: "WeaponView",
|
||||
props: {
|
||||
@@ -45,6 +512,171 @@ name: "WeaponView",
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAddDialog: false,
|
||||
showEditDialog: false,
|
||||
isLoading: false,
|
||||
isSubmitting: false,
|
||||
masterWeapons: [],
|
||||
filteredMasterWeapons: [],
|
||||
selectedWeapon: null,
|
||||
editingWeapon: null,
|
||||
searchQuery: '',
|
||||
weaponAmount: 1
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$api = API
|
||||
},
|
||||
methods: {
|
||||
async openAddWeaponDialog() {
|
||||
this.showAddDialog = true
|
||||
this.isLoading = true
|
||||
|
||||
try {
|
||||
const response = await this.$api.get('/api/maintenance/weapons')
|
||||
this.masterWeapons = response.data || []
|
||||
this.filteredMasterWeapons = this.masterWeapons
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Waffen-Stammdaten:', error)
|
||||
alert(this.$t('weapon.loadError') + ': ' + (error.response?.data?.error || error.message))
|
||||
} finally {
|
||||
this.isLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
filterWeapons() {
|
||||
const query = this.searchQuery.toLowerCase().trim()
|
||||
if (!query) {
|
||||
this.filteredMasterWeapons = this.masterWeapons
|
||||
} else {
|
||||
this.filteredMasterWeapons = this.masterWeapons.filter(weapon =>
|
||||
weapon.name.toLowerCase().includes(query) ||
|
||||
(weapon.beschreibung && weapon.beschreibung.toLowerCase().includes(query))
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
selectWeapon(weapon) {
|
||||
this.selectedWeapon = weapon
|
||||
},
|
||||
|
||||
async addWeapon() {
|
||||
if (!this.selectedWeapon) {
|
||||
alert(this.$t('weapon.pleaseSelect'))
|
||||
return
|
||||
}
|
||||
|
||||
this.isSubmitting = true
|
||||
|
||||
try {
|
||||
const weaponData = {
|
||||
character_id: this.character.id,
|
||||
name: this.selectedWeapon.name,
|
||||
beschreibung: this.selectedWeapon.beschreibung || '',
|
||||
gewicht: this.selectedWeapon.weight || 0,
|
||||
wert: this.selectedWeapon.value || 0,
|
||||
anzahl: this.weaponAmount,
|
||||
ist_magisch: false,
|
||||
anb: this.selectedWeapon.attack_bonus || 0,
|
||||
abwb: this.selectedWeapon.defense_bonus || 0,
|
||||
schb: this.selectedWeapon.damage_bonus || 0,
|
||||
beinhaltet_in: '',
|
||||
contained_in: 0,
|
||||
container_type: ''
|
||||
}
|
||||
|
||||
await this.$api.post('/api/weapons', weaponData)
|
||||
|
||||
alert(this.$t('weapon.addSuccess'))
|
||||
this.closeDialog()
|
||||
this.$emit('character-updated')
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Hinzufügen der Waffe:', error)
|
||||
alert(this.$t('weapon.addError') + ': ' + (error.response?.data?.error || error.message))
|
||||
} finally {
|
||||
this.isSubmitting = false
|
||||
}
|
||||
},
|
||||
|
||||
editWeapon(weapon) {
|
||||
this.editingWeapon = {
|
||||
id: weapon.id,
|
||||
name: weapon.name,
|
||||
beschreibung: weapon.beschreibung || '',
|
||||
ist_magisch: weapon.ist_magisch || false,
|
||||
anzahl: weapon.anzahl || 1,
|
||||
wert: weapon.wert || 0,
|
||||
anb: weapon.anb || 0,
|
||||
abwb: weapon.abwb || 0,
|
||||
schb: weapon.schb || 0
|
||||
}
|
||||
this.showEditDialog = true
|
||||
},
|
||||
|
||||
async saveWeapon() {
|
||||
if (!this.editingWeapon) {
|
||||
return
|
||||
}
|
||||
|
||||
this.isSubmitting = true
|
||||
|
||||
try {
|
||||
const weaponData = {
|
||||
beschreibung: this.editingWeapon.beschreibung,
|
||||
ist_magisch: this.editingWeapon.ist_magisch,
|
||||
anzahl: this.editingWeapon.anzahl,
|
||||
wert: this.editingWeapon.wert,
|
||||
anb: this.editingWeapon.anb,
|
||||
abwb: this.editingWeapon.abwb,
|
||||
schb: this.editingWeapon.schb
|
||||
}
|
||||
|
||||
await this.$api.put(`/api/weapons/${this.editingWeapon.id}`, weaponData)
|
||||
|
||||
alert(this.$t('weapon.editSuccess'))
|
||||
this.closeEditDialog()
|
||||
this.$emit('character-updated')
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Speichern der Waffe:', error)
|
||||
alert(this.$t('weapon.editError') + ': ' + (error.response?.data?.error || error.message))
|
||||
} finally {
|
||||
this.isSubmitting = false
|
||||
}
|
||||
},
|
||||
|
||||
async deleteWeapon(weapon) {
|
||||
if (!confirm(this.$t('weapon.confirmDelete').replace('{name}', weapon.name))) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await this.$api.delete(`/api/weapons/${weapon.id}`)
|
||||
alert(this.$t('weapon.deleteSuccess'))
|
||||
this.$emit('character-updated')
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen der Waffe:', error)
|
||||
alert(this.$t('weapon.deleteError') + ': ' + (error.response?.data?.error || error.message))
|
||||
}
|
||||
},
|
||||
|
||||
closeEditDialog() {
|
||||
this.showEditDialog = false
|
||||
this.editingWeapon = null
|
||||
},
|
||||
|
||||
closeDialog() {
|
||||
this.showAddDialog = false
|
||||
this.selectedWeapon = null
|
||||
this.searchQuery = ''
|
||||
this.weaponAmount = 1
|
||||
this.filteredMasterWeapons = []
|
||||
this.masterWeapons = []
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -54,6 +54,25 @@ export default {
|
||||
quelle:'Quelle',
|
||||
system:'System',
|
||||
personal_item:'Pers',
|
||||
add: 'Ausrüstung hinzufügen',
|
||||
addEquipment: 'Ausrüstung hinzufügen',
|
||||
search: 'Suche',
|
||||
searchPlaceholder: 'Ausrüstung suchen...',
|
||||
loading: 'Lade Ausrüstung...',
|
||||
noEquipment: 'Keine Ausrüstung vorhanden. Klicken Sie auf "Ausrüstung hinzufügen", um eine hinzuzufügen.',
|
||||
noResults: 'Keine Ausrüstung gefunden.',
|
||||
noMasterData: 'Keine Ausrüstungs-Stammdaten verfügbar.',
|
||||
selectedEquipment: 'Ausgewählte Ausrüstung',
|
||||
cancel: 'Abbrechen',
|
||||
adding: 'Wird hinzugefügt...',
|
||||
pleaseSelect: 'Bitte wählen Sie eine Ausrüstung aus.',
|
||||
addSuccess: 'Ausrüstung erfolgreich hinzugefügt!',
|
||||
addError: 'Fehler beim Hinzufügen der Ausrüstung',
|
||||
loadError: 'Fehler beim Laden der Ausrüstungs-Stammdaten',
|
||||
confirmDelete: 'Möchten Sie die Ausrüstung "{name}" wirklich löschen?',
|
||||
deleteSuccess: 'Ausrüstung erfolgreich gelöscht!',
|
||||
deleteError: 'Fehler beim Löschen der Ausrüstung',
|
||||
actions: 'Aktionen'
|
||||
},
|
||||
skill:{
|
||||
id:'ID',
|
||||
@@ -132,6 +151,34 @@ export default {
|
||||
personal_item:'Pers',
|
||||
quelle:'Quelle',
|
||||
system:'System',
|
||||
add: 'Waffe hinzufügen',
|
||||
addWeapon: 'Waffe hinzufügen',
|
||||
search: 'Suche',
|
||||
searchPlaceholder: 'Waffe suchen...',
|
||||
loading: 'Lade Waffen...',
|
||||
noWeapons: 'Keine Waffen vorhanden. Klicken Sie auf "Waffe hinzufügen", um eine hinzuzufügen.',
|
||||
noResults: 'Keine Waffen gefunden.',
|
||||
noMasterData: 'Keine Waffen-Stammdaten verfügbar.',
|
||||
selectedWeapon: 'Ausgewählte Waffe',
|
||||
cancel: 'Abbrechen',
|
||||
adding: 'Wird hinzugefügt...',
|
||||
pleaseSelect: 'Bitte wählen Sie eine Waffe aus.',
|
||||
addSuccess: 'Waffe erfolgreich hinzugefügt!',
|
||||
addError: 'Fehler beim Hinzufügen der Waffe',
|
||||
loadError: 'Fehler beim Laden der Waffen-Stammdaten',
|
||||
confirmDelete: 'Möchten Sie die Waffe "{name}" wirklich löschen?',
|
||||
deleteSuccess: 'Waffe erfolgreich gelöscht!',
|
||||
deleteError: 'Fehler beim Löschen der Waffe',
|
||||
actions: 'Aktionen',
|
||||
editWeapon: 'Waffe bearbeiten',
|
||||
magical: 'Magisch',
|
||||
attackBonus: 'Angriffsbonus',
|
||||
defenseBonus: 'Abwehrbonus',
|
||||
damageBonus: 'Schadensbonus',
|
||||
save: 'Speichern',
|
||||
saving: 'Wird gespeichert...',
|
||||
editSuccess: 'Waffe erfolgreich aktualisiert!',
|
||||
editError: 'Fehler beim Speichern der Waffe'
|
||||
},
|
||||
Weapons:'Waffen',
|
||||
weaponskill:{
|
||||
|
||||
+47
-2
@@ -53,8 +53,25 @@ export default {
|
||||
wert:'Value',
|
||||
quelle:'Source',
|
||||
system:'System',
|
||||
personal_item:'Pers',
|
||||
},
|
||||
personal_item:'Pers', add: 'Add Equipment',
|
||||
addEquipment: 'Add Equipment',
|
||||
search: 'Search',
|
||||
searchPlaceholder: 'Search equipment...',
|
||||
loading: 'Loading equipment...',
|
||||
noEquipment: 'No equipment available. Click "Add Equipment" to add one.',
|
||||
noResults: 'No equipment found.',
|
||||
noMasterData: 'No equipment master data available.',
|
||||
selectedEquipment: 'Selected Equipment',
|
||||
cancel: 'Cancel',
|
||||
adding: 'Adding...',
|
||||
pleaseSelect: 'Please select equipment.',
|
||||
addSuccess: 'Equipment successfully added!',
|
||||
addError: 'Error adding equipment',
|
||||
loadError: 'Error loading equipment master data',
|
||||
confirmDelete: 'Do you really want to delete the equipment "{name}"?',
|
||||
deleteSuccess: 'Equipment successfully deleted!',
|
||||
deleteError: 'Error deleting equipment',
|
||||
actions: 'Actions' },
|
||||
skill:{
|
||||
id:'ID',
|
||||
name:'Name',
|
||||
@@ -132,6 +149,34 @@ export default {
|
||||
personal_item:'Pers',
|
||||
quelle:'Source',
|
||||
system:'System',
|
||||
add: 'Add Weapon',
|
||||
addWeapon: 'Add Weapon',
|
||||
search: 'Search',
|
||||
searchPlaceholder: 'Search weapon...',
|
||||
loading: 'Loading weapons...',
|
||||
noWeapons: 'No weapons available. Click "Add Weapon" to add one.',
|
||||
noResults: 'No weapons found.',
|
||||
noMasterData: 'No weapon master data available.',
|
||||
selectedWeapon: 'Selected Weapon',
|
||||
cancel: 'Cancel',
|
||||
adding: 'Adding...',
|
||||
pleaseSelect: 'Please select a weapon.',
|
||||
addSuccess: 'Weapon successfully added!',
|
||||
addError: 'Error adding weapon',
|
||||
loadError: 'Error loading weapon master data',
|
||||
confirmDelete: 'Do you really want to delete the weapon "{name}"?',
|
||||
deleteSuccess: 'Weapon successfully deleted!',
|
||||
deleteError: 'Error deleting weapon',
|
||||
actions: 'Actions',
|
||||
editWeapon: 'Edit Weapon',
|
||||
magical: 'Magical',
|
||||
attackBonus: 'Attack Bonus',
|
||||
defenseBonus: 'Defense Bonus',
|
||||
damageBonus: 'Damage Bonus',
|
||||
save: 'Save',
|
||||
saving: 'Saving...',
|
||||
editSuccess: 'Weapon successfully updated!',
|
||||
editError: 'Error saving weapon'
|
||||
},
|
||||
Weapons:'Waffen',
|
||||
weaponskill:{
|
||||
|
||||
Reference in New Issue
Block a user