Add expiring one-off calendar events

Objective

  • Let users create one-off calendar events (stored as Mongo Event documents, with type either 'Event' or 'Block') that expire automatically after a chosen duration or time, so temporary holds and short-lived schedule changes do not have to be removed manually.
  • Keep behavior predictable for dispatch and calendar views that rely on calendar events for availability and time blocking.

Background

  • Operations teams use calendar events for move-up holds, busy / out-of-office style blocks, and other temporary schedule entries; today many of those entries persist until someone deletes them, which is easy to forget and clutters the calendar.
  • Recurring series already use a different model (ReoccuringCalendarEvent with optional endDate in attik-backend/src/routes/reoccurringCaledarEvents.ts and related normalization); this work is about single-instance items created through the normal event APIs, not replacing the recurring series model.
  • Scheduling holds (quotes / online flow) already send expiresInMinutes on created events in places like attik-frontend/src/components/scheduling/QuoteModal.tsx, attik-frontend/src/app/scheduler/utils/sendQuote.ts, and attik-frontend/src/util/functions/quote/manageWorkingHold.ts—that pattern is a product precedent for time-limited events, but the tools calendar add-event path is separate.
  • In the Monday kickoff, Chris called out that events may already have an expiration field and an existing TTL index, so the preferred implementation is likely to reuse that path rather than rebuild expiration logic from scratch.

Scope

Backend

  • attik-backend/src/models/eventSchema.ts already defines optional expiresInMinutes on the Event schema alongside type ('Event' | 'Block').
  • attik-backend/src/routes/event.ts documents expiresInMinutes on POST / and PATCH /event/:id and copies whitelisted keys from Event.schema.obj, so persistence and updates for that field are already wired for single-event create and patch.
  • POST /event/batch builds payloads from _inspectorIds, dates, name, description, and type only; if batch-created calendar events should also support expiry, that route is a separate touchpoint from single POST /event.
  • attik-backend/src/events/streamHandlers/eventStream.ts (and eventStreamDev.ts) on insert enqueue a BullMQ job on the events queue with action: 'remove', jobId workingEventRemover_${_id}, and delay expiresInMinutes * 60000 when expiresInMinutes is set; update adjusts the delayed job when expiresInMinutes changes. Inserts with expiry also call syncHoldEventWithSpectora for Spectora-integrated companies.
  • attik-backend/src/events/bullmq/eventWorker.ts processes action === 'remove' by Event.findByIdAndDelete, which in turn triggers the change stream delete path in eventStream.ts (including deleteHoldEventSpectora when applicable).
  • Decision needed: product rules when expiry is cleared on edit, when the row is non–Spectora-hold, whether expiry applies to both type values or only selected kinds, and any minimum/maximum duration.

Frontend

  • attik-frontend/src/app/tools/calendar/AddEventModel.tsx submits new items via POST event (single inspector) or POST event/batch (multiple inspectors); the create flow defaults type to Block for the common “add block” path but the same form supports calendar Event rows. There is no user-facing control today to set expiresInMinutes on those requests.
  • attik-frontend/src/util/types/serverTypeCollection/event.ts already types expiresInMinutes as an optional number on the Zod event shape.
  • Calendar rendering and interaction live under attik-frontend/src/components/calendar/ (e.g. CalendarEventWrapper.tsx); any visual indication of an expiring calendar event (optional) would align with how holds are communicated elsewhere.
  • Office vs inspector calendar entry points (attik-frontend/src/app/tools/calendar/office/page.tsx, MasterCalendar.tsx) should be checked so whichever surfaces use AddEventModel stay consistent.

Mobile

  • No mobile calendar event editor was identified in the initial audit; include only if product confirms mobile parity.

References

  • Milestone: Calendar Updates (project milestone on this work item).
  • Backend: attik-backend/src/models/eventSchema.ts, attik-backend/src/routes/event.ts, attik-backend/src/events/streamHandlers/eventStream.ts, attik-backend/src/events/bullmq/eventWorker.ts.
  • Frontend: attik-frontend/src/app/tools/calendar/AddEventModel.tsx, attik-frontend/src/util/types/serverTypeCollection/event.ts.
  • Prior art for timed events / holds: attik-frontend/src/components/scheduling/QuoteModal.tsx, attik-frontend/src/util/functions/quote/manageWorkingHold.ts.

Please authenticate to join the conversation.

Upvoters
Status

Completed

Board
🏠

Main App

Date

About 1 month ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.