Skip to content

Conversation

@hariombalhara
Copy link
Member

@hariombalhara hariombalhara commented Dec 30, 2025

What does this PR do?

Integrates the Booking History feature into the Bookings V3 design by adding an Info/History segmented control in the booking details sheet. This allows users to view booking audit logs directly within the booking details panel instead of navigating to a separate page.

Loom Demo

Key changes:

  • Added new SegmentedControl UI component to @calcom/ui
  • Added Info/History tabs in BookingDetailsSheet (gated by booking-audit feature flag)
  • Moved BookingLogsView to @calcom/features/booking-audit as BookingHistory
  • Added FeaturesRepository.getUserFeaturesStatus() method for efficient batch feature flag checks
  • Added BookingHistoryPage wrapper for standalone page context

Updates since last revision

  • Renamed useBiDirectionalSyncBetweenZustandAndNuqs to useBiDirectionalSyncBetweenStoreAndUrl to avoid using provider names in concrete implementations

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - internal feature flag gated functionality.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  1. Enable the booking-audit feature flag for a test user
  2. Navigate to Bookings page with Bookings V3 enabled
  3. Click on a booking to open the details sheet
  4. Verify the Info/History segmented control appears
  5. Click "History" tab and verify booking audit logs are displayed
  6. Verify the /booking/[uid]/logs page still works with the new BookingHistoryPage component

Without feature flag:

  • Verify the segmented control does NOT appear when booking-audit flag is disabled
  • Verify only the Info content is shown

Human Review Checklist

  • Verify SegmentedControl component renders correctly and is accessible
  • Verify feature flag gating works correctly (tabs hidden when booking-audit disabled)
  • Verify getUserFeaturesStatus handles edge cases (empty slugs array, missing features)
  • Verify the History tab correctly displays booking audit logs
  • Verify bi-directional sync between store and URL works correctly (active segment persists on page refresh)

@vercel
Copy link

vercel bot commented Dec 30, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Review Updated (UTC)
cal Ignored Ignored Jan 5, 2026 10:31am
cal-companion Ignored Ignored Preview Jan 5, 2026 10:31am
cal-eu Ignored Ignored Jan 5, 2026 10:31am

@github-actions
Copy link
Contributor

github-actions bot commented Dec 30, 2025

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

No release type found in pull request title "Integrate BookingHistory with Bookings V3 design". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

- Updated the booking page to retrieve user feature statuses for "bookings-v3" and "booking-audit".
- Modified BookingDetailsSheet and BookingListContainer components to accept and utilize the new bookingAuditEnabled prop.
- Adjusted the BookingHistory display logic to conditionally render based on the bookingAuditEnabled state.
- Refactored SegmentedControl to support generic types for better type safety.

This change improves the user experience by allowing conditional access to booking audit features based on user permissions.
@hariombalhara hariombalhara self-assigned this Jan 1, 2026
@hariombalhara hariombalhara marked this pull request as ready for review January 1, 2026 13:31
@hariombalhara hariombalhara requested review from a team as code owners January 1, 2026 13:31
@graphite-app graphite-app bot added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Jan 1, 2026
@graphite-app graphite-app bot requested a review from a team January 1, 2026 13:31
@devin-ai-integration devin-ai-integration bot changed the title Integrate BookingHistory with Bookings V3 design feat: integrate BookingHistory with Bookings V3 design Jan 1, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 14 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/ui/components/segmented-control/SegmentedControl.tsx">

<violation number="1" location="packages/ui/components/segmented-control/SegmentedControl.tsx:58">
P1: Hardcoded radio button `name` will cause conflicts when multiple SegmentedControl instances exist on the same page. Consider using React&#39;s `useId()` hook to generate a unique name per component instance.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/modules/bookings/components/BookingDetailsSheet.tsx">

<violation number="1" location="apps/web/modules/bookings/components/BookingDetailsSheet.tsx:102">
P1: When `activeSegment` is `null` (initial state or after closing sheet), neither the info nor history content will render because strict equality checks fail. The function should default to `&quot;info&quot;` when `activeSegment` is `null` to match the original behavior.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

…and store

- Removed local state management for active segment in BookingDetailsSheet and integrated Zustand store for better state synchronization.
- Introduced useActiveSegmentFromUrl hook to sync active segment with URL query parameters.
- Updated BookingDetailsSheet to handle derived active segment logic based on bookingAuditEnabled state.
- Adjusted SegmentedControl to ensure it defaults to "info" when activeSegment is null.

This refactor enhances the maintainability and responsiveness of the booking details component.
@hariombalhara hariombalhara force-pushed the integrate-history-bookings-v3 branch from 3f38cd7 to 6e38e44 Compare January 2, 2026 08:34
Comment on lines +99 to +102
if (!bookingAuditEnabled && activeSegment === "history") {
return "info";
}
return activeSegment ?? "info";
Copy link
Member Author

