Skip to content

fix(companion): event type links for org user#32

Open
tomerqodo wants to merge 7 commits intocoderabbit_full_base_fixcompanion_event_type_links_for_org_user_pr5from
coderabbit_full_head_fixcompanion_event_type_links_for_org_user_pr5
Open

fix(companion): event type links for org user#32
tomerqodo wants to merge 7 commits intocoderabbit_full_base_fixcompanion_event_type_links_for_org_user_pr5from
coderabbit_full_head_fixcompanion_event_type_links_for_org_user_pr5

Conversation

@tomerqodo
Copy link

@tomerqodo tomerqodo commented Jan 29, 2026

Benchmark PR from agentic-review-benchmarks#5

Summary by CodeRabbit

Release Notes

  • New Features

    • Added booking URL support to event type links and integrations throughout the app.
  • Style

    • Updated UI element colors from blue to black for filters, dropdowns, and icons.
    • Removed bottom border from profile header.
    • Improved layout alignment in filter and settings components for better visual consistency.

✏️ Tip: You can customize this high-level summary in your review settings.

dhairyashiil and others added 7 commits January 25, 2026 12:01
Addresses Cubic AI review feedback (confidence 9/10): The username was
hardcoded to 'username' but still used by BasicsTab as a fallback for
URL display when bookingUrl is unavailable. This restores the useEffect
that fetches the actual username from CalComAPIService.getUsername().

Co-Authored-By: unknown <>
@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

Walkthrough

This pull request integrates an optional bookingUrl field throughout the application to replace hardcoded URL construction logic with direct API values. Multiple UI color tokens are updated from blue to black, and layout alignment adjustments are made in form components. The CalComAPIService removes buildEventTypeLink and exposes getUsername, while event type handlers across web, iOS, and extension entry points now prefer bookingUrl with fallback to legacy URL construction.

Changes

