Füge neue Funktionalität zum Abrufen von Worship-Optionen hinzu: Implementiere Endpunkt für eindeutige Gestalter und Küsterdienste. Aktualisiere das Worship Management-Formular zur Verwendung von Multiselect-Komponenten für die Auswahl und Eingabe von Gestaltern und Küstern. Integriere die Fetch-Funktion für Worship-Optionen im Vue-Komponenten-Lifecycle.

This commit is contained in:
Torsten Schulz (local)
2025-10-07 16:52:52 +02:00
parent 3303c749e2
commit fd84112cef
3 changed files with 118 additions and 4 deletions

View File

@@ -120,3 +120,60 @@ exports.getFilteredWorships = async (req, res) => {
res.status(500).json({ message: 'Fehler beim Abrufen der gefilterten Gottesdienste' }); res.status(500).json({ message: 'Fehler beim Abrufen der gefilterten Gottesdienste' });
} }
}; };
exports.getWorshipOptions = async (req, res) => {
try {
// Alle eindeutigen Organizer-Werte abrufen
const organizers = await Worship.findAll({
attributes: [[sequelize.fn('DISTINCT', sequelize.col('organizer')), 'organizer']],
where: {
organizer: {
[Op.not]: null,
[Op.ne]: ''
}
},
raw: true
});
// Alle eindeutigen Sacristan-Service-Werte abrufen
const sacristanServices = await Worship.findAll({
attributes: [[sequelize.fn('DISTINCT', sequelize.col('sacristanService')), 'sacristanService']],
where: {
sacristanService: {
[Op.not]: null,
[Op.ne]: ''
}
},
raw: true
});
// Strings aufteilen (kommasepariert) und alle eindeutigen Werte sammeln
const organizerSet = new Set();
organizers.forEach(item => {
if (item.organizer) {
item.organizer.split(',').forEach(org => {
const trimmed = org.trim();
if (trimmed) organizerSet.add(trimmed);
});
}
});
const sacristanSet = new Set();
sacristanServices.forEach(item => {
if (item.sacristanService) {
item.sacristanService.split(',').forEach(sac => {
const trimmed = sac.trim();
if (trimmed) sacristanSet.add(trimmed);
});
}
});
res.status(200).json({
organizers: Array.from(organizerSet).sort(),
sacristanServices: Array.from(sacristanSet).sort()
});
} catch (error) {
console.log(error);
res.status(500).json({ message: 'Fehler beim Abrufen der Worship-Optionen' });
}
};

View File

@@ -1,9 +1,10 @@
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
const { getAllWorships, createWorship, updateWorship, deleteWorship, getFilteredWorships } = require('../controllers/worshipController'); const { getAllWorships, createWorship, updateWorship, deleteWorship, getFilteredWorships, getWorshipOptions } = require('../controllers/worshipController');
const authMiddleware = require('../middleware/authMiddleware'); const authMiddleware = require('../middleware/authMiddleware');
router.get('/', getAllWorships); router.get('/', getAllWorships);
router.get('/options', getWorshipOptions);
router.post('/', authMiddleware, createWorship); router.post('/', authMiddleware, createWorship);
router.put('/:id', authMiddleware, updateWorship); router.put('/:id', authMiddleware, updateWorship);
router.delete('/:id', authMiddleware, deleteWorship); router.delete('/:id', authMiddleware, deleteWorship);

View File

