add calendarview event creation

This commit is contained in:
Schneider Roland
2025-11-23 22:26:16 +01:00
parent 008b644bb1
commit 6b975dadac
24 changed files with 583 additions and 31 deletions

View File

@@ -6,10 +6,17 @@ import { RecurrenceRule } from '../entity/recurrence-rule.entity';
import { EventException } from '../entity/event-exception.entity';
import { Event } from '../entity/event.entity';
import { Booking } from '../entity/booking.entity';
import { EventType } from '../entity/event-type.entity';
@Module({
imports: [
TypeOrmModule.forFeature([RecurrenceRule, EventException, Event, Booking]),
TypeOrmModule.forFeature([
RecurrenceRule,
EventException,
Event,
Booking,
EventType,
]),
],
controllers: [CalendarController],
providers: [CalendarService],

View File

@@ -15,6 +15,7 @@ import { CreateExceptionDto } from './dto/create-exception.dto';
import { Booking } from '../entity/booking.entity';
import { CancelBookingDto } from './dto/cancel-booking.dto';
import { CreateBookingDto } from './dto/create-booking.dto';
import { EventType } from '../entity/event-type.entity';
// --- Type-Safe Maps ---
const frequencyMap: Record<string, RRule.Frequency> = {
@@ -60,6 +61,8 @@ export class CalendarService {
private readonly dataSource: DataSource,
@InjectRepository(Event)
private readonly eventRepository: Repository<Event>,
@InjectRepository(EventType)
private readonly eventTypeRepository: Repository<EventType>,
@InjectRepository(RecurrenceRule)
private readonly recurrenceRuleRepository: Repository<RecurrenceRule>,
@InjectRepository(EventException)
@@ -196,9 +199,37 @@ export class CalendarService {
// --- Other service methods (createEvent, etc.) remain unchanged ---
async createEvent(createEventDto: CreateEventDto): Promise<Event> {
console.info('createEvent', createEventDto);
const { recurrenceRule, ...eventData } = createEventDto;
const event = this.eventRepository.create(eventData);
const newEvent: Omit<
Event,
'id' | 'bookings' | 'exceptions' | 'recurrenceRule'
> = {
...eventData,
createdAt: new Date(),
updatedAt: new Date(),
timezone: 'Europe/Budapest',
eventType: undefined,
isRecurring: recurrenceRule ? true : false,
};
// check if event type exists
if (eventData.eventTypeId) {
console.info('eventTypeId found');
const eventType = await this.eventTypeRepository.findOneBy({
id: eventData.eventTypeId,
});
if (!eventType) {
throw new BadRequestException(
{},
'Event type not found ' + eventData.eventTypeId,
);
}
newEvent.eventType = eventType;
}
const event = this.eventRepository.create(newEvent);
const savedEvent = await this.eventRepository.save(event);
if (event.isRecurring && recurrenceRule) {

View File

@@ -55,9 +55,9 @@ export class CreateEventDto {
@Type(() => Date)
endTime: Date;
@IsNotEmpty()
@IsString()
timezone: string; // e.g., 'Europe/Berlin'
// @IsNotEmpty()
// @IsString()
// timezone: string; // e.g., 'Europe/Berlin'
@IsOptional()
@IsInt()
@@ -71,4 +71,4 @@ export class CreateEventDto {
@ValidateNested()
@Type(() => RecurrenceRuleDto)
recurrenceRule?: RecurrenceRuleDto;
}
}

View File

@@ -23,7 +23,7 @@ export class Event {
title: string;
@Column({ name: 'description', type: 'text', nullable: true })
description: string;
description?: string;
@Column({ name: 'start_time', type: 'timestamptz' })
startTime: Date;
@@ -45,15 +45,15 @@ export class Event {
// --- Relationships ---
@Column({ name: 'event_type_id', type: 'bigint', nullable: true })
eventTypeId: number;
// @Column({ name: 'event_type_id', type: 'bigint', nullable: true })
// eventTypeId: number;
@ManyToOne(() => EventType, (eventType) => eventType.events, {
nullable: true,
onDelete: 'SET NULL', // As requested for optional relationship
})
@JoinColumn({ name: 'event_type_id' })
eventType: EventType;
eventType?: EventType;
@OneToOne(() => RecurrenceRule, (rule) => rule.event, {
cascade: true, // Automatically save/update recurrence rule when event is saved

View File

@@ -26,6 +26,7 @@ async function bootstrap() {
transformOptions: {
enableImplicitConversion: true, // Allows class-transformer to convert string primitives to their target types
},
enableDebugMessages: true,
}),
);