On this page
What changed, preciselyHow to test the fixWhere the edges areA known, unfixed gap to probeFor Quality
What changed, precisely
Three defensive guards against branchData (and branchData.branchDetails) being undefined at the moment it's read:
getStartAndEndTimes()— shared helper, mobile package, used by both
platforms.
CheckRepeatTimesAvailabilityButton— web, the repeat-appointment
"Available Slots" button.
MonthlyCalendar— web, the month-view date picker, plus a missing
branchData dependency in a useMemo.
See The three guards, in detail for exact file:line references and code.
How to test the fix
The trigger condition is: the BRANCH_DETAILS query for the currently selected branch has not yet resolved. In practice, the most reliable way to reproduce this in a test environment:
- Log in to a company with more than one branch.
- Throttle the network (browser devtools → Network → Slow 3G, or similar)
to widen the loading window.
- Switch to a branch you have not opened yet this session (a fresh
selectedBranch value Apollo hasn't cached).
- Immediately — before the page settles — do each of the following, one
test pass per item:
- Open Create New Appointment.
- Click the calendar icon next to Day (month view).
- Toggle Repeat, fill in times/days, click Available Slots.
Expected (post-fix): no crash in any case. The month view may briefly show nothing (empty grid) until data loads, then populate. The repeat form and its Available Slots modal should work once you're able to interact with them (fields depending on branch hours default to "open all day" until the real hours load, then correct themselves).
Regression signal: an uncaught exception / blank page in any of the three flows above, specifically right after a branch switch.
Where the edges are
- Race, not determinism: the bug (and therefore the fix's efficacy) is
timing-dependent. A fast network or a warm Apollo cache may never expose the original crash at all — that's expected, not a sign the fix isn't needed. Throttling is the reliable way to force the window open.
- First branch visit vs. revisit: only the first visit to a given
branch in a session round-trips to the network (fetchPolicy: 'cache-first'). Revisiting an already-loaded branch will never hit this path — don't waste test cycles there.
- Mobile app: the shared helper (
calendarHelpers.js) is also used by
the mobile app's AvailableSlotsScreen and MonthlyCalendarScreen. This PR's mobile-side fix is in the shared helper only — worth a pass on the mobile app's equivalent screens (branch switch → immediately open repeat-availability / month view) to confirm the same fix covers them there too.
A known, unfixed gap to probe
getAvailableSlots and isSlotAvailable (same calendarHelpers.js, not touched by this PR) still assume branchData.branchDetails exists with no guard. CheckRepeatTimesAvailabilityButton calls them once its Available Slots modal is rendering results, using a parsedBranchData that this PR made fall back to {} (rather than crash) if branchData was still missing at render time. If branchData still hasn't resolved by the time those results render — a narrower window nested inside the one this PR fixes — expect a crash on {}.branchDetails.openDays / {}.branchDetails.breaks.
To try to hit it: throttle network further, and specifically try to get the DATE_RANGE_APPOINTMENTS query (triggered by clicking Available Slots) to resolve before BRANCH_DETAILS does — e.g., by switching branches, then clicking Available Slots as early as possible, before the branch-details network request would typically complete. If you can reproduce a crash this way, it's real and worth filing as a separate follow-up — see The three guards, in detail for the exact lines involved.