170 lines
5.4 KiB
JavaScript
170 lines
5.4 KiB
JavaScript
import CalendarEvent from '../models/community/calendar_event.js';
|
|
import User from '../models/community/user.js';
|
|
import { Op } from 'sequelize';
|
|
|
|
class CalendarService {
|
|
/**
|
|
* Get all calendar events for a user
|
|
* @param {string} hashedUserId - The user's hashed ID
|
|
* @param {object} options - Optional filters (startDate, endDate)
|
|
*/
|
|
async getEvents(hashedUserId, options = {}) {
|
|
const user = await User.findOne({ where: { hashedId: hashedUserId } });
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
|
|
const where = { userId: user.id };
|
|
|
|
// Filter by date range if provided
|
|
if (options.startDate || options.endDate) {
|
|
where[Op.or] = [];
|
|
|
|
if (options.startDate && options.endDate) {
|
|
// Events that overlap with the requested range
|
|
where[Op.or].push({
|
|
startDate: { [Op.between]: [options.startDate, options.endDate] }
|
|
});
|
|
where[Op.or].push({
|
|
endDate: { [Op.between]: [options.startDate, options.endDate] }
|
|
});
|
|
where[Op.or].push({
|
|
[Op.and]: [
|
|
{ startDate: { [Op.lte]: options.startDate } },
|
|
{ endDate: { [Op.gte]: options.endDate } }
|
|
]
|
|
});
|
|
} else if (options.startDate) {
|
|
where[Op.or].push({ startDate: { [Op.gte]: options.startDate } });
|
|
where[Op.or].push({ endDate: { [Op.gte]: options.startDate } });
|
|
} else if (options.endDate) {
|
|
where[Op.or].push({ startDate: { [Op.lte]: options.endDate } });
|
|
}
|
|
}
|
|
|
|
const events = await CalendarEvent.findAll({
|
|
where,
|
|
order: [['startDate', 'ASC'], ['startTime', 'ASC']]
|
|
});
|
|
|
|
return events.map(e => this.formatEvent(e));
|
|
}
|
|
|
|
/**
|
|
* Get a single event by ID
|
|
*/
|
|
async getEvent(hashedUserId, eventId) {
|
|
const user = await User.findOne({ where: { hashedId: hashedUserId } });
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
|
|
const event = await CalendarEvent.findOne({
|
|
where: { id: eventId, userId: user.id }
|
|
});
|
|
|
|
if (!event) {
|
|
throw new Error('Event not found');
|
|
}
|
|
|
|
return this.formatEvent(event);
|
|
}
|
|
|
|
/**
|
|
* Create a new calendar event
|
|
*/
|
|
async createEvent(hashedUserId, eventData) {
|
|
const user = await User.findOne({ where: { hashedId: hashedUserId } });
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
|
|
const event = await CalendarEvent.create({
|
|
userId: user.id,
|
|
title: eventData.title,
|
|
description: eventData.description || null,
|
|
categoryId: eventData.categoryId || 'personal',
|
|
startDate: eventData.startDate,
|
|
endDate: eventData.endDate || eventData.startDate,
|
|
startTime: eventData.allDay ? null : eventData.startTime,
|
|
endTime: eventData.allDay ? null : eventData.endTime,
|
|
allDay: eventData.allDay || false
|
|
});
|
|
|
|
return this.formatEvent(event);
|
|
}
|
|
|
|
/**
|
|
* Update an existing calendar event
|
|
*/
|
|
async updateEvent(hashedUserId, eventId, eventData) {
|
|
const user = await User.findOne({ where: { hashedId: hashedUserId } });
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
|
|
const event = await CalendarEvent.findOne({
|
|
where: { id: eventId, userId: user.id }
|
|
});
|
|
|
|
if (!event) {
|
|
throw new Error('Event not found');
|
|
}
|
|
|
|
await event.update({
|
|
title: eventData.title,
|
|
description: eventData.description || null,
|
|
categoryId: eventData.categoryId || 'personal',
|
|
startDate: eventData.startDate,
|
|
endDate: eventData.endDate || eventData.startDate,
|
|
startTime: eventData.allDay ? null : eventData.startTime,
|
|
endTime: eventData.allDay ? null : eventData.endTime,
|
|
allDay: eventData.allDay || false
|
|
});
|
|
|
|
return this.formatEvent(event);
|
|
}
|
|
|
|
/**
|
|
* Delete a calendar event
|
|
*/
|
|
async deleteEvent(hashedUserId, eventId) {
|
|
const user = await User.findOne({ where: { hashedId: hashedUserId } });
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
|
|
const event = await CalendarEvent.findOne({
|
|
where: { id: eventId, userId: user.id }
|
|
});
|
|
|
|
if (!event) {
|
|
throw new Error('Event not found');
|
|
}
|
|
|
|
await event.destroy();
|
|
return { success: true };
|
|
}
|
|
|
|
/**
|
|
* Format event for API response
|
|
*/
|
|
formatEvent(event) {
|
|
return {
|
|
id: event.id,
|
|
title: event.title,
|
|
description: event.description,
|
|
categoryId: event.categoryId,
|
|
startDate: event.startDate,
|
|
endDate: event.endDate,
|
|
startTime: event.startTime ? event.startTime.substring(0, 5) : null, // HH:MM format
|
|
endTime: event.endTime ? event.endTime.substring(0, 5) : null,
|
|
allDay: event.allDay,
|
|
createdAt: event.createdAt,
|
|
updatedAt: event.updatedAt
|
|
};
|
|
}
|
|
}
|
|
|
|
export default new CalendarService();
|