Add widget management functionality: Implement getAvailableWidgets method in dashboardService to retrieve widget types, and create corresponding API endpoint in dashboardRouter. Update LoggedInView to allow users to select and add widgets dynamically, enhancing dashboard customization options.
This commit is contained in:
@@ -13,9 +13,22 @@
|
||||
Dashboard bearbeiten
|
||||
</button>
|
||||
<template v-else>
|
||||
<button type="button" class="btn-add" @click="addWidget">
|
||||
+ Widget hinzufügen
|
||||
</button>
|
||||
<div class="widget-add-row">
|
||||
<select
|
||||
v-model="selectedWidgetTypeId"
|
||||
class="widget-type-select"
|
||||
@change="onSelectWidgetType"
|
||||
>
|
||||
<option value="">+ Widget hinzufügen …</option>
|
||||
<option
|
||||
v-for="wt in widgetTypeOptions"
|
||||
:key="wt.id"
|
||||
:value="wt.id"
|
||||
>
|
||||
{{ wt.label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" class="btn-done" @click="doneEditing">
|
||||
Fertig
|
||||
</button>
|
||||
@@ -106,9 +119,17 @@ function generateId() {
|
||||
export default {
|
||||
name: 'HomeLoggedInView',
|
||||
components: { DashboardWidget },
|
||||
computed: {
|
||||
widgetTypeOptions() {
|
||||
if (this.availableWidgets.length > 0) return this.availableWidgets;
|
||||
return [{ id: 'default', label: 'Termine', endpoint: '/api/termine' }];
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
widgets: [],
|
||||
availableWidgets: [],
|
||||
selectedWidgetTypeId: '',
|
||||
loading: true,
|
||||
loadError: null,
|
||||
editMode: false,
|
||||
@@ -118,12 +139,21 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.loadConfig();
|
||||
this.loadAvailableWidgets();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['logout']),
|
||||
handleLogout() {
|
||||
this.logout();
|
||||
},
|
||||
async loadAvailableWidgets() {
|
||||
try {
|
||||
const { data } = await apiClient.get('/api/dashboard/widgets');
|
||||
this.availableWidgets = Array.isArray(data) ? data : [];
|
||||
} catch (e) {
|
||||
this.availableWidgets = [];
|
||||
}
|
||||
},
|
||||
async loadConfig() {
|
||||
this.loading = true;
|
||||
this.loadError = null;
|
||||
@@ -150,13 +180,19 @@ export default {
|
||||
console.error('Dashboard speichern fehlgeschlagen:', e);
|
||||
}
|
||||
},
|
||||
addWidget() {
|
||||
this.widgets.push({
|
||||
id: generateId(),
|
||||
title: 'Neues Widget',
|
||||
endpoint: '/api/termine'
|
||||
});
|
||||
this.saveConfig();
|
||||
onSelectWidgetType() {
|
||||
const id = this.selectedWidgetTypeId;
|
||||
if (!id) return;
|
||||
const wt = this.widgetTypeOptions.find(w => String(w.id) === String(id));
|
||||
if (wt) {
|
||||
this.widgets.push({
|
||||
id: generateId(),
|
||||
title: wt.label,
|
||||
endpoint: wt.endpoint
|
||||
});
|
||||
this.saveConfig();
|
||||
}
|
||||
this.selectedWidgetTypeId = '';
|
||||
},
|
||||
removeWidget(index) {
|
||||
this.widgets.splice(index, 1);
|
||||
@@ -250,14 +286,23 @@ export default {
|
||||
}
|
||||
|
||||
.btn-edit:hover,
|
||||
.btn-add:hover,
|
||||
.btn-done:hover {
|
||||
background: #f1f3f5;
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
border-color: #0d6efd;
|
||||
color: #0d6efd;
|
||||
.widget-add-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.widget-type-select {
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #ced4da;
|
||||
background: #fff;
|
||||
color: #495057;
|
||||
font-size: 0.9rem;
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.btn-done {
|
||||
|
||||
Reference in New Issue
Block a user