Choose a reason for hiding this comment

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

Ensures that if a state is invalid as per feature flag, it is not transitioned to.

Comment on lines -202 to -219
useEffect(() => {
const unsubscribe = store.subscribe((state) => {
const storeUid = state.selectedBookingUid;
if (storeUid !== selectedBookingUidFromUrl) {
setSelectedBookingUidToUrl(storeUid);
}
});

return unsubscribe;
}, [selectedBookingUidFromUrl, setSelectedBookingUidToUrl, store]);

// Sync URL → Store
useEffect(() => {
const currentStoreUid = store.getState().selectedBookingUid;
if (currentStoreUid !== selectedBookingUidFromUrl) {
store.getState().setSelectedBookingUid(selectedBookingUidFromUrl);
}
}, [selectedBookingUidFromUrl, store]);
Copy link
Member Author

@hariombalhara hariombalhara Jan 2, 2026

Choose a reason for hiding this comment

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

Moved to separate hook useBiDirectionalSyncBetweenZustandAndNuqs and fixed a race condition.

Also, added a TODO to avoid useEffect syncing entirely.

Comment on lines +56 to +63
type="radio"
id={inputId}
value={itemValue}
checked={isActive}
onChange={() => handleChange(itemValue)}
disabled={disabled}
className="sr-only"
aria-checked={isActive}
Copy link
Contributor

Choose a reason for hiding this comment

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

why are you using not using our components from @calcom/ui?

Copy link
Member Author

Choose a reason for hiding this comment

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

I did not see a component for this purpose in there. In Figma it was named SegementedControl, so I am using that only.

Could you confirm if it or similar one exists there?

Copy link
Contributor

Choose a reason for hiding this comment

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

There is a Radio component in packages/ui/components/radio/Radio.tsx. We can create more variant if we want the UI to be different

Copy link
Member Author

Choose a reason for hiding this comment

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

I think SegementedControl makes more sense. radix ui also has this https://www.radix-ui.com/themes/docs/components/segmented-control

volnei
volnei previously requested changes Jan 5, 2026
Copy link
Contributor

@volnei volnei left a comment

Choose a reason for hiding this comment

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

small comment, happy to approve when fixed 💯

@github-actions github-actions bot marked this pull request as draft January 5, 2026 10:16
…rectionalSyncBetweenStoreAndUrl

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
@hariombalhara hariombalhara requested a review from volnei January 5, 2026 10:34
@hariombalhara hariombalhara marked this pull request as ready for review January 5, 2026 10:34
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 16 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/web/modules/bookings/views/bookings-view.tsx">

<violation number="1" location="apps/web/modules/bookings/views/bookings-view.tsx:84">
P2: `bookingAuditEnabled` is passed to `BookingListContainer` but not to `BookingCalendarContainer`. Users viewing bookings from the calendar view won&#39;t see the Info/History segmented control even when the `booking-audit` feature flag is enabled. For consistency, `BookingCalendarContainer` should also receive and forward this prop to `BookingDetailsSheet`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@hariombalhara hariombalhara merged commit a7fd789 into main Jan 5, 2026
55 checks passed
@hariombalhara hariombalhara deleted the integrate-history-bookings-v3 branch January 5, 2026 10:51
Pallava-Joshi pushed a commit to Pallava-Joshi/cal.com that referenced this pull request Jan 7, 2026
* Integrate BookingHistory with Bookings V3 design

* Enhance booking features by integrating booking audit functionality

- Updated the booking page to retrieve user feature statuses for "bookings-v3" and "booking-audit".
- Modified BookingDetailsSheet and BookingListContainer components to accept and utilize the new bookingAuditEnabled prop.
- Adjusted the BookingHistory display logic to conditionally render based on the bookingAuditEnabled state.
- Refactored SegmentedControl to support generic types for better type safety.

This change improves the user experience by allowing conditional access to booking audit features based on user permissions.

* Refactor BookingDetailsSheet to manage active segment state with Zustand store

- Removed local state management for active segment in BookingDetailsSheet and integrated Zustand store for better state synchronization.
- Introduced useActiveSegmentFromUrl hook to sync active segment with URL query parameters.
- Updated BookingDetailsSheet to handle derived active segment logic based on bookingAuditEnabled state.
- Adjusted SegmentedControl to ensure it defaults to "info" when activeSegment is null.

This refactor enhances the maintainability and responsiveness of the booking details component.

* refactor: rename useBiDirectionalSyncBetweenZustandAndNuqs to useBiDirectionalSyncBetweenStoreAndUrl

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ready-for-e2e size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants