Skip to content

[Cal.com] Major expansion: availability management, out of office, and View Bookings redesign#27133

Merged
raycastbot merged 72 commits intoraycast:mainfrom
andrewbenson:feat/cal-com-availability-management
Apr 14, 2026
Merged

[Cal.com] Major expansion: availability management, out of office, and View Bookings redesign#27133
raycastbot merged 72 commits intoraycast:mainfrom
andrewbenson:feat/cal-com-availability-management

Conversation

@andrewbenson
Copy link
Copy Markdown
Contributor

@andrewbenson andrewbenson commented Apr 13, 2026

Summary

This PR expands the Cal.com Share Meeting Links extension into a more general Cal.com workflow surface. It includes the v1 → v2 API migration (originally opened as #27118 — this PR supersedes it), plus three substantial new feature areas and a fix for a long-standing pagination bug in View Bookings.

Naming note for reviewers: the extension's name slug is unchanged (cal-com-share-meeting-links) so existing users keep their stored API key and cached state. The title is bumped from Cal.com - Share Meeting Links to just Cal.com since the scope no longer fits the original name. Open to feedback on whether to keep that title or pick something else.

Why one PR for all this

The features are intentionally cohesive: they share the same API layer (src/api/cal.com.ts), reuse the same useCachedPromise cache-namespace fix, follow the same forms/actions/optimistic-update patterns, and depend on common helpers in src/lib/. Splitting them into separate PRs would either force artificial dependencies or duplicate the shared infrastructure across reviews. The rebrand also only makes sense once the full feature set lands. Happy to split if reviewers prefer.

What's in this PR

1. v1 → v2 API migration (was #27118)

  • All API calls migrated from Cal.com v1 to v2 (v1 was permanently shut down on April 8, 2026)
  • Authentication switched from query parameter to Bearer token header
  • Required cal-api-version headers added per endpoint
  • Replaced unified booking status update with separate confirm/decline endpoints
  • Cancel booking switched from DELETE to POST with body
  • Adopted v2 field names (meetingUrl, location, lengthInMinutes, etc.)

2. New: Availability schedule management

A new top-level View Availability command:

  • List all of your schedules (default sorted to top)
  • Sectioned detail view: Working Hours (Mon–Sun), Date Overrides, Settings (timezone, default flag, name)
  • Edit working hours per day (up to 3 ranges with overlap validation)
  • Add / edit / delete date overrides (date picker + time range, or "Unavailable all day")
  • Edit timezone with a humanized, searchable IANA dropdown ((GMT-7) America/Los Angeles, searchable by city)
  • Rename schedule, set default, and a Cmd+Shift+T "Set to Device Timezone" action available on every relevant surface
  • Glance pane shows working hours by day, upcoming date overrides (with weekday context), and which event types use this schedule (as a TagList)
  • All cache mutations propagate across views via a hoisted-fetcher pattern (fixes a real "edit doesn't refresh parent" bug discovered during QA)

3. New: Out of Office

Two new commands: Out of Office (browse/manage) and Create Out of Office (top-level form with native Raycast draft support):

  • List current + upcoming OOO entries with reason-tinted icons matching cal.com's web emojis (🏝 vacation, 🛫 travel, 🤒 sick, 📅 public holiday, 🕒 unspecified)
  • Each row shows the date range, weekday range, and accessories for the redirect target (with circular avatar) and active state
  • Create / edit / delete entries with date range, reason enum, optional notes, and a searchable team-member redirect picker
  • Team-member dropdown shows circular 32px avatars (with Cal.com URL normalization) and supports search by name, email, or team
  • Self-filtered out of the redirect list; gracefully degrades when the user has no teammates or insufficient permission to list memberships
  • Native Raycast draft persistence on the standalone "Create Out of Office" command (auto-save + resume prompt + discard)
  • Quick links to the OOO and General Account settings pages on cal.com (the latter covers scheduled timezone change, which has no public API)

4. View Bookings — bug fix + redesign

The bug: useBookings() was calling GET /v2/bookings with no params, which defaults to take=100, skip=0 in the API's internal order — effectively the oldest 100 bookings. Users with longer histories never saw recent or upcoming bookings.

The fix + redesign:

  • Three section-specific hooks (Pending, Upcoming, Past, Cancelled) with the correct status + sortStart query params
  • Past bookings lazy-load on scroll via Raycast's useCachedPromise pagination (50 per page)
  • New layout: Pending Confirmation → Upcoming → Past (Cancelled hidden by default behind Cmd+H)
  • Cmd+Shift+A toggle: Show Only My Bookings (hosts include you) vs Show All Bookings (includes team bookings hosted by others); default is filtered to yours, with a filter-aware empty state
  • Safer destructive UX: Enter is now Open Booking in Browser, Cancel uses Ctrl+X, Accept Cmd+Y, Decline Cmd+Shift+X. The cancel-confirm flow is unchanged.
  • New Cmd+Shift+R "Request Reschedule" action on Pending and Upcoming bookings — pushes a form where the user enters a reason, confirms, and the extension calls POST /v2/bookings/{uid}/request-reschedule. Cal.com cancels the original booking and emails the attendee a link to pick a new time.
  • Booking URL fixed to use https://app.cal.com/bookings/upcoming?uid=... (the logged-in user view) instead of the public-facing https://cal.com/booking/...

Implementation notes

  • Multi-component caches share a stable function reference so useCachedPromise's namespace (derived from object_hash(fn)) doesn't partition data across components — see comments on fetchSchedules, fetchOOOEntries, and fetchPastBookingsPaginator
  • Type updates to CalEventType.scheduleId to enable the View Availability "Used by" linkage
  • src/lib/ now houses pure helpers per feature area (schedule.ts, ooo.ts, bookings.ts) — easily unit-testable later, no test framework added in this PR

Test plan

  • npx ray lint clean (one pre-existing title-casing warning on the new "Create Out of Office" command — the suggested "Create out of Office" reads oddly so left as-is; happy to change)
  • npx ray build -e dist clean across all 5 entry points (index, view-bookings, view-availability, out-of-office, create-out-of-office)
  • Manual QA against a real Cal.com account verified each feature end-to-end (including a team account with multiple teammates for the OOO redirect picker)

Breaking changes

None for end users. The name slug is unchanged so existing installs preserve their stored API key and useCachedState data. The useBookings() API helper is removed but it was internal only.

Open items / known limitations

  1. Scheduled timezone change has no public API. The Cmd+Shift+A action in the OOO command opens the relevant cal.com settings page as an escape hatch.
  2. Team-member listing for the OOO redirect picker uses /v2/teams + /v2/teams/{id}/memberships. Returns full membership lists for org owners (verified) and gracefully degrades to an empty dropdown for users without permission. Other listing endpoints might exist that work for non-admins — would appreciate Cal.com guidance.
  3. Title casing of the new command "Create Out of Office" — Raycast's lint suggests "Create out of Office" which feels wrong. Open to whatever reviewers prefer.

Cal.com permanently shut down API v1 on April 8, 2026, breaking this
extension completely (HTTP 410 on all requests). This migrates all
endpoints to v2.

Changes:
- Replace v1 query-param auth with v2 Bearer token auth
- Add required cal-api-version headers per endpoint family
- Update all types to match v2 response shapes
- Replace single PATCH booking update with separate confirm/decline endpoints
- Change cancel booking from DELETE to POST with request body
- Use v2 field names throughout (start/end, lengthInMinutes, meetingUrl, etc.)
- Remove "Pending" status option (no longer supported in v2)

Fixes #27030
For consistency with all other endpoints in the file.
- Remove cal-api-version from /me (not required per docs)
- Use correct version 2024-09-04 for private-links endpoint
@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: cal-com-share-meeting-links Issues related to the cal-com-share-meeting-links extension labels Apr 13, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

raycastbot commented Apr 13, 2026

Thank you for your contribution! 🎉

🔔 @eluce2 @peduarte @pernielsentikaer @AlexIsMaking @jfkisafk @runofthemillgeek you might want to have a look.

You can use this guide to learn how to check out the Pull Request locally in order to test it.

📋 Quick checkout commands
BRANCH="feat/cal-com-availability-management"
FORK_URL="https://github.com/andrewbenson/extensions.git"
EXTENSION_NAME="cal-com-share-meeting-links"
REPO_NAME="extensions"

git clone -n --depth=1 --filter=tree:0 -b $BRANCH $FORK_URL
cd $REPO_NAME
git sparse-checkout set --no-cone "extensions/$EXTENSION_NAME"
git checkout
cd "extensions/$EXTENSION_NAME"
npm install && npm run dev

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 13, 2026

Greptile Summary

This PR delivers a complete Cal.com API v1→v2 migration (v1 shut down April 8, 2026), three new commands (View Availability, Out of Office, Create Out of Office), and a meaningful fix to the View Bookings pagination bug that was hiding recent/upcoming bookings. The implementation is well-structured: hoisted fetcher references maintain correct useCachedPromise cache namespaces across components, optimistic updates are applied consistently with proper rollback on error, and the new src/lib/ helpers are cleanly separated and pure.

Two minor items to address before merge:

  • dayjs is listed in package.json dependencies but is not imported anywhere in src/ after the rewrite — remove it to satisfy the unused-dependency policy.
  • formatCalendarDate and formatWeekday in src/lib/ooo.ts pass undefined as the locale, so dates and weekday names render in the user's OS language rather than English. The rest of the extension (e.g. formatTimeZoneOffset) pins to "en-US" — these two helpers should do the same.

Confidence Score: 5/5

  • Safe to merge — all remaining findings are P2 style/cleanup items that do not affect functionality or data integrity.
  • The API migration is correct and well-tested against a real account. The pagination bug fix addresses a genuine data correctness issue (old users never saw recent bookings). Optimistic updates follow the right pattern with proper error rollback throughout. The only open items are an unused dayjs dependency and an inconsistent locale string in two OOO date-formatting helpers — neither blocks shipping.
  • No files require special attention beyond the two P2 comments on package.json and src/lib/ooo.ts.

Important Files Changed

Filename Overview
extensions/cal-com-share-meeting-links/src/api/cal.com.ts Complete v1→v2 API migration: unified axios instance with Bearer auth, per-endpoint cal-api-version headers, new typed interfaces for schedules/OOO/teams, paginated past bookings with hoisted stable function reference for cache-namespace correctness. Logic is sound.
extensions/cal-com-share-meeting-links/src/view-bookings.tsx Major redesign: four section-specific hooks (pending/upcoming/past/cancelled) replace the single broken useBookings; paginated past bookings; client-side "show only mine" filter with clear empty-state distinction; safer keyboard shortcuts for destructive actions. Well-structured.
extensions/cal-com-share-meeting-links/src/lib/ooo.ts New pure helpers for OOO date math, range formatting, and UTC-start/end conversion. Logic is correct; formatCalendarDate and formatWeekday use undefined locale (system locale) rather than the "en-US" used elsewhere in the extension, causing inconsistent display on non-English systems.
extensions/cal-com-share-meeting-links/src/lib/schedule.ts Pure helpers for schedule availability manipulation, override upsert/remove, time-slot constants, and timezone formatting. UTC-pinned date parsing prevents DST drift. formatTimeZoneOffset correctly pins locale to "en-US".
extensions/cal-com-share-meeting-links/src/view-availability.tsx New command: lists schedules with detail pane showing working hours, upcoming date overrides, and linked event types. Correct use of hoisted useSchedules for shared cache propagation. Toggle detail / set default / set timezone actions all use optimistic updates correctly.
extensions/cal-com-share-meeting-links/src/out-of-office.tsx New command: lists current + upcoming OOO entries with reason icons, redirect-target avatar, and Active badge. Error and empty states handled. Detail pane and create/edit/delete actions use optimistic updates correctly.
extensions/cal-com-share-meeting-links/src/components/edit-ooo.tsx Shared create/edit form for OOO entries. Draft support flag correctly restricted to top-level command. Optimistic create includes synthetic toUser from cached teammate list to avoid a stale avatar flash. Teammate filtering and graceful degradation handled.
extensions/cal-com-share-meeting-links/package.json Version bumps for @raycast/api and @raycast/utils; three new commands added. dayjs remains listed as a dependency but is not imported anywhere in src/ after the rewrite.
extensions/cal-com-share-meeting-links/src/components/schedule-detail.tsx Detail view for a single schedule: working hours per weekday, date overrides, and settings (timezone, default flag, name). All mutations use optimistic updates via the shared useSchedules mutate function. Clear-day and delete-override actions include confirmation guards.
extensions/cal-com-share-meeting-links/src/components/cancel-booking.tsx Updated to use bookingUid string and new CalBooking type; optimistic update now drops the booking from the list (for sectioned layout) rather than marking it cancelled in-place. onAfterCancel callback added for revalidating the Cancelled section.
extensions/cal-com-share-meeting-links/CHANGELOG.md Four new changelog entries, each using {PR_MERGE_DATE} placeholder, placed at the top in the expected format. Follows the required convention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/cal-com-share-meeting-links/src/lib/ooo.ts
Line: 743-749

Comment:
**Locale-sensitive date formatting uses system locale**

`formatCalendarDate` and `formatWeekday` pass `undefined` as the locale to `toLocaleDateString`, which resolves to the user's OS locale. On a system set to French or Japanese, OOO date ranges and weekday names will render in that language. Elsewhere in the extension (e.g. `formatTimeZoneOffset` in `schedule.ts`) the locale is pinned to `"en-US"` for consistency — apply the same here.

```suggestion
function formatCalendarDate(d: Date): string {
  return d.toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
}
```

```suggestion
function formatWeekday(d: Date): string {
  return d.toLocaleDateString("en-US", { weekday: "long" });
}
```

**Rule Used:** What: Do not implement custom localization logic i... ([source](https://app.greptile.com/review/custom-context?memory=78677f74-64f7-483b-b90d-9c33e2e049da))

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/cal-com-share-meeting-links/package.json
Line: 72-73

Comment:
**`dayjs` dependency is unused**

`dayjs` is listed in `dependencies` but is not imported anywhere under `src/` (verified via grep). The new code uses `moment` for formatting (`formatDateTime` / `formatTime`) and native `Date` APIs for everything else. Removing `dayjs` keeps the bundle lean and satisfies the requirement that every listed dependency is actually used.

```suggestion
    "axios": "^1.8.4",
    "moment": "^2.30.1"
```

**Rule Used:** What: Every dependency listed in package.json must... ([source](https://app.greptile.com/review/custom-context?memory=bffc60eb-f9f2-4219-b804-76e29e267d43))

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "Bump @raycast/api to ^1.104, @raycast/ut..." | Re-trigger Greptile

Comment thread extensions/cal-com-share-meeting-links/src/api/cal.com.ts
…O past filter; populate optimistic toUser on OOO create
@andrewbenson
Copy link
Copy Markdown
Contributor Author

andrewbenson commented Apr 13, 2026

Addressed all three findings in fb2b955:

  1. pop() in finally (5 forms) — fixed in edit-day-hours, edit-override, edit-timezone, rename-schedule, and edit-ooo's apply function. They now return after showFailureToast and only pop() on success, matching the handleDelete pattern. Users keep their input and can retry on error.

  2. OOO past-entry filter documented — added a comment on fetchOOOEntries explaining the intentional "current + upcoming only" scope and what to change if a "Show Past" toggle gets added later.

  3. Optimistic toUser on OOO create — the synthetic entry now looks up the selected teammate from useTeammates() and embeds the matching toUser object so the avatar/name renders immediately, not just after the API responds.

Copy link
Copy Markdown
Collaborator

@pernielsentikaer pernielsentikaer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi 👋

Thanks for your contribution 💪

I have now tested your extension, and I have some feedback ready for you:

  • Outdated deps — @raycast/api ^1.79.1 (should be ^1.100+) and @raycast/utils ^1.16.1 (should be ^2.x). These need bumping.

  • Both moment and dayjs in dependencies — the existing code uses moment, the new code uses dayjs. Would be cleaner to pick one, but not blocking.

  • No .prettierrc — standard Raycast prettier config is missing.

I'm looking forward to testing this extension again 🔥

Feel free to contact me here or at Slack if you have any questions.


I converted this PR into a draft until it's ready for the review, please press the button Ready for review when it's ready and we'll have a look 😊

@pernielsentikaer pernielsentikaer marked this pull request as draft April 14, 2026 10:26
@pernielsentikaer pernielsentikaer self-assigned this Apr 14, 2026
@andrewbenson
Copy link
Copy Markdown
Contributor Author

@pernielsentikaer Thanks for the quick feedback!

Outdated deps — fixed in c2ceef021:

  • @raycast/api bumped from ^1.79.1 → ^1.104.12
  • @raycast/utils bumped from ^1.16.1 → ^2.2.3
  • @types/react pinned to 19.0.10 to match the version bundled inside @raycast/api
  • Build passes clean across all 5 entry points.

moment + dayjs — acknowledged. Both are inherited from the original extension's code. Happy to consolidate in a follow-up, leaving as-is for now since it's not blocking.

.prettierrc — it's actually already tracked in the repo (since the original extension, commit 601a6e8ab):

{
    "printWidth": 120,
    "singleQuote": false
  }

Let me know if you'd like a different config — happy to adjust.

I've marked the PR as ready for review but please let me know if there's any additional feedback!

@andrewbenson andrewbenson marked this pull request as ready for review April 14, 2026 10:48
Copy link
Copy Markdown
Collaborator

@pernielsentikaer pernielsentikaer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, approved 🔥

@raycastbot raycastbot merged commit 1faac63 into raycast:main Apr 14, 2026
2 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

Published to the Raycast Store:
https://raycast.com/cal/cal-com-share-meeting-links

@raycastbot
Copy link
Copy Markdown
Collaborator

🎉 🎉 🎉

Such a great contribution deserves a reward, but unfortunately we couldn't find your Raycast account based on your GitHub username (@andrewbenson).

Please link your GitHub account to your Raycast account to receive your credits and soon be able to exchange them for some swag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extension: cal-com-share-meeting-links Issues related to the cal-com-share-meeting-links extension extension fix / improvement Label for PRs with extension's fix improvements platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants