feat(backend, frontend): Hinzufügen von Funktionen zur Verwaltung von Lagerbeständen im Falukant-System

- Implementierung von Methoden zur Hinzufügung und Abfrage von Lagerbeständen im AdminController und AdminService.
- Erweiterung der Routen im AdminRouter zur Unterstützung der neuen Lagerverwaltungsfunktionen.
- Anpassung der Benutzeroberfläche zur Integration eines Dialogs für die Lagerhinzufügung und zur Anzeige von Lagertypen.
- Aktualisierung der Übersetzungen in den Sprachdateien für die neuen Funktionen und Fehlermeldungen.
This commit is contained in:
Torsten Schulz (local)
2025-08-31 20:51:15 +02:00
parent 8a03c04668
commit 224503b660
9 changed files with 373 additions and 5 deletions

View File

@@ -62,8 +62,16 @@
"branches": {
"title": "Niederlassungen & Lager",
"noStocks": "Kein Lager vorhanden",
"noBranches": "Keine Niederlassungen gefunden"
}
"noBranches": "Keine Niederlassungen gefunden",
"addStock": "Lager hinzufügen",
"stockType": "Lagertyp",
"selectStockType": "Lagertyp auswählen",
"quantity": "Menge"
},
"errorLoadingStockTypes": "Fehler beim Laden der Lagertypen.",
"errorAddingStock": "Fehler beim Hinzufügen des Lagers.",
"stockAdded": "Lager erfolgreich hinzugefügt.",
"invalidStockData": "Bitte gültige Lagertyp- und Mengenangaben eingeben."
}
},
"chatrooms": {

View File

@@ -48,6 +48,8 @@
"create": "Erstellen",
"update": "Aktualisieren",
"save": "Speichern",
"add": "Hinzufügen",
"cancel": "Abbrechen",
"yes": "Ja",
"no": "Nein"
}

View File

@@ -74,8 +74,16 @@
"branches": {
"title": "Branches & Warehouse",
"noStocks": "No warehouse available",
"noBranches": "No branches found"
}
"noBranches": "No branches found",
"addStock": "Add Warehouse",
"stockType": "Warehouse Type",
"selectStockType": "Select warehouse type",
"quantity": "Quantity"
},
"errorLoadingStockTypes": "Error loading warehouse types.",
"errorAddingStock": "Error adding warehouse.",
"stockAdded": "Warehouse successfully added.",
"invalidStockData": "Please enter valid warehouse type and quantity."
}
}
}

View File

@@ -15,6 +15,8 @@
"create": "Create",
"update": "Update",
"save": "Save",
"add": "Add",
"cancel": "Cancel",
"yes": "Yes",
"no": "No"
}

View File

@@ -67,6 +67,11 @@
<div v-else class="no-stocks">
{{ $t('admin.falukant.edituser.branches.noStocks') }}
</div>
<div class="add-stock-section">
<button @click="openAddStockDialog(branch.id)" class="add-stock-btn">
{{ $t('admin.falukant.edituser.branches.addStock') }}
</button>
</div>
</div>
</div>
<div v-if="!userBranches.length" class="no-branches">
@@ -76,6 +81,36 @@
</div>
</div>
</div>
<!-- Add Stock Dialog -->
<div v-if="showAddStockDialog" class="dialog-overlay" @click="closeAddStockDialog">
<div class="dialog" @click.stop>
<h3>{{ $t('admin.falukant.edituser.branches.addStock') }}</h3>
<div class="dialog-content">
<div class="form-group">
<label>{{ $t('admin.falukant.edituser.branches.stockType') }}:</label>
<select v-model="newStock.stockTypeId" class="form-select">
<option value="">{{ $t('admin.falukant.edituser.branches.selectStockType') }}</option>
<option v-for="stockType in stockTypes" :key="stockType.id" :value="stockType.id">
{{ $t(`falukant.branch.stocktype.${stockType.labelTr}`) }}
</option>
</select>
</div>
<div class="form-group">
<label>{{ $t('admin.falukant.edituser.branches.quantity') }}:</label>
<input type="number" v-model="newStock.quantity" min="1" class="form-input" />
</div>
</div>
<div class="dialog-actions">
<button @click="closeAddStockDialog" class="btn btn-secondary">
{{ $t('common.cancel') }}
</button>
<button @click="addStock" class="btn btn-primary">
{{ $t('common.add') }}
</button>
</div>
</div>
</div>
</div>
</template>
@@ -109,8 +144,16 @@ export default {
{ value: 'branches', label: 'admin.falukant.edituser.tabs.branches' }
],
userBranches: [],
stockTypes: [],
newStock: {
branchId: null,
stockTypeId: null,
quantity: 0
},
showAddStockDialog: false,
loading: {
branches: false
branches: false,
stockTypes: false
}
}
},
@@ -120,6 +163,9 @@ export default {
async mounted() {
const titlesResult = await apiClient.get('/api/falukant/nobility/titels');
this.titles = titlesResult.data;
// Lade Stock-Types
await this.loadStockTypes();
},
methods: {
async searchUser() {
@@ -192,6 +238,55 @@ export default {
console.error('Error updating stock:', error);
this.$root.$refs.errorDialog.open('tr:admin.falukant.edituser.errorUpdatingStock');
}
},
async loadStockTypes() {
this.loading.stockTypes = true;
try {
const stockTypesResult = await apiClient.get('/api/admin/falukant/stock-types');
this.stockTypes = stockTypesResult.data;
} catch (error) {
console.error('Error loading stock types:', error);
this.$root.$refs.errorDialog.open('tr:admin.falukant.edituser.errorLoadingStockTypes');
} finally {
this.loading.stockTypes = false;
}
},
openAddStockDialog(branchId) {
this.newStock.branchId = branchId;
this.newStock.stockTypeId = null;
this.newStock.quantity = 0;
this.showAddStockDialog = true;
},
closeAddStockDialog() {
this.showAddStockDialog = false;
this.newStock = {
branchId: null,
stockTypeId: null,
quantity: 0
};
},
async addStock() {
if (!this.newStock.stockTypeId || this.newStock.quantity <= 0) {
this.$root.$refs.errorDialog.open('tr:admin.falukant.edituser.invalidStockData');
return;
}
try {
await apiClient.post('/api/admin/falukant/stock', {
branchId: this.newStock.branchId,
stockTypeId: this.newStock.stockTypeId,
quantity: this.newStock.quantity
});
this.$root.$refs.messageDialog.open('tr:admin.falukant.edituser.stockAdded');
this.closeAddStockDialog();
// Lade Branches neu um den neuen Stock anzuzeigen
await this.loadUserBranches();
} catch (error) {
console.error('Error adding stock:', error);
this.$root.$refs.errorDialog.open('tr:admin.falukant.edituser.errorAddingStock');
}
}
}
}
@@ -404,4 +499,117 @@ export default {
font-style: italic;
padding: 20px;
}
/* Add Stock Dialog Styles */
.dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.dialog {
background: white;
border-radius: 8px;
padding: 20px;
min-width: 400px;
max-width: 500px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
.dialog h3 {
margin: 0 0 20px 0;
color: #333;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.dialog-content {
margin-bottom: 20px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #555;
}
.form-select, .form-input {
width: 100%;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.form-select:focus, .form-input:focus {
outline: none;
border-color: #1976d2;
box-shadow: 0 0 0 2px rgba(25, 118, 210, 0.2);
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
}
.btn-primary {
background: #1976d2;
color: white;
}
.btn-primary:hover {
background: #1565c0;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-secondary:hover {
background: #5a6268;
}
/* Add Stock Button */
.add-stock-section {
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #eee;
}
.add-stock-btn {
background: #28a745;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.add-stock-btn:hover {
background: #218838;
}
</style>