213 lines
6.4 KiB
JavaScript
213 lines
6.4 KiB
JavaScript
const { Event, Institution, EventPlace, ContactPerson, EventType, EventContactPerson, sequelize } = require('../models');
|
|
const { Op, fn, col, where: sequelizeWhere } = require('sequelize');
|
|
const { format, startOfDay } = require('date-fns');
|
|
|
|
function buildUpcomingWhere() {
|
|
// Compare on date-only level to avoid timezone/DATETIME offset issues.
|
|
const todayDate = format(startOfDay(new Date()), 'yyyy-MM-dd');
|
|
return {
|
|
[Op.or]: [
|
|
// Fixed-date events: only today or future.
|
|
sequelizeWhere(fn('DATE', col('date')), { [Op.gte]: todayDate }),
|
|
// Recurring/undated events: date is null (dayOfWeek may be set).
|
|
{ date: { [Op.eq]: null } },
|
|
],
|
|
};
|
|
}
|
|
|
|
const getAllEvents = async (req, res) => {
|
|
try {
|
|
const includePast = String(req.query?.includePast || '').toLowerCase();
|
|
const wantsPast = includePast === '1' || includePast === 'true' || includePast === 'yes';
|
|
|
|
const where = wantsPast
|
|
? undefined
|
|
: buildUpcomingWhere();
|
|
|
|
const events = await Event.findAll({
|
|
where,
|
|
include: [
|
|
{ model: Institution, as: 'institution' },
|
|
{ model: EventPlace, as: 'eventPlace' },
|
|
{ model: EventType, as: 'eventType' },
|
|
{ model: ContactPerson, as: 'contactPersons', through: { attributes: [] } }
|
|
],
|
|
order: [
|
|
['date', 'ASC'],
|
|
['time', 'ASC'],
|
|
['name', 'ASC'],
|
|
],
|
|
});
|
|
res.json(events);
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Failed to fetch events' });
|
|
console.error(error);
|
|
}
|
|
};
|
|
|
|
const filterEvents = async (req, res) => {
|
|
try {
|
|
const request = req.body;
|
|
const where = buildUpcomingWhere();
|
|
const order = [
|
|
['date', 'ASC'],
|
|
['time', 'ASC']
|
|
];
|
|
|
|
if (request.id === 'all') {
|
|
const events = await Event.findAll({
|
|
where,
|
|
include: [
|
|
{ model: Institution, as: 'institution' },
|
|
{ model: EventPlace, as: 'eventPlace' },
|
|
{ model: EventType, as: 'eventType' },
|
|
{ model: ContactPerson, as: 'contactPersons', through: { attributes: [] } }
|
|
],
|
|
order: order,
|
|
logging: console.log // Log the generated SQL query
|
|
});
|
|
return res.json({ events });
|
|
}
|
|
|
|
if (request.id === 'home') {
|
|
const events = await Event.findAll({
|
|
where: {
|
|
alsoOnHomepage: 1,
|
|
...buildUpcomingWhere(),
|
|
},
|
|
include: [
|
|
{ model: Institution, as: 'institution' },
|
|
{ model: EventPlace, as: 'eventPlace' },
|
|
{ model: EventType, as: 'eventType' },
|
|
{ model: ContactPerson, as: 'contactPersons', through: { attributes: [] } },
|
|
],
|
|
order: order,
|
|
});
|
|
return res.json({ events });
|
|
}
|
|
|
|
if (!request.id && !request.places && !request.types) {
|
|
return res.json({ events: [], places: [], types: [], contactPersons: [] });
|
|
}
|
|
|
|
if (request.id) {
|
|
where.id = request.id;
|
|
}
|
|
|
|
if (request.places && request.places.length > 0) {
|
|
where.event_place_id = {
|
|
[Op.in]: request.places.map(id => parseInt(id))
|
|
};
|
|
}
|
|
|
|
if (request.types && request.types.length > 0) {
|
|
where.eventTypeId = {
|
|
[Op.in]: request.types.map(id => parseInt(id))
|
|
};
|
|
}
|
|
|
|
const events = await Event.findAll({
|
|
where,
|
|
include: [
|
|
{ model: Institution, as: 'institution' },
|
|
{ model: EventPlace, as: 'eventPlace' },
|
|
{ model: EventType, as: 'eventType' },
|
|
{ model: ContactPerson, as: 'contactPersons', through: { attributes: [] } }
|
|
],
|
|
order: order,
|
|
});
|
|
const displayFields = request.display ? request.display : [];
|
|
|
|
const filteredEvents = events.map(event => {
|
|
const filteredEvent = { ...event.toJSON() };
|
|
|
|
if (!displayFields.includes('name')) delete filteredEvent.name;
|
|
if (!displayFields.includes('type')) delete filteredEvent.eventType;
|
|
if (!displayFields.includes('place')) delete filteredEvent.eventPlace;
|
|
if (!displayFields.includes('description')) delete filteredEvent.description;
|
|
if (!displayFields.includes('time')) delete filteredEvent.time;
|
|
if (!displayFields.includes('time')) delete filteredEvent.endTime;
|
|
if (!displayFields.includes('contactPerson')) delete filteredEvent.contactPersons;
|
|
if (!displayFields.includes('day')) delete filteredEvent.dayOfWeek;
|
|
if (!displayFields.includes('institution')) delete filteredEvent.institution;
|
|
|
|
return filteredEvent;
|
|
});
|
|
|
|
res.json({ events: filteredEvents });
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Failed to filter events' });
|
|
console.error(error);
|
|
}
|
|
};
|
|
|
|
const createEvent = async (req, res) => {
|
|
try {
|
|
const { contactPersonIds, ...eventData } = req.body;
|
|
eventData.alsoOnHomepage = eventData.alsoOnHomepage ?? 0;
|
|
const event = await Event.create(eventData);
|
|
if (contactPersonIds) {
|
|
await event.setContactPersons(contactPersonIds);
|
|
}
|
|
res.status(201).json(event);
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Failed to create event' });
|
|
console.error(error);
|
|
}
|
|
};
|
|
|
|
const updateEvent = async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { contactPersonIds, ...eventData } = req.body;
|
|
const event = await Event.findByPk(id);
|
|
if (!event) {
|
|
return res.status(404).json({ error: 'Event not found' });
|
|
}
|
|
await event.update(eventData);
|
|
if (contactPersonIds) {
|
|
await event.setContactPersons(contactPersonIds);
|
|
}
|
|
res.status(200).json(event);
|
|
} catch (error) {
|
|
res.status(500).json({ error: 'Failed to update event' });
|
|
console.error(error);
|
|
}
|
|
};
|
|
|
|
const deleteEvent = async (req, res) => {
|
|
const transaction = await sequelize.transaction();
|
|
try {
|
|
const { id } = req.params;
|
|
// Erst Zuordnungen in der Join-Tabelle löschen, damit FK-Constraints erfüllt sind.
|
|
await EventContactPerson.destroy({
|
|
where: { event_id: id },
|
|
transaction,
|
|
});
|
|
|
|
const deleted = await Event.destroy({
|
|
where: { id: id },
|
|
transaction,
|
|
});
|
|
if (deleted) {
|
|
await transaction.commit();
|
|
res.status(204).json();
|
|
} else {
|
|
await transaction.rollback();
|
|
res.status(404).json({ error: 'Event not found' });
|
|
}
|
|
} catch (error) {
|
|
await transaction.rollback();
|
|
res.status(500).json({ error: 'Failed to delete event' });
|
|
console.error(error);
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
getAllEvents,
|
|
createEvent,
|
|
updateEvent,
|
|
deleteEvent,
|
|
filterEvents
|
|
};
|