@@ -19,10 +19,28 @@
<input type="text" id="title" v-model="worshipData.title" required> <input type="text" id="title" v-model="worshipData.title" required>
<label for="organizer">Gestalter:</label> <label for="organizer">Gestalter:</label>
<input type="text" id="organizer" v-model="worshipData.organizer"> <multiselect
v-model="selectedOrganizers"
:options="organizerOptions"
:multiple="true"
:taggable="true"
@tag="addOrganizerTag"
placeholder="Gestalter wählen oder neu eingeben"
label="name"
track-by="name">
</multiselect>
<label for="sacristanService">Küsterdienst:</label> <label for="sacristanService">Küsterdienst:</label>
<input type="text" id="sacristanService" v-model="worshipData.sacristanService"> <multiselect
v-model="selectedSacristans"
:options="sacristanOptions"
:multiple="true"
:taggable="true"
@tag="addSacristanTag"
placeholder="Küsterdienst wählen oder neu eingeben"
label="name"
track-by="name">
</multiselect>
<label for="collection">Kollekte:</label> <label for="collection">Kollekte:</label>
<input type="text" id="collection" v-model="worshipData.collection"> <input type="text" id="collection" v-model="worshipData.collection">
@@ -88,6 +106,10 @@ export default {
return { return {
worships: [], worships: [],
eventPlaces: [], eventPlaces: [],
organizerOptions: [],
sacristanOptions: [],
selectedOrganizers: [],
selectedSacristans: [],
worshipData: { worshipData: {
eventPlaceId: null, eventPlaceId: null,
date: '', date: '',
@@ -150,6 +172,7 @@ export default {
async created() { async created() {
await this.fetchEventPlaces(); await this.fetchEventPlaces();
await this.fetchWorships(); await this.fetchWorships();
await this.fetchWorshipOptions();
}, },
methods: { methods: {
formatTime, formatTime,
@@ -170,11 +193,22 @@ export default {
console.error('Fehler beim Abrufen der Veranstaltungsorte:', error); console.error('Fehler beim Abrufen der Veranstaltungsorte:', error);
} }
}, },
async fetchWorshipOptions() {
try {
const response = await axios.get('/worships/options');
this.organizerOptions = response.data.organizers.map(org => ({ name: org }));
this.sacristanOptions = response.data.sacristanServices.map(sac => ({ name: sac }));
} catch (error) {
console.error('Fehler beim Abrufen der Worship-Optionen:', error);
}
},
async saveWorship() { async saveWorship() {
try { try {
const payload = { const payload = {
...this.worshipData, ...this.worshipData,
eventPlaceId: this.selectedEventPlace ? this.selectedEventPlace.id : null eventPlaceId: this.selectedEventPlace ? this.selectedEventPlace.id : null,
organizer: this.selectedOrganizers.map(org => org.name).join(', '),
sacristanService: this.selectedSacristans.map(sac => sac.name).join(', ')
}; };
if (this.editMode) { if (this.editMode) {
@@ -185,6 +219,7 @@ export default {
this.resetForm(); this.resetForm();
await this.fetchWorships(); await this.fetchWorships();
await this.fetchWorshipOptions();
} catch (error) { } catch (error) {
console.error('Fehler beim Speichern des Gottesdienstes:', error); console.error('Fehler beim Speichern des Gottesdienstes:', error);
} }
@@ -195,6 +230,15 @@ export default {
this.worshipData.time = formatTime(worship.time); this.worshipData.time = formatTime(worship.time);
console.log(this.worshipData); console.log(this.worshipData);
this.selectedEventPlace = this.eventPlaces.find(ep => ep.id === worship.eventPlaceId); this.selectedEventPlace = this.eventPlaces.find(ep => ep.id === worship.eventPlaceId);
// Konvertiere kommaseparierte Strings zu Arrays für Multiselect
this.selectedOrganizers = worship.organizer
? worship.organizer.split(',').map(org => ({ name: org.trim() }))
: [];
this.selectedSacristans = worship.sacristanService
? worship.sacristanService.split(',').map(sac => ({ name: sac.trim() }))
: [];
this.editMode = true; this.editMode = true;
this.editId = worship.id; this.editId = worship.id;
}, },
@@ -221,6 +265,8 @@ export default {
introLine: '' introLine: ''
}; };
this.selectedEventPlace = null; this.selectedEventPlace = null;
this.selectedOrganizers = [];
this.selectedSacristans = [];
this.editMode = false; this.editMode = false;
this.editId = null; this.editId = null;
}, },
@@ -235,6 +281,16 @@ export default {
}, },
clearSearch() { clearSearch() {
this.searchDate = ''; this.searchDate = '';
},
addOrganizerTag(newTag) {
const tag = { name: newTag };
this.organizerOptions.push(tag);
this.selectedOrganizers.push(tag);
},
addSacristanTag(newTag) {
const tag = { name: newTag };
this.sacristanOptions.push(tag);
this.selectedSacristans.push(tag);
} }
} }
}; };