Cohort / File(s) Summary
Color & Visual Updates
companion/app/(tabs)/(availability)/availability-detail.tsx, companion/app/(tabs)/(bookings)/index.ios.tsx, companion/app/(tabs)/(bookings)/index.tsx, companion/app/profile-sheet.ios.tsx, companion/app/profile-sheet.tsx
Icon, label, and header element colors changed from blue (#007AFF) to black (#000000); bottom border styling removed from profile headers.
Layout & Style Refinements
companion/components/event-type-detail/tabs/{AdvancedTab.tsx,BasicsTab.tsx,LimitsTab.tsx,RecurringTab.tsx}, companion/components/Header.tsx
Explicit flexDirection: "row" and alignItems: "center" added to row containers; justifyContent: "center" added to switch/control containers for vertical alignment.
Service Layer & Type Definitions
companion/services/calcom.ts, companion/services/types/event-types.types.ts
EventType interface adds optional bookingUrl?: string field; buildEventTypeLink removed from CalComAPIService; new getUsername() public method added with enhanced error handling.
Event Type Detail & Basics Tab
companion/app/(tabs)/(event-types)/event-type-detail.tsx, companion/components/event-type-detail/tabs/BasicsTab.tsx
New bookingUrl state and prop added; handlePreview and handleCopyLink now require and use bookingUrl directly; new getDisplayUrl helper parses booking URL to derive display format fallback.
Event Type Listing & List Item Components
companion/components/event-type-list-item/{EventTypeListItem.tsx,EventTypeListItem.ios.tsx,EventTypeListItemParts.tsx}
bookingUrl prop added and passed through component hierarchy; new getDisplayUrl helper function extracts domain/prefix from booking URL for display.
Event Type Index (Web & iOS)
companion/app/(tabs)/(event-types)/index.tsx, companion/app/(tabs)/(event-types)/index.ios.tsx
CalComAPIService usage removed in favor of direct eventType.bookingUrl; handleCopyLink, _handleShare, and handlePreview now validate bookingUrl presence with fallback error alerts.
Extension & Content Integration
companion/extension/entrypoints/background/index.ts, companion/extension/entrypoints/content.ts, companion/extension/lib/linkedin.ts
Optional bookingUrl field added to event type shapes throughout content script, LinkedIn integration, and background logic; link construction prioritizes bookingUrl with fallback to username/slug-based URL building.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 URLs now bloom in their rightful place,
No more construction from slug and face,
BookingUrl flows through every thread,
Colors turn black from blue instead,
Layout aligned, our forms stand tall—
A booking refactor to catch them all! 🎯

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(companion): event type links for org user' directly aligns with the main changeset focus: refactoring event type link generation to use bookingUrl from the API instead of dynamically constructing links via CalComAPIService, with special handling for org users.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@companion/app/`(tabs)/(event-types)/event-type-detail.tsx:
- Around line 180-181: The bookingUrl state is initialized but never populated,
so preview/copy guards fail; update bookingUrl when the event type data is
loaded by calling setBookingUrl with the fetched URL (e.g.,
setBookingUrl(eventType.bookingUrl) or the appropriate property) inside the
data-fetch completion (such as the useEffect or the callback that handles
loadEventType/fetchEventType), and likewise apply the same setBookingUrl update
in the other occurrence mentioned (lines 948-962) so the bookingUrl state
reflects API data and the preview/copy logic can run.

In `@companion/extension/entrypoints/content.ts`:
- Around line 1125-1128: The Gmail copy path constructs bookingUrl from
eventType.users?.[0]?.username instead of using the canonical
eventType.bookingUrl; update the logic where bookingUrl is defined/used (the
bookingUrl variable in entrypoints/content.ts and the Gmail copy button handler)
to prefer eventType.bookingUrl when present and only fall back to
`https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`;
ensure the Gmail copy implementation uses that bookingUrl variable so the copied
link matches preview/insert behavior.

In `@companion/services/calcom.ts`:
- Around line 1654-1662: The catch in getUsername currently declares an unused
error and discards the original error; update the catch to capture the error
(e.g., catch (error)) and preserve its context when rethrowing or logging—for
example include the original error message or use the Error cause option when
throwing a new error from getUsername so you don't lose stack/message
information while removing the unused-variable warning.
🧹 Nitpick comments (3)
companion/components/event-type-detail/tabs/LimitsTab.tsx (1)

127-127: Minor redundancy with className styles.

The flexDirection: "row" and alignItems: "center" in the inline style duplicate the flex-row items-center Tailwind classes already applied. While this doesn't cause functional issues, it adds maintenance overhead. Consider keeping styles in one place.

♻️ Optional: Remove redundant inline styles
-        style={{ height: 44, flexDirection: "row", alignItems: "center" }}
+        style={{ height: 44 }}
companion/components/event-type-detail/tabs/AdvancedTab.tsx (2)

141-141: Same redundancy as LimitsTab.tsx.

The flexDirection: "row" and alignItems: "center" inline styles duplicate the flex-row items-center Tailwind classes.

♻️ Optional: Remove redundant inline styles
-        style={{ height, flexDirection: "row", alignItems: "center" }}
+        style={{ height }}

100-168: Consider extracting shared SettingRow component.

The SettingRow component in this file is nearly identical to the one in LimitsTab.tsx. Consider extracting it into a shared component to reduce duplication and ensure consistent behavior/styling across tabs.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca09b13 and 161a777.

📒 Files selected for processing (21)
  • companion/app/(tabs)/(availability)/availability-detail.tsx
  • companion/app/(tabs)/(bookings)/index.ios.tsx
  • companion/app/(tabs)/(bookings)/index.tsx
  • companion/app/(tabs)/(event-types)/event-type-detail.tsx
  • companion/app/(tabs)/(event-types)/index.ios.tsx
  • companion/app/(tabs)/(event-types)/index.tsx
  • companion/app/profile-sheet.ios.tsx
  • companion/app/profile-sheet.tsx
  • companion/components/Header.tsx
  • companion/components/event-type-detail/tabs/AdvancedTab.tsx
  • companion/components/event-type-detail/tabs/BasicsTab.tsx
  • companion/components/event-type-detail/tabs/LimitsTab.tsx
  • companion/components/event-type-detail/tabs/RecurringTab.tsx
  • companion/components/event-type-list-item/EventTypeListItem.ios.tsx
  • companion/components/event-type-list-item/EventTypeListItem.tsx
  • companion/components/event-type-list-item/EventTypeListItemParts.tsx
  • companion/extension/entrypoints/background/index.ts
  • companion/extension/entrypoints/content.ts
  • companion/extension/lib/linkedin.ts
  • companion/services/calcom.ts
  • companion/services/types/event-types.types.ts
🧰 Additional context used
🧬 Code graph analysis (6)
companion/components/Header.tsx (1)
companion/components/AppPressable.tsx (1)
  • AppPressable (48-104)
companion/components/event-type-detail/tabs/AdvancedTab.tsx (1)
packages/features/calendars/weeklyview/types/state.ts (1)
  • View (7-7)
companion/app/profile-sheet.ios.tsx (1)
packages/features/calendars/weeklyview/types/state.ts (1)
  • View (7-7)
companion/app/(tabs)/(event-types)/index.tsx (4)
companion/utils/alerts.ts (2)
  • showErrorAlert (36-51)
  • showSuccessAlert (67-74)
companion/services/calcom.ts (1)
  • EventType (138-138)
companion/services/types/event-types.types.ts (1)
  • EventType (173-284)
companion/utils/browser.ts (1)
  • openInAppBrowser (44-68)
companion/app/(tabs)/(event-types)/index.ios.tsx (4)
companion/utils/alerts.ts (2)
  • showErrorAlert (36-51)
  • showSuccessAlert (67-74)
companion/utils/index.ts (3)
  • showErrorAlert (14-14)
  • showSuccessAlert (14-14)
  • openInAppBrowser (16-16)
companion/services/types/event-types.types.ts (1)
  • EventType (173-284)
companion/hooks/index.ts (1)
  • EventType (41-41)
companion/app/(tabs)/(event-types)/event-type-detail.tsx (1)
companion/utils/index.ts (2)
  • showErrorAlert (14-14)
  • openInAppBrowser (16-16)
🪛 Biome (2.3.13)
companion/services/calcom.ts

[error] 1659-1659: This variable error is unused.

Unused variables are often the result of typos, incomplete refactors, or other sources of bugs.
Unsafe fix: If this is intentional, prepend error with an underscore.

(lint/correctness/noUnusedVariables)

companion/app/(tabs)/(event-types)/event-type-detail.tsx

[error] 180-180: This variable setBookingUrl is unused.

Unused variables are often the result of typos, incomplete refactors, or other sources of bugs.
Unsafe fix: If this is intentional, prepend setBookingUrl with an underscore.

(lint/correctness/noUnusedVariables)

🔇 Additional comments (33)
companion/extension/entrypoints/background/index.ts (1)

277-283: LGTM! Proper linter suppression with clear justification.

The biome-ignore comment appropriately documents why the any type assertion is necessary for Safari's Manifest V2 browserAction API, which isn't present in Chrome's type definitions. The cross-browser fallback pattern is correct.

companion/app/(tabs)/(availability)/availability-detail.tsx (1)

91-91: LGTM!

The icon color change from #007AFF to #000000 aligns with the broader UI consistency updates across the app.

companion/app/profile-sheet.ios.tsx (1)

150-150: LGTM!

The bottom border removal from the Profile Header container is consistent with the parallel change in profile-sheet.tsx, maintaining visual consistency across platforms.

companion/app/profile-sheet.tsx (1)

127-127: LGTM!

The border removal aligns with the corresponding change in profile-sheet.ios.tsx, ensuring consistent visual styling.

companion/app/(tabs)/(bookings)/index.ios.tsx (1)

65-65: LGTM!

Both filter menu label color changes from #007AFF to #000000 are consistent with the UI color token updates seen across the codebase.

Also applies to: 126-126

companion/components/event-type-detail/tabs/LimitsTab.tsx (1)

143-150: LGTM!

Adding justifyContent: "center" improves the vertical centering of the Switch component within its container.

companion/components/event-type-detail/tabs/AdvancedTab.tsx (1)

157-164: LGTM!

The justifyContent: "center" addition is consistent with LimitsTab.tsx changes.

companion/components/event-type-detail/tabs/RecurringTab.tsx (2)

91-93: Minor style redundancy, but LGTM.

The inline flexDirection: "row" and alignItems: "center" styles duplicate what's already applied via the flex-row items-center className. This redundancy is harmless and the layout fix achieves the intended alignment.


107-114: LGTM!

Adding justifyContent: "center" properly centers the Switch vertically within its container.

companion/components/Header.tsx (2)

106-114: Style redundancy noted, but consistent with PR-wide changes.

The inline flexDirection: "row" and alignItems: "center" styles duplicate the flex-row items-center className. This pattern appears across multiple files in this PR, suggesting a deliberate approach for explicit styling. The color token updates to black (#000000) for active states are applied consistently.


149-153: LGTM!

Color token updates from blue to black for active/selected states are applied consistently across all filter and sort options.

Also applies to: 171-175, 212-217, 234-239, 256-261, 292-297, 313-318, 336-341, 362-368, 388-393

companion/components/event-type-list-item/EventTypeListItem.tsx (1)

50-55: LGTM!

Correctly propagates bookingUrl to EventTypeTitle for proper URL display and linking, aligning with the PR's goal of using direct booking URLs when available.

companion/app/(tabs)/(bookings)/index.tsx (1)

63-81: LGTM!

The style updates and color token change to black (#000000) for the selected state are consistent with the broader PR-wide UI updates in Header.tsx.

companion/extension/lib/linkedin.ts (2)

118-119: LGTM!

Adding optional bookingUrl to the EventType interface aligns with the broader PR changes propagating booking URLs across the codebase.


667-672: LGTM!

The buildBookingUrl function now correctly prefers eventType.bookingUrl when available, falling back to the legacy URL construction. This supports organization users who may have different booking URL structures.

companion/services/types/event-types.types.ts (1)

282-283: Looks good — optional bookingUrl keeps backward compatibility.

companion/components/event-type-list-item/EventTypeListItem.ios.tsx (1)

99-104: Good wiring of bookingUrl into the title component.

companion/app/(tabs)/(event-types)/event-type-detail.tsx (2)

1273-1276: UI alignment tweaks look good.

Also applies to: 2340-2350


1430-1430: Prop wiring to BasicsTab is consistent.

companion/components/event-type-detail/tabs/BasicsTab.tsx (1)

40-41: Booking URL display + alignment tweaks look solid.

Also applies to: 205-210, 257-276

companion/app/(tabs)/(event-types)/index.ios.tsx (1)

1-3: Nice switch to bookingUrl with clear user-facing guards.

Also applies to: 31-31, 113-135, 234-241

companion/app/(tabs)/(event-types)/index.tsx (1)

40-40: bookingUrl flow updates and minor UI tweaks look good.

Also applies to: 135-157, 288-297, 452-452, 517-517

companion/components/event-type-list-item/EventTypeListItemParts.tsx (3)

7-22: Clean helper for display URL resolution.

Good encapsulation of the fallback logic and parsing behavior.


24-37: EventTypeTitle uses unified display URL.

Nice reuse of the helper to keep the title/link text consistent.


54-62: EventTypeLink aligned with bookingUrl display logic.

Consistent with the title rendering and avoids duplicate URL construction.

companion/extension/entrypoints/content.ts (8)

827-837: Booking URL added to Gmail event-type shape.

Good—this keeps the data model aligned with the new API field.

Also applies to: 868-879, 885-895


1081-1085: Preview button now prefers bookingUrl.

This matches the intended behavior and preserves fallback logic.


1291-1300: Insert link now prefers bookingUrl.

This aligns the inserted link with the API-provided URL.


1319-1327: Copy helper uses bookingUrl fallback.

Consistent with other link paths.


1576-1586: Booking URL added to LinkedIn event-type shape.

Good parity with Gmail data shape updates.

Also applies to: 1617-1628, 1633-1644


1829-1832: LinkedIn preview prefers bookingUrl.

Matches the new source-of-truth link behavior.


1871-1873: LinkedIn copy link prefers bookingUrl.

Consistent with preview/insert behavior.


2036-2044: LinkedIn insert link uses bookingUrl fallback.

Good alignment with the new URL sourcing.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +180 to 181
const [bookingUrl, setBookingUrl] = useState<string>("");
const [saving, setSaving] = useState(false);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Populate bookingUrl state or preview/copy will always error.
bookingUrl is initialized but never set from fetched data, so the new guards block preview/copy even when the API provides a URL. This also explains the unused setBookingUrl lint warning.

🐛 Proposed fix
 const applyEventTypeData = useCallback((eventType: EventType) => {
   setEventTypeData(eventType);
+  setBookingUrl(eventType.bookingUrl ?? "");
 
   // Load basic fields

Also applies to: 948-962

🧰 Tools
🪛 Biome (2.3.13)

[error] 180-180: This variable setBookingUrl is unused.

Unused variables are often the result of typos, incomplete refactors, or other sources of bugs.
Unsafe fix: If this is intentional, prepend setBookingUrl with an underscore.

(lint/correctness/noUnusedVariables)

🤖 Prompt for AI Agents
In `@companion/app/`(tabs)/(event-types)/event-type-detail.tsx around lines 180 -
181, The bookingUrl state is initialized but never populated, so preview/copy
guards fail; update bookingUrl when the event type data is loaded by calling
setBookingUrl with the fetched URL (e.g., setBookingUrl(eventType.bookingUrl) or
the appropriate property) inside the data-fetch completion (such as the
useEffect or the callback that handles loadEventType/fetchEventType), and
likewise apply the same setBookingUrl update in the other occurrence mentioned
(lines 948-962) so the bookingUrl state reflects API data and the preview/copy
logic can run.

Comment on lines +1125 to +1128
const bookingUrl =
`https://cal.com/${
eventType.users?.[0]?.username || "user"
}/${eventType.slug}`;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Copy link still ignores bookingUrl.

The Gmail copy button should mirror the preview/insert behavior and prefer eventType.bookingUrl. Otherwise org-user links remain wrong in this path.

🔧 Proposed fix
-    const bookingUrl =
-      `https://cal.com/${
-        eventType.users?.[0]?.username || "user"
-      }/${eventType.slug}`;
+    const bookingUrl =
+      eventType.bookingUrl ||
+      `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const bookingUrl =
`https://cal.com/${
eventType.users?.[0]?.username || "user"
}/${eventType.slug}`;
const bookingUrl =
eventType.bookingUrl ||
`https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`;
🤖 Prompt for AI Agents
In `@companion/extension/entrypoints/content.ts` around lines 1125 - 1128, The
Gmail copy path constructs bookingUrl from eventType.users?.[0]?.username
instead of using the canonical eventType.bookingUrl; update the logic where
bookingUrl is defined/used (the bookingUrl variable in entrypoints/content.ts
and the Gmail copy button handler) to prefer eventType.bookingUrl when present
and only fall back to `https://cal.com/${eventType.users?.[0]?.username ||
"user"}/${eventType.slug}`; ensure the Gmail copy implementation uses that
bookingUrl variable so the copied link matches preview/insert behavior.

Comment on lines +1654 to +1662
// Helper to get username
async function getUsername(): Promise<string> {
try {
const profile = await getUserProfile();
return profile.username;
} catch (error) {
throw new Error("Failed to get username");
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unused error variable and lost error context.

The static analysis correctly flags error as unused. Additionally, the original error details are discarded, which could make debugging harder. Consider preserving the error context.

🛠️ Proposed fix
 async function getUsername(): Promise<string> {
   try {
     const profile = await getUserProfile();
     return profile.username;
-  } catch (error) {
-    throw new Error("Failed to get username");
+  } catch (_error) {
+    const message = _error instanceof Error ? _error.message : String(_error);
+    throw new Error(`Failed to get username: ${message}`);
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Helper to get username
async function getUsername(): Promise<string> {
try {
const profile = await getUserProfile();
return profile.username;
} catch (error) {
throw new Error("Failed to get username");
}
}
// Helper to get username
async function getUsername(): Promise<string> {
try {
const profile = await getUserProfile();
return profile.username;
} catch (_error) {
const message = _error instanceof Error ? _error.message : String(_error);
throw new Error(`Failed to get username: ${message}`);
}
}
🧰 Tools
🪛 Biome (2.3.13)

[error] 1659-1659: This variable error is unused.

Unused variables are often the result of typos, incomplete refactors, or other sources of bugs.
Unsafe fix: If this is intentional, prepend error with an underscore.

(lint/correctness/noUnusedVariables)

🤖 Prompt for AI Agents
In `@companion/services/calcom.ts` around lines 1654 - 1662, The catch in
getUsername currently declares an unused error and discards the original error;
update the catch to capture the error (e.g., catch (error)) and preserve its
context when rethrowing or logging—for example include the original error
message or use the Error cause option when throwing a new error from getUsername
so you don't lose stack/message information while removing the unused-variable
warning.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants