Files
bamort/frontend/src/components/EquipmentView.vue
T

274 lines
8.5 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="fullwidth-container">
<div class="header-section">
<h2>{{ $t('EquipmentView') }}</h2>
<button v-if="isOwner" @click="openAddEquipmentDialog" class="btn-add-equipment">
{{ $t('equipment.add') }}
</button>
</div>
<div class="cd-list">
<table class="cd-table">
<thead>
<tr>
<th>{{ $t('equipment.name') }}</th>
<th>{{ $t('equipment.description') }}</th>
<th>{{ $t('equipment.weight') }}</th>
<th>{{ $t('equipment.value') }}</th>
<th>{{ $t('equipment.amount') }}</th>
<th>{{ $t('equipment.contained_in') }}</th>
<th>{{ $t('equipment.bonus') }}</th>
<th v-if="isOwner">{{ $t('equipment.actions') }}</th>
</tr>
</thead>
<tbody>
<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>
<td>{{ equipment.wert || '-' }}</td>
<td>{{ equipment.anzahl || '-' }}</td>
<td>{{ equipment.beinhaltet_in || '-' }}</td>
<td>{{ equipment.bonus || '-' }}</td>
<td v-if="isOwner" 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>
<!-- Dialog für Ausrüstung hinzufügen -->
<div v-if="showAddDialog" class="modal-overlay" @click.self="closeDialog">
<div class="modal-content modal-fullscreen">
<div class="modal-header">
<h3>{{ $t('equipment.addEquipment') }}</h3>
<button @click="closeDialog" class="close-button">&times;</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 scoped>
/* All styles moved to main.css */
/* Equipment-specific table header color override */
.cd-table th {
background-color: #1da766;
}
/* Fix modal footer visibility */
.modal-fullscreen {
display: flex;
flex-direction: column;
max-height: calc(100vh - 50px);
}
.modal-fullscreen .modal-body {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
}
.modal-fullscreen .modal-header,
.modal-fullscreen .modal-footer {
flex-shrink: 0;
}
</style>
<script>
import API from '@/utils/api'
export default {
name: "EquipmentView",
props: {
character: {
type: Object,
required: true
},
isOwner: {
type: Boolean,
default: false
}
},
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>