refactor: remove redundant isRecurring property, use recurrenceRule instead

isRecurring was redundant since recurrenceRule as truthy/falsy check suffices.
Removed from shared CalendarEvent type, Mongoose virtual, and all usages.
This commit is contained in:
2026-02-07 16:16:35 +01:00
parent 1092ff2648
commit 81221d8b70
6 changed files with 10 additions and 20 deletions

View File

@@ -203,7 +203,7 @@ const Calendar = () => {
const occurrenceDate = getDateKey(new Date(event.occurrenceStart)); const occurrenceDate = getDateKey(new Date(event.occurrenceStart));
try { try {
if (event.isRecurring) { if (event.recurrenceRule) {
// Recurring event: use mode and occurrenceDate // Recurring event: use mode and occurrenceDate
await EventService.delete(event.id, mode, occurrenceDate); await EventService.delete(event.id, mode, occurrenceDate);
// Reload events to reflect changes // Reload events to reflect changes
@@ -260,7 +260,7 @@ const Calendar = () => {
<DeleteEventModal <DeleteEventModal
visible={deleteModalVisible} visible={deleteModalVisible}
eventTitle={eventToDelete?.title || ""} eventTitle={eventToDelete?.title || ""}
isRecurring={eventToDelete?.isRecurring || false} isRecurring={!!eventToDelete?.recurrenceRule}
onConfirm={handleDeleteConfirm} onConfirm={handleDeleteConfirm}
onCancel={handleDeleteCancel} onCancel={handleDeleteCancel}
/> />

View File

@@ -19,7 +19,7 @@ export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
startTime={event.occurrenceStart} startTime={event.occurrenceStart}
endTime={event.occurrenceEnd} endTime={event.occurrenceEnd}
description={event.description} description={event.description}
isRecurring={event.isRecurring} isRecurring={!!event.recurrenceRule}
> >
{/* Action buttons - TouchableOpacity with delayPressIn allows ScrollView to detect scroll gestures */} {/* Action buttons - TouchableOpacity with delayPressIn allows ScrollView to detect scroll gestures */}
<View className="flex-row justify-end mt-3 gap-3"> <View className="flex-row justify-end mt-3 gap-3">

View File

@@ -2,22 +2,18 @@ import mongoose, { Schema, Document, Model } from "mongoose";
import { CalendarEvent } from "@calchat/shared"; import { CalendarEvent } from "@calchat/shared";
import { IdVirtual } from "./types"; import { IdVirtual } from "./types";
interface EventVirtuals extends IdVirtual {
isRecurring: boolean;
}
export interface EventDocument export interface EventDocument
extends Omit<CalendarEvent, "id" | "isRecurring">, extends Omit<CalendarEvent, "id">,
Document { Document {
toJSON(): CalendarEvent; toJSON(): CalendarEvent;
} }
const EventSchema = new Schema< const EventSchema = new Schema<
EventDocument, EventDocument,
Model<EventDocument, {}, {}, EventVirtuals>, Model<EventDocument, {}, {}, IdVirtual>,
{}, {},
{}, {},
EventVirtuals IdVirtual
>( >(
{ {
userId: { userId: {
@@ -61,11 +57,6 @@ const EventSchema = new Schema<
return this._id.toString(); return this._id.toString();
}, },
}, },
isRecurring: {
get() {
return !!this.recurrenceRule;
},
},
}, },
toJSON: { toJSON: {
virtuals: true, virtuals: true,

View File

@@ -37,8 +37,8 @@ export class EventService {
const allEvents = await this.eventRepo.findByUserId(userId); const allEvents = await this.eventRepo.findByUserId(userId);
// Separate recurring and non-recurring events // Separate recurring and non-recurring events
const recurringEvents = allEvents.filter((e) => e.isRecurring); const recurringEvents = allEvents.filter((e) => e.recurrenceRule);
const nonRecurringEvents = allEvents.filter((e) => !e.isRecurring); const nonRecurringEvents = allEvents.filter((e) => !e.recurrenceRule);
// Expand all events (recurring get multiple instances, non-recurring stay as-is) // Expand all events (recurring get multiple instances, non-recurring stay as-is)
const expanded = expandRecurringEvents( const expanded = expandRecurringEvents(
@@ -90,7 +90,7 @@ export class EventService {
} }
// For non-recurring events, always delete completely // For non-recurring events, always delete completely
if (!event.isRecurring || !event.recurrenceRule) { if (!event.recurrenceRule) {
await this.eventRepo.delete(id); await this.eventRepo.delete(id);
return null; return null;
} }

View File

@@ -48,7 +48,7 @@ export function expandRecurringEvents(
// to find events that start before rangeStart but extend into the range // to find events that start before rangeStart but extend into the range
const adjustedRangeStart = new Date(rangeStart.getTime() - duration); const adjustedRangeStart = new Date(rangeStart.getTime() - duration);
if (!event.isRecurring || !event.recurrenceRule) { if (!event.recurrenceRule) {
// Non-recurring event: add if it overlaps with the range // Non-recurring event: add if it overlaps with the range
if (endTime >= rangeStart && startTime <= rangeEnd) { if (endTime >= rangeStart && startTime <= rangeEnd) {
expanded.push({ expanded.push({

View File

@@ -6,7 +6,6 @@ export interface CalendarEvent {
startTime: Date; startTime: Date;
endTime: Date; endTime: Date;
note?: string; note?: string;
isRecurring?: boolean;
recurrenceRule?: string; recurrenceRule?: string;
exceptionDates?: string[]; // ISO date strings (YYYY-MM-DD) for excluded occurrences exceptionDates?: string[]; // ISO date strings (YYYY-MM-DD) for excluded occurrences
createdAt?: Date; createdAt?: Date;