## What does this PR do?
Fixes footer text overlap in the Booking Details drawer where action buttons covered the last content items on smaller screens.
**Root cause:** `sm:-my-6` on `SheetFooter` applied both negative top and bottom margins. The negative top margin pulled the footer up into the body content area, causing the overlap.
**Fix:**
- Removed `-mb-4` and `sm:-my-6` from `SheetFooter`, keeping only horizontal negative margins (`-mx-4` / `sm:-mx-6`) for edge-to-edge stretch
- Added `pb-0` to `SheetContent` to remove bottom padding so the footer sits flush at the bottom on all breakpoints
<img width="1098" height="1362" alt="image" src="https://github.com/user-attachments/assets/0418df56-a432-4edf-8e5b-664a5e8c18ac" />
- Fixes #XXXX (GitHub issue number)
- Fixes CAL-XXXX (Linear issue number - should be visible at the bottom of the GitHub issue description)
## Visual Demo (For contributors especially)
#### Image Demo (if applicable):
See screenshot above showing the overlap bug. The footer actions ("..." button) overlap with the last booking history entry.
## 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](https://cal.com/docs). If N/A, write N/A here and check the checkbox.
- [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
1. Open any booking in the bookings list to open the details drawer
2. Scroll to the bottom of the drawer content
3. Verify the footer actions (buttons, dropdown) do not overlap with the last content item
4. Test on both mobile and desktop viewport sizes — footer should sit flush at the bottom with no extra gap on either
## Human Review Checklist
- [ ] Verify footer appearance on **mobile** (below `sm` breakpoint) — no gap below footer, no overlap with content
- [ ] Verify footer appearance on **desktop** (`sm+` breakpoint) — same checks
- [ ] Confirm the footer still stretches edge-to-edge horizontally on both breakpoints
## Checklist
- I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- My code doesn't follow the style guidelines of this project
- I haven't commented my code, particularly in hard-to-understand areas
- I haven't checked if my changes generate no new warnings
- My PR is too large (>500 lines or >10 files) and should be split into smaller PRs
---
Link to Devin run: https://app.devin.ai/sessions/b9d130b8a7a54f039b90b53921b19c78
Requested by: @hariombalhara
* Add DB table for wrong assignment reports
* When report is submitted write to the db
* Prevent duplicate reportings
* test: add migration and tests for WrongAssignmentReport table
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add unique constraint on bookingUid and booking access check for hasWrongAssignmentReport
- Add @unique constraint on bookingUid in WrongAssignmentReport model to prevent duplicate reports at DB level
- Add booking ownership check using BookingAccessService in hasWrongAssignmentReport endpoint
- Refactor hasWrongAssignmentReport into separate handler and schema files
Addresses Cubic AI review feedback on PR #27405
Co-Authored-By: unknown <>
* feat: add routingFormId to WrongAssignmentReport and fix Select clearing
- Add routingFormId field to WrongAssignmentReport model in schema.prisma
- Add relation to App_RoutingForms_Form with SetNull on delete
- Update WrongAssignmentReportRepository.createReport to accept routingFormId
- Update BookingRepository.findByUidIncludeEventTypeAndTeamAndAssignmentReason to include routedFromRoutingFormReponse
- Extract routingFormId from booking in reportWrongAssignment handler
- Fix Select clearing issue: handle null case when user clears team member selection
- Update tests to include routingFormId field
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* chore: add migration for routingFormId in WrongAssignmentReport
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add wrong assignment reports dashboard under routing tab
- Add reviewedById and reviewedAt fields to WrongAssignmentReport model
- Add repository methods for listing reports by status and updating status
- Create tRPC endpoints for fetching reports and updating status
- Create dashboard UI with pending/reviewed tabs showing routing form name
- Add translation keys for dashboard UI
- Integrate dashboard into routing insights page
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: move hooks before early return and fix indentation
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: address Udit's review comments
- hasWrongAssignmentReport: throw UNAUTHORIZED error instead of returning false
- reportWrongAssignment: add try-catch for Prisma P2002 unique constraint error
- WrongAssignmentReport: add Team relation to teamId field
- WrongAssignmentReportRepository: use findUnique instead of findFirst
- reportWrongAssignment: use i18n for error messages
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: revert hasWrongAssignmentReport to return false when user lacks access
Per PR checklist, hasWrongAssignmentReport should return { hasReport: false }
when user lacks access to booking, not throw an error. This allows the UI
to gracefully treat 'no access' as 'no report exists'.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* test: update mocks for findUnique and i18n in unit tests
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: throw UNAUTHORIZED in hasWrongAssignmentReport and squash migrations
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: move wrong assignment reports to its own tab under Insights
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Use data table for wrong reports
* Add option to view routing trace
* feat: add view routing form submission action to wrong assignment reports
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add RoutingFormResponseSheet component for viewing form submissions
- Create slide-out sheet to display routing form responses
- Map option IDs to display labels for select/multiselect fields
- Handle both legacy and modern option formats
- Add i18n strings: form_submission, no_responses_found
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: improve wrong assignment reports UX
- Integrate RoutingFormResponseSheet as slide-out panel instead of new tab
- Fix dropdown padding by using StartIcon prop instead of manual Icon
- Allow direct status changes for reviewed reports (no need to reopen first)
- Remove unused Icon import
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: change User relation onDelete from Cascade to SetNull in WrongAssignmentReport
Address Hariom's review feedback:
- Changed reportedById from Int to Int? (nullable)
- Changed reportedBy relation from onDelete: Cascade to onDelete: SetNull
- Updated migration SQL to reflect these changes
This preserves wrong assignment reports even when the reporting user is deleted,
as the data is still useful for analysis.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add missing i18n strings for wrong assignment reports dashboard
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: move form response display value resolution server-side
Replace client-side option ID to label resolution in
RoutingFormResponseSheet with a new lean tRPC endpoint
(getFormResponseDisplay) that resolves values server-side using
the existing getHumanReadableFieldResponseValue utility. This
enforces DTO boundaries by returning a clean pre-resolved payload
instead of leaking internal option format details to the client.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add report wrong assignment button to routing trace sheet
Wire up the WrongAssignmentDialog from the routing trace sheet header
so users can flag wrong assignments directly while viewing the trace.
The report button is disabled with a tooltip when a report already
exists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: reuse existing WrongAssignmentDialog from parent
Replace the duplicate WrongAssignmentDialog in RoutingTraceSheet with
a callback to the existing instance in BookingActionsDropdown. This
reduces the prop surface from a 6-field reportContext object to an
onReport callback and hasExistingReport boolean.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: use repository instead of direct Prisma in getFormResponseDisplay
Replace direct Prisma query with PrismaRoutingFormResponseRepository's
findByIdIncludeForm method. Extend the method to also select form name,
description, userId, and teamId needed for display and auth checks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: replace direct Prisma calls with repository methods
Use MembershipRepository.hasMembership() for auth checks and
TeamRepository.findAllByParentId() for child team queries instead
of direct Prisma calls. Replace direct user query with
UserRepository.getTimeZoneAndDefaultScheduleId(). Remove unused
seed script.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: use PBAC services for wrong assignment report auth
Replace manual MembershipRepository.hasMembership() checks with
PBAC-aware permission checking. getWrongAssignmentReports uses
createTeamPbacProcedure middleware since teamId is in input.
updateWrongAssignmentReportStatus uses PermissionCheckService
directly since teamId is discovered from the report entity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve type errors in RoutingFormResponseSheet and wrong-routing view
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add seed script for wrong assignment reports test data
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Revert "feat: add seed script for wrong assignment reports test data"
This reverts commit 0bd60e9661858a59aab1573d14d57d81733b7991.
* Only update reviewed fields when not pending
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: wrap handleStatusChange in useCallback to fix useMemo recalculation
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Fix routing sheet UI
* fix: use appropriate error message in getFormResponseDisplay handler
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: extract WrongAssignmentReportService from tRPC handlers
Move business logic (booking lookup, duplicate check, report creation,
webhook dispatch, org-level team resolution) into a dedicated service
in packages/features. Handlers become thin controllers that only handle
auth checks and delegate to the service.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restrict report status updates to admin/owner roles
Remove MembershipRole.MEMBER from fallbackRoles in
updateWrongAssignmentReportStatus permission check. Updating report
status is an administrative action that should be limited to team
admins and owners.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: localize hard-coded success message in WrongAssignmentReportService
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: rename reviewed tab to handled and add missing translations
Rename the "Reviewed" tab to "Handled" since it groups three distinct
statuses (Reviewed, Resolved, Dismissed). Also add missing translation
keys for "resolved" and "dismissed" status badges.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* merge: resolve conflicts with main branch
Merge main into devin/1769747741-wrong-assignment-dashboard, resolving conflicts in:
- BookingActionsDropdown.tsx: use main's booking prop with PR's fragment structure
- reportWrongAssignment.handler.ts: keep PR's service-based approach
- reportWrongAssignment.handler.test.ts: use main's class-based mocks with PR's additions
- WrongAssignmentReportService.ts: align with main's repo method and field names
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Add guard when accessing assignmentReasonSortedByCreatedAt
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fix: address Cubic AI review feedback - select projection and useLocale refactor
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: remove stale TRPCError assertion in test (service throws ErrorWithCode)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: remove unused findByTeamIdAndStatus and findByTeamIdAndStatuses methods
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* perf: add composite index on WrongAssignmentReport and narrow findByIdIncludeForm select
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* perf: use lightweight findTeamIdById in update-status handler instead of findById
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: hariom@cal.com <hariombalhara@gmail.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: alex@cal.com <me@alexvanandel.com>
* feat: re-render bookings page after feature opt-in without full refresh
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: make onOptInSuccess a required prop
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: maintain uid parameter in BookingDetailsSheet URL
Move the isSyncedFromUrlToStoreRef guard from the effect level to inside
the Zustand subscription callback. This ensures the Store→URL subscription
is always created while still preventing premature URL overwrites during
URL→Store sync.
Also adds an E2E test verifying the uid parameter appears in the URL
after clicking a booking item in the v3 bookings view.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* Update apps/web/playwright/bookings-list.e2e.ts
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fix: clean up bookings-v3 feature flag after E2E test
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* refactor: apply biome formatting to packages/features (batch 1 - small subdirs)
Format small subdirectories in packages/features: di, flags, holidays, oauth,
settings, users, assignment-reason, selectedCalendar, hashedLink, host, form,
form-builder, availability, data-table, pbac, schedules, troubleshooter,
eventtypes, calendar-subscription, and root-level files.
Also includes straggler apps/web BookEventForm.tsx.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: apply biome formatting to packages/features (batch 2 - medium subdirs)
Format medium subdirectories in packages/features: auth, credentials,
calendars, routing-forms, routing-trace, attributes, watchlist, calAIPhone,
tasker, and webhooks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: apply biome formatting to packages/features (batch 3 - bookings + insights)
Format bookings and insights subdirectories in packages/features.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: apply biome formatting to packages/features (batch 4 - ee)
Format packages/features/ee subdirectory covering billing, workflows,
organizations, teams, managed-event-types, round-robin, dsync,
integration-attribute-sync, and payments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: apply biome formatting to packages/features (batch 5 - booking-audit part 1)
Format booking-audit di, actions, common, dto, repository, and types
subdirectories in packages/features/booking-audit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: apply biome formatting to packages/features (batch 6 - booking-audit part 2)
Format booking-audit service subdirectory in packages/features/booking-audit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update booking page terms text to use APP_NAME instead of 'our'
Co-Authored-By: carina@cal.com <c.wollendorfer@me.com>
* remove changes for platform booker
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
* feat: add activeFilters validator to DataTableProvider for filter segment validation
- Add validateActiveFilters prop to DataTableProvider to filter out inaccessible values
- Create useActiveFiltersValidator hook in bookings module to validate filter values
- Integrate validator in bookings-view.tsx to validate userId, eventTypeId, teamId filters
- Add comprehensive tests for the filter validation logic
This provides a scalable solution for handling stale filter segment data by validating
filters at the caller level using already-fetched accessible resource IDs.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add type guard for eventTypeIds to ensure number[] type
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: delay segment filter application until validator is ready
- Change useActiveFiltersValidator to return 'loading' state while data is fetching
- Add pending segment handling in DataTableProvider to delay filter application
- Expose isValidatorPending in context for consumers to disable queries
- Update BookingListContainer to disable bookings query while validator is pending
This prevents both errors from invalid filters and flash from fetching without filters.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: extract useSegmentManagement hook from DataTableProvider
- Extract segment management logic into dedicated useSegmentManagement hook
- Reduces DataTableProvider from ~500 lines to ~330 lines
- Use NuqsSetter type to match nuqs useQueryState setter signatures
- Maintains all existing functionality and type safety
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: export ActiveFiltersValidator types from data-table lib/types
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: import ActiveFiltersValidatorState from lib/types instead of hook
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* Revert "refactor: extract useSegmentManagement hook from DataTableProvider"
This reverts commit dd588ac4cfb1d709c71d1f621994a7e8f3118f33.
* refactor: split DataTableProvider into fine-grained context providers
- Create DataTableStateContext for raw nuqs state management
- Create DataTableSegmentContext for segment management
- Create DataTableFiltersContext for filter manipulation
- DataTableProvider now composes all providers with a bridge component
- Maintains backward compatibility via combined DataTableContext
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: apply segment filters when navigating back to page with existing URL state
When navigating back to a page with a segment already selected in the URL,
the segment was being marked as selected but its filters were not being
applied. This caused non-deterministic behavior where the filter segment
would sometimes not take effect.
The fix ensures that when segmentIdRaw exists in the URL and segments are
fetched, we also call applySegmentFilters() (with validator timing support)
instead of just setting the selectedSegment state.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: simplify filter validator to only handle multi-select
These filters are always multi-select, so remove unnecessary
single-select handling code and tests.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: cancel debounced search term on unmount
Cancel the debounced search term on unmount/dependency change to avoid
queued updates firing after the provider unmounts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Add updateCurrentTimeOnFocus prop to Calendar component that enables
the current time indicator to update when the page is refocused.
This helps users see the accurate current time after switching tabs.
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
* refactor: move shared components from apps/web to packages/features
Move components that don't require dependency injection:
- DisconnectIntegrationModal
- Booking components (Header, Section, TimeFormatToggle, PayIcon, Price)
- useInitializeWeekStart hook
- TeamEventTypeForm
- Event type components (AssignAllTeamMembers, BulkEditDefaultForEventsModal, etc.)
- Event type dialogs (HostEditDialogs, ManagedEventDialog)
- Location components (LocationInput, types)
- Tab components (EventLimitsTab, EventRecurringTab, etc.)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: update import paths to use @calcom/features
Update imports in apps/web and packages/platform/atoms to reference
the moved components from @calcom/features instead of @calcom/web.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: delete original files from apps/web/modules
Complete the file move by deleting the original files that were
copied to packages/features. This makes it a proper move instead
of a copy, reducing the PR size significantly.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update import paths to use @calcom/features for moved files
Update import paths in apps/web files that reference components
that were moved from apps/web/modules to packages/features:
- LearnMoreLink
- ChildrenEventTypeSelect
- AssignAllTeamMembers
- WeightDescription
- LocationCustomClassNames (types)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update additional import paths for moved components
Update import paths in apps/web files that reference components
moved from apps/web/modules to packages/features:
- AppList.tsx: BulkEditDefaultForEventsModal
- schedule-view.tsx: BulkUpdatParams type
- AddMembersWithSwitch.tsx: AssignAllTeamMembers, CheckedTeamSelect
- EventTypeWebWrapper.tsx: ChildrenEventType, ManagedEventDialog
- DefaultLocationSettings.tsx: LocationCustomClassNames, LocationInput
- Locations.tsx: LocationCustomClassNames, LocationInput
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: resolve circular dependency by adding isPlatform prop to Header
This fixes the circular dependency where @calcom/atoms (CalendarViewComponent)
was importing Header from @calcom/features, but Header was importing
useIsPlatform from @calcom/atoms.
The fix adds an isPlatform prop to the Header component so it no longer
needs to import useIsPlatform from @calcom/atoms. Callers now pass the
isPlatform value directly:
- atoms components pass isPlatform={true}
- web components pass the isPlatform prop they receive
Fix confidence: 9/10 (Cubic AI)
Co-Authored-By: unknown <>
* fix
* fix
* fix
* fix
* fix
* fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: move Booker hooks from packages/features to apps/web/modules
Migrate the following Booker hooks:
- useOverlayCalendar
- useSkipConfirmStep
- useInitializeWeekStart
- useIsQuickAvailabilityCheckFeatureEnabled
- useDecoyBooking
These hooks are only imported by apps/web files, making them safe to move
without creating circular dependencies.
Part of the tRPC-driven UI migration from packages/features to apps/web/modules.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: revert useIsQuickAvailabilityCheckFeatureEnabled move and fix import paths
- Reverted useIsQuickAvailabilityCheckFeatureEnabled.ts back to packages/features since it's imported by useSlots.ts in packages/features (would create circular dependency)
- Fixed import paths in useOverlayCalendar.ts to use @calcom/features paths
- Fixed import paths in useSkipConfirmStep.ts to use @calcom/features paths
- Updated Booker.tsx to import useIsQuickAvailabilityCheckFeatureEnabled from original location
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: use @calcom/web alias for hook imports to fix vitest resolution
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor
* migrate more hooks
* fix
* mv types
* fix
* fix
* fix
* fix
* revert: remove formatting-only changes to make PR easier to review
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* fix
* fix
* revert: restore original import ordering in moved hooks
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix imports
* fix
* fix
* wip
* wip
* wip
* wip
* wip
* wip
* fix: add isBrowser guard to useSlotsViewOnSmallScreen hook
Address Cubic AI review feedback (confidence 9/10) by adding the isBrowser
guard to the useSlotsViewOnSmallScreen hook to follow the file's client-only
contract and avoid executing during SSR/prerendering.
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: Disables syncing of calendarList on overlay calendar fetch
* Unwrap ToggledConnectedCalendars
* Pick the right type for connectedCalendars
* further type amends
* Type fixes, tons of em
* Some further fixups consistent with what was before
* fix: resolve type incompatibility in getConnectedDestinationCalendars return type
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: update DestinationCalendarProps to accept tRPC handler return type
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: use generic type for DestinationCalendarProps to accept tRPC enriched types
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: simplify DestinationCalendarProps type for better compatibility
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: export ConnectedCalendar type for consistent type inference
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: use permissive type for connectedCalendars to accept tRPC enriched types
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: export ConnectedCalendar and ConnectedDestinationCalendars types from platform-libraries
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* fix: update ConnectedCalendar type to use boolean | null for primary field
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* Update ConnectedCalendarItem
* Undo some of Devins fixes, more fixes
* Fixup the destination calendar return type, historically not null
* Change init to undefined to deal with null
* Approach to connect selected calendars with the right credential
* This return type is used way too much everywhere, not refactoring
* Add the selectedCalendars to the type
* Actually fix overlay calendar
* set calendarsToLoad param as required
* Apply suggestion from @cubic-dev-ai[bot]
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Add new translation for 'Calendar Settings'
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* refactor: move booking-audit client components from packages/features to apps/web/modules
This is part of the larger effort to move tRPC-dependent UI components from packages/features to apps/web/modules to eliminate circular dependencies.
Changes:
- Move BookingHistory.tsx and BookingHistoryPage.tsx to apps/web/modules/booking-audit/components/
- Update imports in apps/web to use the new location
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move formbricks client from packages/features to apps/web/modules
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move hooks and stores from packages/features to apps/web/modules
- Move useAppsData hook from packages/features/apps/hooks to apps/web/modules/apps/hooks
- Move onboardingStore from packages/features/ee/organizations/lib to apps/web/modules/ee/organizations/lib
- Move useWelcomeModal hook from packages/features/ee/organizations/hooks to apps/web/modules/ee/organizations/hooks
- Move useAgentsData hook from packages/features/ee/workflows/hooks to apps/web/modules/ee/workflows/hooks
- Update all import paths in consuming files
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: move onboardingStore test file to apps/web/modules
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: save progress
* chore:
* feat: add input dialog
* fix: type error
* feat: mass apply dialog
* test: per host location
* test: fix test
* fix: address Cubic AI review feedback (confidence >= 9/10)
- Remove PII (address, phone number) from tracing logs in RegularBookingService.ts
- Constrain HostLocation.type to EventLocationType["type"] for compile-time validation
Co-Authored-By: unknown <>
* fix: translation
* refactor: improvements
* fix: correct grammar in custom host locations tooltip
Change 'custom host locations is enabled' to 'custom host locations are enabled' (plural subject requires plural verb).
Addresses Cubic AI review feedback (confidence 9/10).
Co-Authored-By: unknown <>
* refactor: improvements
* fix: auth
* fix: check
* refactor: improvements
* fix: address Cubic AI review feedback (confidence >= 9/10)
- Add scheduleId to newly created hosts in update.handler.ts to persist
host-specific schedules during create operations
- Change host location deletion filter from !host.location to
host.location === null to only delete when explicitly set to null
- Fix static-link per-host locations to use actual link instead of type
in locationBodyString for bookingLocationService.ts
Co-Authored-By: unknown <>
* fix: preserve existing host scheduleId when not explicitly provided
Change scheduleId handling for existing hosts from 'host.scheduleId ?? null'
to 'host.scheduleId === undefined ? undefined : host.scheduleId' so that
when the client doesn't provide a scheduleId, the existing value is preserved
instead of being cleared to null.
Co-Authored-By: unknown <>
* fix; type erro
* fix; type erro
* fix; type erro
* refactor: move repository
* refactor: move repository
* fix: add singular/plural translations for location_applied_to_hosts
Addresses Cubic AI review feedback (confidence 9/10) to fix '1 hosts' rendering as '1 host' by using i18next plural format with _one and _other suffixes.
Co-Authored-By: unknown <>
* refactor: feedback
* fix: type err
* fix: use uuid in schema and remove attendee locaiton
* fix: type err
* fix: type err
* fix: validate eventTypeId as integer in massApplyHostLocation schema
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: allow normal users to see userId filter with only themselves as option
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: return empty map when canReadOthersBookings is false and currentUser doesn't exist
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: use generic type parameter for Table to fix type compatibility
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* perf: disable listSimpleMembers query when canReadOthersBookings is false
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: add new view for two step slot selection for embed
* fix: make sure two step slot selection is false by default
* chore: update embed playground to showcase two step slot selection
* chore: add tests
* chore: update embed snippet generator code to include two step slot selection
* chore: update docs
* fix: back button styling
* chore: implement feedback from cubic
* fix: add missing isEnableTwoStepSlotSelectionVisible properties to test mock store
Co-Authored-By: unknown <>
* chore: implement PR feedback
* chore: update slot selection modal
* chore: add prop to hide available times header
* fix: scope two-step slot selection visibility to mobile only
Restores the isMobile check in the timeslot visibility guard to ensure
desktop embeds continue to show the booking UI when two-step slot
selection is enabled. The feature should only hide the timeslot list
on mobile devices.
Addresses Cubic AI review feedback (confidence 9/10).
Co-Authored-By: unknown <>
* fixup: use translations for loading instead of actual word
* fix: type check
* fix: add window.matchMedia mock for jsdom test environment
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: add window.matchMedia mock to packages/testing/src/setupVitest.ts
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: unit tests failing
* add a width style to the two-step slot selection embed container.
* refactor: rename enableTwoStepSlotSelection to useSlotsViewOnSmallScreen
- Rename external-facing embed config option from enableTwoStepSlotSelection to useSlotsViewOnSmallScreen
- Update URL parameter parsing in embed-iframe.ts
- Update type definitions in types.ts and index.d.ts
- Update internal variable names to slotsViewOnSmallScreen for consistency
- Update documentation, playground examples, and tests
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Add config to prefill all booking fields so that slot has confirm button along with it
* chore: implement PR feedback
* fix: move twoStepSlotSelection embed outside misc-embeds div to fix e2e test
The e2e test was failing because the misc-embeds div content was
intercepting pointer events on mobile viewport. This follows the same
pattern used for skeletonDemo - the embed is now outside misc-embeds
and the div is hidden when testing this namespace.
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: prevent pointer event interception in twoStepSlotSelection embed
Hide heading and note elements and set pointer-events: none on container
elements while keeping pointer-events: auto on the iframe container.
This prevents the container from intercepting clicks on the iframe
during mobile viewport e2e tests.
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: hide all non-essential content for twoStepSlotSelection e2e test
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: disable pointer-events on body for twoStepSlotSelection e2e test
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: remove pointer-events: auto on container to let clicks pass through to iframe
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: explicitly set pointer-events: none on container and inline-embed-container
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: also set pointer-events: none on html element to prevent interception
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: make .place div fill viewport for twoStepSlotSelection e2e test
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* fix: failing embed tests
* fixup
* fixup fixup
* fix: failing tests
* fix: update checks for verifying prefilled date
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
* feat: add option to hide duration selector in booking page for multiple durations
- Add 'hideDurationSelectorInBookingPage' field to event type metadata schema
- Add checkbox under Default Duration select in event type settings
- Modify Duration component to hide selector when setting is enabled
- URL params can still set duration when selector is hidden
- Add i18n translation for the new checkbox label
- Add e2e tests for the new functionality
Co-Authored-By: ali@cal.com <ali@cal.com>
* fix: rename checkbox label to 'Hide duration selector'
Co-Authored-By: ali@cal.com <ali@cal.com>
* fix: replace text locator with data-testid in E2E test
Replace `text=Multiple duration` locator with `page.getByTestId("event-types").locator('a[title="Multiple duration"]')` to follow E2E test best practices.
Co-Authored-By: unknown <>
* fix: add data-testid to hide duration selector checkbox for E2E tests
Co-Authored-By: ali@cal.com <ali@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ali@cal.com <ali@cal.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
* docs: add feature opt-in banner system plan
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* docs: iterate on feature opt-in banner plan based on feedback
- Use config.ts for feature metadata instead of TRPC response
- Consolidate localStorage dismissal into single key to avoid bloat
- Replace separate success dialog with in-dialog success state for smoother UX
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: implement feature opt-in banner system
- Add checkFeatureOptInEligibility TRPC procedure to check if user can opt-in
- Create useFeatureOptInBanner hook with localStorage dismissal state
- Create FeatureOptInBanner floating component for bottom-right display
- Create FeatureOptInConfirmDialog with role-based options and success state
- Integrate banner into bookings-view.tsx as example usage
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add i18n translation keys for feature opt-in banner
* refactor: create FeatureOptInBannerWrapper for simpler consumer integration
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: use @calcom/lib/webstorage and add Zod schema for localStorage
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: address PR review comments - use PBAC, move logic to service, improve typing
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
# Conflicts:
# packages/features/feature-opt-in/services/FeatureOptInService.ts
* test: add comprehensive tests for checkFeatureOptInEligibility method
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: correct import and Checkbox type errors
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update message
* invalidate after dialog dismiss
* feat: simulate user opt-in to determine banner eligibility
When a feature has a strict policy and org/team hasn't explicitly
enabled it, user opt-in alone won't enable the feature. This change
simulates what would happen if the user opts in and only shows the
banner if opting in would actually enable the feature.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add early return for missing featureConfig and clarify simulation comment
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix repository usage
* refactor: simplify FeatureOptInConfirmDialog UI and remove unused translation
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: replace radio buttons with multi-select dropdown in FeatureOptInConfirmDialog
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* resize banner
* refactor: use AnimatedPopover pattern for team selection and rename titleI18nKey to nameI18nKey
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: change 'Just for me' to 'For me', fix width clipping, remove divider
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update style
* feat: make 'Just for me' mutually exclusive with teams/org and store opt-ins in localStorage
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: remove barrel imports and update to direct imports
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add modal prop to AnimatedPopover to fix scroll lock conflict in dialogs
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: wrap Popover.Content with Portal to prevent layout interference in dialogs
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: use flexbox gap instead of space-y to prevent popover wrapper from affecting layout
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* Revert "fix: use flexbox gap instead of space-y to prevent popover wrapper from affecting layout"
This reverts commit 8385adafa890c2f2674aa3ae3b10ca6e0c55ba5c.
* Revert "fix: wrap Popover.Content with Portal to prevent layout interference in dialogs"
This reverts commit e84301a35a99b3559d47c2d37316af290834ca2d.
* Revert "fix: add modal prop to AnimatedPopover to fix scroll lock conflict in dialogs"
This reverts commit b015af2f1cf31ef7087c02cb8535d96cc4a34125.
* feat: replace Radix Dialog and AnimatedPopover with coss-ui components
This migration uses @coss/ui Dialog and Popover components which are built on
Base UI instead of Radix. Base UI handles scroll locking and positioning
differently, which should fix the gap issue when opening the popover inside
the dialog.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: replace remaining @calcom/ui components with coss-ui
- Replace Divider with Separator from @coss/ui
- Replace Label with Label from @coss/ui
- Replace CheckboxField with Checkbox + Label from @coss/ui
- Replace Icon with direct lucide-react icons (UserIcon, BuildingIcon, UsersIcon, CheckIcon)
- Replace showToast with toastManager.add() from @coss/ui
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: replace Popover with Menu component from coss-ui
- Replace Popover + FilterCheckboxField with Menu + MenuCheckboxItem
- MenuCheckboxItem provides built-in checkbox indicator and styling
- MenuSeparator provides proper menu separators
- Cleaner API with onCheckedChange callback
- Better keyboard navigation support
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: align icon and text on same line in MenuCheckboxItem, widen dialog
- Wrap icon and text in flex container with items-center gap-2
- Change dialog width from sm:max-w-md to sm:max-w-lg to prevent text wrapping
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* use dimmed bg for coss dialog title
* refactor: change nameI18nKey/descriptionI18nKey to nested i18n object
- Change OptInFeatureConfig interface to use i18n: { name, description }
- Update all component usages to use featureConfig.i18n.name and featureConfig.i18n.description
- Update test mocks to use new structure
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: add i18n.title to OptInFeatureConfig type definition
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update texts
* use title instead of name
* update banner style
* refactor: split FeatureOptInConfirmDialog into separate success and confirmation dialogs
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: don't record dismissed info in local storage after successful opt-in
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: add checkFeatureOptInEligibility to IFeatureOptInService interface
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update common.json
* refactor: move tRPC usage from features package to apps/web/modules
Addresses Cubic AI review feedback (confidence 9/10):
- Remove @calcom/trpc import from FeatureOptInConfirmDialog.tsx
- Add FeatureOptInMutations type for passing mutation functions via props
- Move tRPC hooks to useFeatureOptInBanner hook in apps/web/modules
- Pass mutations through FeatureOptInBannerWrapper to dialog component
This maintains the architectural constraint that packages/features
should not import from @calcom/trpc to prevent circular dependencies.
Co-Authored-By: unknown <>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Add interpolation: { escapeValue: false } to AttendeeRequestEmail.tsx
- Add interpolation: { escapeValue: false } to attendee-request-email.ts
- Add interpolation: { escapeValue: false } to bookings-single-view.tsx
This prevents special characters like '/' from being HTML-encoded to '/'
in booking confirmation emails and success page dialogs.
Fixes#26938