diff --git a/controllers/eventController.js b/controllers/eventController.js index 47a38f1..cdd4b60 100644 --- a/controllers/eventController.js +++ b/controllers/eventController.js @@ -21,7 +21,7 @@ const getAllEvents = async (req, res) => { const filterEvents = async (req, res) => { try { - const { id, 'event-places': eventPlaces, 'event-types': eventTypes, display } = req.query; + const request = req.body; const where = { [Op.or]: [ { @@ -36,7 +36,7 @@ const filterEvents = async (req, res) => { ] }; - if (id === 'all') { + if (request.id === 'all') { const events = await Event.findAll({ where, include: [ @@ -49,7 +49,7 @@ const filterEvents = async (req, res) => { return res.json({ events }); } - if (id === 'home') { + if (request.id === 'home') { const events = await Event.findAll({ where: { alsoOnHomepage: 1, @@ -65,23 +65,23 @@ const filterEvents = async (req, res) => { return res.json({ events }); } - if (!id && !eventPlaces && !eventTypes) { - return res.json({ events: [], eventPlaces: [], eventTypes: [], contactPersons: [] }); + if (!request.id && !request.places && !request.types) { + return res.json({ events: [], places: [], types: [], contactPersons: [] }); } - if (id) { - where.id = id; + if (request.id) { + where.id = request.id; } - if (eventPlaces) { + if (request.places && request.places.length > 0) { where.event_place_id = { - [Op.in]: eventPlaces.split('|').map(id => parseInt(id)) + [Op.in]: request.places.map(id => parseInt(id)) }; } - if (eventTypes) { + if (request.types && request.types.length > 0) { where.eventTypeId = { - [Op.in]: eventTypes.split('|').map(id => parseInt(id)) + [Op.in]: request.types.map(id => parseInt(id)) }; } @@ -94,8 +94,7 @@ const filterEvents = async (req, res) => { { model: ContactPerson, as: 'contactPersons', through: { attributes: [] } } ] }); - - const displayFields = display ? display.split('|') : []; + const displayFields = request.display ? request.display : []; const filteredEvents = events.map(event => { const filteredEvent = { ...event.toJSON() }; diff --git a/controllers/institutionController.js b/controllers/institutionController.js index 65f1b2b..577c407 100644 --- a/controllers/institutionController.js +++ b/controllers/institutionController.js @@ -18,6 +18,28 @@ const getAllInstitutions = async (req, res) => { } }; +const getInstitutionById = async (req, res) => { + try { + const { id } = req.params; + const institution = await Institution.findByPk(id, { + include: [ + { + model: ContactPerson, + as: 'contactPersons', + through: { attributes: [] } + } + ] + }); + if (!institution) { + return res.status(404).json({ error: 'Institution not found' }); + } + res.json(institution); + } catch (error) { + res.status(500).json({ error: 'Failed to fetch institution' }); + console.error(error); + } +}; + const createInstitution = async (req, res) => { try { const { contactPersonIds, ...institutionData } = req.body; @@ -70,6 +92,7 @@ const deleteInstitution = async (req, res) => { module.exports = { getAllInstitutions, + getInstitutionById, createInstitution, updateInstitution, deleteInstitution diff --git a/controllers/worshipController.js b/controllers/worshipController.js index 4ded946..5c57158 100644 --- a/controllers/worshipController.js +++ b/controllers/worshipController.js @@ -49,24 +49,21 @@ exports.deleteWorship = async (req, res) => { }; exports.getFilteredWorships = async (req, res) => { - const { location, orderBy } = req.query; + const { location, order } = req.query; const where = {}; - if (location && location !== '-1') { - if (location.includes('|')) { - const locationsArray = location.split('|'); + const locations = JSON.parse(location); + if (location && locations.length > 0) { where.eventPlaceId = { - [Sequelize.Op.in]: locationsArray + [Sequelize.Op.in]: locations } - } else { - where.eventPlaceId = location; - } } where.date = { [Op.gte]: new Date(), // Only include events from today onwards }; + console.log(where, order); try { const worships = await Worship.findAll({ where, @@ -74,7 +71,7 @@ exports.getFilteredWorships = async (req, res) => { model: EventPlace, as: 'eventPlace', }, - order: [orderBy.split(' ')], + order: [order.split(' ')], }); res.status(200).json(worships); } catch (error) { diff --git a/models/Image.js b/models/Image.js index 3318bad..15c4537 100644 --- a/models/Image.js +++ b/models/Image.js @@ -26,7 +26,7 @@ module.exports = (sequelize) => { pageId: { type: DataTypes.UUID, allowNull: true - } + }, }, { tableName: 'images', timestamps: false diff --git a/models/MenuItem.js b/models/MenuItem.js index cb53fbb..ee977fe 100644 --- a/models/MenuItem.js +++ b/models/MenuItem.js @@ -37,7 +37,11 @@ module.exports = (sequelize) => { page_title: { type: DataTypes.STRING, allowNull: true - } + }, + image: { + type: DataTypes.STRING, + allowNull: true, + }, }, { tableName: 'menu_items', timestamps: false diff --git a/public/images/uploads/0cf0624e-8394-49fc-a44d-3d2f4d876061.jpg b/public/images/uploads/0cf0624e-8394-49fc-a44d-3d2f4d876061.jpg new file mode 100644 index 0000000..2117044 Binary files /dev/null and b/public/images/uploads/0cf0624e-8394-49fc-a44d-3d2f4d876061.jpg differ diff --git a/routes/event.js b/routes/event.js index 40f8b80..9607a36 100644 --- a/routes/event.js +++ b/routes/event.js @@ -7,6 +7,6 @@ router.get('/', authMiddleware, getAllEvents); router.post('/', authMiddleware, createEvent); router.put('/:id', authMiddleware, updateEvent); router.delete('/:id', authMiddleware, deleteEvent); -router.get('/filter', filterEvents); +router.post('/filter', filterEvents); module.exports = router; diff --git a/routes/institutions.js b/routes/institutions.js index 37304ec..5b9f0aa 100644 --- a/routes/institutions.js +++ b/routes/institutions.js @@ -1,9 +1,10 @@ const express = require('express'); const router = express.Router(); const institutionController = require('../controllers/institutionController'); -const authMiddleware = require('../middleware/authMiddleware') +const authMiddleware = require('../middleware/authMiddleware'); -router.get('/', authMiddleware, institutionController.getAllInstitutions); +router.get('/', institutionController.getAllInstitutions); +router.get('/:id', institutionController.getInstitutionById); // Neuer Endpunkt router.post('/', authMiddleware, institutionController.createInstitution); router.put('/:id', authMiddleware, institutionController.updateInstitution); router.delete('/:id', authMiddleware, institutionController.deleteInstitution); diff --git a/src/common/components/HeaderComponent.vue b/src/common/components/HeaderComponent.vue index 5ca11f3..9ce3159 100644 --- a/src/common/components/HeaderComponent.vue +++ b/src/common/components/HeaderComponent.vue @@ -24,10 +24,12 @@ export default { await this.loadMenuData(); this.$router.push({ path: '/' }); // Zurück zur Startseite oder eine andere Seite, um sicherzustellen, dass der Router neu geladen wird const routes = this.$store.state.menuData.map(item => { - return { - path: item.link, - component: () => import(`../components/${item.component}.vue`) - }; + if (item.component) { + return { + path: item.link, + component: () => import(`../components/${item.component}.vue`) + }; + } }); routes.forEach(route => router.addRoute(route)); // Neue Routen hinzufügen } diff --git a/src/components/AddContactDialog.vue b/src/components/AddContactDialog.vue index 0f72a5c..1d672be 100644 --- a/src/components/AddContactDialog.vue +++ b/src/components/AddContactDialog.vue @@ -18,6 +18,11 @@ +
+ + +
{ @@ -110,16 +119,18 @@ export default { selectedContact.value = null; selectedEventTypes.value = []; selectedPlaces.value = []; + selectedPositions.value = []; } else if (selectedTypes.value.some(type => type.id === 'specific')) { selectedTypes.value = [{ id: 'specific', caption: 'Eine Person' }]; selectedEventTypes.value = []; selectedPlaces.value = []; + selectedPositions.value = []; } else if (selectedTypes.value.some(type => type.id === 'places')) { selectedContact.value = null; - selectedEventTypes.value = []; } else if (selectedTypes.value.some(type => type.id === 'types')) { selectedContact.value = null; - selectedPlaces.value = []; + } else if (selectedPositions.value.some(type => type.id === 'position')) { + selectedContact.value = null; } }; @@ -132,8 +143,9 @@ export default { } else if (selectedTypes.value.some(type => type.id === 'specific') && selectedContact.value) { selection['id'] = selectedContact.value.id; } else { - selection['types'] = selectedEventTypes.value.map((type) => type.id).join('|'); - selection['places'] = selectedPlaces.value.map((place) => place.id).join('|'); + selection['types'] = selectedEventTypes.value.map((type) => type.id); + selection['places'] = selectedPlaces.value.map((place) => place.id); + selection['positions'] = selectedPositions.value((postion) => postion.id); } const contact = { selection: selection, @@ -166,13 +178,21 @@ export default { const fetchPlaces = async () => { try { const response = await axios.get('/event-places'); - console.log(response); places.value = response.data; } catch (error) { console.error('Fehler beim Laden der Orte:', error); } }; + const fetchPositions = async () => { + try { + const response = await axios.get('/positions'); + positions.value = response.data; + } catch (error) { + console.error('Fehler beim Laden der Positionen:', error) + } + } + return { isOpen, contacts, @@ -190,6 +210,8 @@ export default { onTypeSelect, places, eventTypes, + positions, + selectedPositions, }; }, }; diff --git a/src/components/AddDownloadDialog.vue b/src/components/AddDownloadDialog.vue index f307206..c60c4a5 100644 --- a/src/components/AddDownloadDialog.vue +++ b/src/components/AddDownloadDialog.vue @@ -50,7 +50,8 @@ }, confirm() { if (this.selectedFile) { - this.$emit('confirm', this.selectedFile.hash); + console.log(this.selectedFile.hash); + this.$emit('confirm', { hash: this.selectedFile.hash }); this.closeDialog(); } else { alert('Bitte wählen Sie eine Datei aus.'); diff --git a/src/components/AddEventDialog.vue b/src/components/AddEventDialog.vue index ddecdeb..ba598be 100644 --- a/src/components/AddEventDialog.vue +++ b/src/components/AddEventDialog.vue @@ -102,23 +102,21 @@ export default { }; const confirmAddEventConfiguration = () => { - let configString = ''; - const displayString = Object.keys(displayOptions.value) - .filter(key => displayOptions.value[key]) - .join('|'); + const event = {}; + event.display = Object.keys(displayOptions.value) + .filter(key => displayOptions.value[key]); if (isHomepage.value) { - configString = `{{ events:id=home,display=${displayString} }}` + event.id = "home"; } else if (selectedTypes.value.includes('Alle')) { - configString = `{{ events:id=all,display=${displayString} }}`; + event.id = "all" } else if (selectedTypes.value.includes('Ein bestimmtes')) { - configString = `{{ events:id=${selectedEvent.value.id},display=${displayString} }}`; + event.id = selectedEvent.value.id; } else { - const placesString = selectedPlaces.value.map(place => place.id).join('|'); - const eventTypesString = selectedEventTypes.value.map(eventType => eventType.id).join('|'); - configString = `{{ events:${placesString ? `event-places=${placesString},` : ''}${eventTypesString ? `event-types=${eventTypesString},` : ''}display=${displayString} }}`; + event.types = selectedEventTypes.value.map(eventType => eventType.id); + event.places = selectedPlaces.value.map(place => place.id); } - emit('confirm', configString); + emit('confirm', '{{ events:' + JSON.stringify(event) + ' }}'); closeAddEventDialog(); }; diff --git a/src/components/AddImageDialog.vue b/src/components/AddImageDialog.vue index 753caa5..9476d09 100644 --- a/src/components/AddImageDialog.vue +++ b/src/components/AddImageDialog.vue @@ -42,7 +42,6 @@ export default { const confirmAddImageConfiguration = () => { if (selectedImage.value) { - console.log('->', selectImage.value); emit('confirm', `${selectedImage.value.id}`); } closeAddImageDialog(); diff --git a/src/components/AddInstitutionDialog.vue b/src/components/AddInstitutionDialog.vue new file mode 100644 index 0000000..08a35f2 --- /dev/null +++ b/src/components/AddInstitutionDialog.vue @@ -0,0 +1,154 @@ + + + + + + \ No newline at end of file diff --git a/src/components/ContactRender.vue b/src/components/ContactRender.vue index cad8d21..7ae5cdf 100644 --- a/src/components/ContactRender.vue +++ b/src/components/ContactRender.vue @@ -46,15 +46,11 @@ export default { }, async created() { try { - console.log('Initial config:', JSON.stringify(this.config)); this.displayOptions = this.config.display || []; - console.log('Display options:', this.displayOptions); const response = await axios.post('/contact-persons/filter', { config: JSON.stringify(this.config), }); this.contacts = response.data; - console.log('Fetched contacts:', JSON.stringify(this.contacts)); - console.log('Config style:', this.config.style); this.loading = false; } catch (error) { console.error('Error loading contacts:', error); diff --git a/src/components/DownloadLink.vue b/src/components/DownloadLink.vue index 503f86e..ceed6a7 100644 --- a/src/components/DownloadLink.vue +++ b/src/components/DownloadLink.vue @@ -1,5 +1,5 @@ + + + \ No newline at end of file diff --git a/src/components/RenderContentComponent.vue b/src/components/RenderContentComponent.vue index e581286..a971d8b 100644 --- a/src/components/RenderContentComponent.vue +++ b/src/components/RenderContentComponent.vue @@ -7,7 +7,9 @@ import { createApp, h, ref, watch } from 'vue'; import WorshipRender from './WorshipRender.vue'; import ImageRender from './ImageRender.vue'; import EventRender from './EventRender.vue'; -import ContactRender from './ContactRender.vue'; // Neue Komponente importieren +import ContactRender from './ContactRender.vue'; // Importiere die neue Komponente +import InstitutionRender from './InstitutionRender.vue'; // Importiere die neue Komponente +import DownloadLink from './DownloadLink.vue'; export default { name: 'RenderContentComponent', @@ -23,8 +25,10 @@ export default { const renderContent = (content) => { let result = renderWorship(content); result = renderImage(result); + result = renderDownload(result); result = renderEvent(result); - result = renderContact(result); // Neuer Filter + result = renderContact(result); + result = renderInstitution(result); return result; }; @@ -32,14 +36,13 @@ export default { const worshipsPattern = /{{ worshipslist:(.*?) }}/g; let result = content; result = result.replace(worshipsPattern, (match, config) => { - const props = parseConfig(config); const placeholderId = `worship-render-placeholder-${Math.random().toString(36).substr(2, 9)}`; setTimeout(() => { const placeholder = document.getElementById(placeholderId); if (placeholder) { - const app = createApp({ + const app = createApp({ render() { - return h(WorshipRender, props); + return h(WorshipRender, {config: JSON.parse(config) }); }, }); app.mount(placeholder); @@ -71,18 +74,39 @@ export default { return result; }; + const renderDownload = (content) => { + const downloadPattern = /{{ download:(.*?) }}/g; + let result = content; + result = result.replace(downloadPattern, (match, config) => { + const placeholderId = `image-render-placeholder-${Math.random().toString(36).substr(2, 9)}`; + setTimeout(() => { + const placeholder = document.getElementById(placeholderId); + if (placeholder) { + const app = createApp({ + render() { + return h(DownloadLink, { hash: config }); + }, + }); + app.mount(placeholder); + } + }, 0); + return ``; + }); + return result; + }; + const renderEvent = (content) => { const eventsPattern = /{{ events:(.*?) }}/g; let result = content; result = result.replace(eventsPattern, (match, config) => { - const props = parseConfig(config); const placeholderId = `event-render-placeholder-${Math.random().toString(36).substr(2, 9)}`; setTimeout(() => { const placeholder = document.getElementById(placeholderId); if (placeholder) { const app = createApp({ render() { - return h(EventRender, { id: props.id, config: props }); + console.log('RC', config) + return h(EventRender, {config: JSON.parse(config) }); }, }); app.mount(placeholder); @@ -97,7 +121,7 @@ export default { const contactPattern = /{{ contact:(.*?) }}/g; let result = content; result = result.replace(contactPattern, (match, config) => { - const props = JSON.parse(config); + const props = parseConfig(config); const placeholderId = `contact-render-placeholder-${Math.random().toString(36).substr(2, 9)}`; setTimeout(() => { const placeholder = document.getElementById(placeholderId); @@ -110,22 +134,42 @@ export default { app.mount(placeholder); } }, 0); - const tag = props.style === 'box' ? 'div' : 'span' - return `<${tag} id="${placeholderId}">`; + return `
`; + }); + return result; + }; + + const renderInstitution = (content) => { + const institutionPattern = /{{ institution:(.*?) }}/g; + let result = content; + result = result.replace(institutionPattern, (match, config) => { + const props = parseConfig(config); + const placeholderId = `institution-render-placeholder-${Math.random().toString(36).substr(2, 9)}`; + setTimeout(() => { + const placeholder = document.getElementById(placeholderId); + if (placeholder) { + const app = createApp({ + render() { + return h(InstitutionRender, { config: props }); + }, + }); + app.mount(placeholder); + } + }, 0); + return `
`; }); return result; }; const parseConfig = (configString) => { - const config = {}; - const configArray = configString.split(','); - configArray.forEach((item) => { - const [key, value] = item.split('='); - if (key && value !== undefined) { - config[key.trim()] = isNaN(value) ? value.trim() : Number(value); - } - }); - return config; + try { + const config = JSON.parse(configString); + return config; + } catch (error) { + console.error('Error parsing config:', error); + console.log(configString); + return {}; + } }; watch( diff --git a/src/components/WorshipDialog.vue b/src/components/WorshipDialog.vue index e59aa08..265de13 100644 --- a/src/components/WorshipDialog.vue +++ b/src/components/WorshipDialog.vue @@ -66,7 +66,7 @@ export default { }; const confirmWorshipConfiguration = () => { - const selectedLocationIds = selectedLocations.value.map(location => location.id).join('|'); + const selectedLocationIds = JSON.stringify(selectedLocations.value.map(location => location.id)); emit('confirm', selectedLocationIds); closeWorshipDialog(); }; diff --git a/src/components/WorshipRender.vue b/src/components/WorshipRender.vue index 7efd586..1534312 100644 --- a/src/components/WorshipRender.vue +++ b/src/components/WorshipRender.vue @@ -32,14 +32,10 @@ import { formatTime, formatDate } from '@/utils/strings'; export default { name: 'WorshipRender', props: { - location: { - type: Number, + config: { + type: Object, required: true }, - orderBy: { - type: String, - default: 'date ASC' - } }, data() { return { @@ -55,10 +51,7 @@ export default { async fetchWorships() { try { const response = await axios.get('/worships/filtered', { - params: { - location: this.location, - orderBy: this.orderBy - } + params: this.config }); this.worships = response.data; } catch (error) { diff --git a/src/content/ImageContent.vue b/src/content/ImageContent.vue index 0ca0ff2..294b4a8 100644 --- a/src/content/ImageContent.vue +++ b/src/content/ImageContent.vue @@ -5,7 +5,7 @@ \ No newline at end of file diff --git a/src/content/music/FlootChildrenContent.vue b/src/content/music/FlootChildrenContent.vue new file mode 100644 index 0000000..3b67dc9 --- /dev/null +++ b/src/content/music/FlootChildrenContent.vue @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/utils/fetchMenuData.js b/utils/fetchMenuData.js index 19e6380..a690f04 100644 --- a/utils/fetchMenuData.js +++ b/utils/fetchMenuData.js @@ -35,6 +35,7 @@ function buildMenuStructure(menuItems) { requiresAuth: item.requires_auth, order_id: item.order_id, pageTitle: item.page_title, + image: item.image, submenu: [] }; });