Federated calendar view across workspace instances

Objective

  • Give coordinators a single calendar view across the companies in a selected workspace so they can compare busy time and capacity across brands without switching context.
  • Make every row and event clearly identify its source company while keeping view, create, and booking actions constrained by per-company permissions.
  • Support the real scheduling workflow where staff need to hold one brand's availability in mind while checking whether a sister brand can cover the same customer sooner.

Background

  • Office staff working across overlapping brands and territories need to compare calendars in real time, especially when one company cannot take a booking but another nearby company may have weekend or sooner availability.
  • The current workflow does not support keeping two company calendars visible in a durable way. Changing workspace context causes the other calendar tab to change as well, which breaks cross-brand comparison on two screens.
  • The practical need is to answer questions like: one brand cannot get there until Monday, but a sister brand may be able to take Saturday. That comparison needs to happen quickly enough to complete the booking while the slot is still available.
  • The current calendar implementation is single-company end to end. src/app/tools/calendar/MasterCalendar.tsx reads schedule settings from schedule-settings/${user._companyId} and renders one row per inspector from a flat inspector list, with no workspace-mode or multi-company data path.
  • src/components/calendar/CalendarRow.tsx fetches its own data from GET /calendar?employeeId=... and does not carry or render _companyId, company chips, or any other cross-company identifier in the row label or event UI.
  • src/routes/calendar.ts builds the main calendar feed with queries scoped to res.locals.company._id. The underlying models include _companyId, but the returned payload does not currently expose it on calendar rows, so the frontend cannot disambiguate source company from the existing response.
  • src/routes/schedule.ts exposes /schedule/optimal-slots, but that logic is also scoped to one company for inspectors, services, holidays, slots, inspections, events, and vacations.
  • Cross-company authorization patterns do exist elsewhere in the backend. src/routes/ccDashboard.ts already accepts companyIds, intersects them with permitted companies, and queries with _companyId: { $in: companyIds }. That is a relevant pattern for federated calendar reads.
  • When ATT-1714 ships cross-instance inspector blocks, federated calendar should consume those blocks in linked instances. The requirement for v1 coupling is still a decision needed.

Scope

Backend

  • Extend the calendar read path so a workspace-scoped request can return data for multiple permitted companies instead of only res.locals.company._id.
  • The most direct touchpoint is src/routes/calendar.ts, where the current aggregations for vacations, events, inspections, available slots, recurring calendar events, and related calendar data are all single-company. A federated version needs to validate a companyIds set against allowed companies and query with _companyId: { $in: companyIds } where appropriate.
  • The response should include _companyId on each returned calendar row so the frontend can label and group events correctly. That field already exists on the underlying Event, Inspection, Vacation, HistoricSlots or Slots, and ReoccuringCalendarEvent models, but it is not surfaced in the current response projections.
  • Reuse the existing permission pattern from src/routes/ccDashboard.ts rather than inventing a separate authorization model.
  • Decision needed: whether v1 should add a single merged calendar feed in calendar.ts or keep separate per-company fetches and merge them in the client.
  • src/routes/schedule.ts and /schedule/optimal-slots are relevant because they remain single-company today. Multi-company booking optimization is not required for v1, but any federated calendar read should avoid creating expectations that this endpoint can book across companies in one pass.

Frontend

  • Update src/app/tools/calendar/MasterCalendar.tsx so workspace mode can request and render multi-company calendar data rather than relying on user._companyId only.
  • Update src/components/calendar/CalendarRow.tsx and related event rendering components so rows and events visibly identify source company. The current row label supports inspector avatar and name only, and there is no company badge, chip, or company-aware filter in the calendar UI.
  • Add a clear disambiguation pattern for inspectors who appear in more than one company. Separate instance-specific inspector records may share a person name, so the row label should distinguish them with company context rather than name alone.
  • Evaluate whether src/components/calendar/CalendarFilterPopover.tsx should gain a company filter in addition to the existing team and service filters.
  • The current calendar page includes src/components/scheduling/SchedulingSlideOutSheet.tsx, but the create-slot flow is not wired through from calendar slot clicks. MasterCalendar.tsx currently redirects to /schedule instead of opening the slide-out, and the slide-out interface does not include any company-selection input.
  • Decision needed: whether creating from a federated calendar in v1 should force a target-company selection before entering scheduling, or whether create actions should stay routed into the existing single-company scheduling flow.

Out of scope

  • Rewriting /schedule/optimal-slots to find the best booking opportunity across multiple companies in one request.
  • Solving full cross-company booking creation and optimization beyond the read-side federated calendar experience.
  • Eliminating all duplicate inspector identity concerns across instances beyond the UI disambiguation needed to make rows understandable.

References

  • ATT-1714
  • src/app/tools/calendar/MasterCalendar.tsx
  • src/components/calendar/CalendarRow.tsx
  • src/components/calendar/CalendarFilterPopover.tsx
  • src/components/scheduling/SchedulingSlideOutSheet.tsx
  • src/routes/calendar.ts
  • src/routes/schedule.ts
  • src/routes/scheduleSettings.ts
  • src/routes/ccDashboard.ts

Additional Transcript Context

  • The immediate workflow pain is that schedulers may need to check availability in RJ and Sherwood for the same customer, but today they have to repeat the search and re-enter information when switching instances.
  • The desired end state is closer to a "search once" flow where staff can quickly tell which sister company has the next available slot.
  • The team also discussed linked inspector memberships, cross-instance blocking, and overflow inspector behavior as possible pieces of a longer-term solution.
  • In the short term, this is not considered mission critical for next week, but it is an important long-term workflow gap.
  • Chris is going to speak with Josh to get his thoughts on a long-term solution.

Please authenticate to join the conversation.

Upvoters
Status

Planned

Board
🏠

Main App

Date

17 days ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.