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.tsxreads schedule settings fromschedule-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.tsxfetches its own data fromGET /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.tsbuilds the main calendar feed with queries scoped tores.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.tsexposes/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.tsalready acceptscompanyIds, 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 acompanyIdsset against allowed companies and query with_companyId: { $in: companyIds }where appropriate. - The response should include
_companyIdon each returned calendar row so the frontend can label and group events correctly. That field already exists on the underlyingEvent,Inspection,Vacation,HistoricSlotsorSlots, andReoccuringCalendarEventmodels, but it is not surfaced in the current response projections. - Reuse the existing permission pattern from
src/routes/ccDashboard.tsrather than inventing a separate authorization model. - Decision needed: whether v1 should add a single merged calendar feed in
calendar.tsor keep separate per-company fetches and merge them in the client. src/routes/schedule.tsand/schedule/optimal-slotsare 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.tsxso workspace mode can request and render multi-company calendar data rather than relying onuser._companyIdonly. - Update
src/components/calendar/CalendarRow.tsxand 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.tsxshould 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.tsxcurrently redirects to/scheduleinstead 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-slotsto 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.tsxsrc/components/calendar/CalendarRow.tsxsrc/components/calendar/CalendarFilterPopover.tsxsrc/components/scheduling/SchedulingSlideOutSheet.tsxsrc/routes/calendar.tssrc/routes/schedule.tssrc/routes/scheduleSettings.tssrc/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.
Status: Planned
Log in to comment and vote
No comments yet
Be the first to share your thoughts.