Skip to content

fix: booking list item hook usage #22215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ddoemonn
Copy link
Contributor

@ddoemonn ddoemonn commented Jul 2, 2025

What does this PR do?

Refactors the BookingListItem component to extract state management into centralized custom hooks, addressing technical debt and improving maintainability. This change consolidates 15+ scattered useState hooks into two focused custom hooks: useDialogState for dialog management and useBookingFormState for form inputs.

Key Changes:

  • Extracted useDialogState hook - Centralizes all dialog visibility state management
  • Extracted useBookingFormState hook - Manages form inputs like rejection reasons
  • Replaced scattered useState calls - Consolidated 15+ individual state declarations
  • Improved separation of concerns - UI logic separated from state management
  • Enhanced testability - Custom hooks can be tested independently

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. If N/A, write N/A - this is an internal refactor with no API changes.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

Environment Setup:

  • Standard Cal.com development environment
  • No special environment variables required

Test Scenarios:

  1. Dialog Functionality:

    • Open/close each dialog (location, reschedule, reassign, etc.)
    • Verify all dialogs open/close correctly
    • Test dialog state persistence during interactions
  2. Form State Management:

    • Enter rejection reasons in rejection dialog
    • Verify form state updates correctly
    • Test form submission with rejection reasons
  3. Booking Actions:

    • Test all booking actions (confirm, reject, reschedule, etc.)
    • Verify no regression in booking functionality
    • Confirm all existing user flows work identically

Expected Behavior:

  • ✅ All dialogs function exactly as before
  • ✅ No visual or functional changes for users
  • ✅ State management is cleaner in dev tools
  • ✅ No console errors or warnings

Test Data:

  • Any existing booking with standard attendees
  • Team bookings for reassign functionality
  • Bookings with payment for charge card dialogs

Checklist

  • I have read the contributing guide
  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have checked if my changes generate no new warnings

Additional Notes:
This refactor maintains 100% backward compatibility - no user-facing changes. The improvement is purely internal code quality, making the component more maintainable and testable for future development.


Summary by cubic

Refactored BookingListItem to use two custom hooks for dialog and form state, replacing over 15 scattered useState calls and making the code easier to maintain.

  • Refactors
    • Added useDialogState and useBookingFormState hooks to centralize state management.
    • Removed individual state variables for dialogs and form fields.

Copy link

vercel bot commented Jul 2, 2025

@ddoemonn is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Jul 2, 2025
@graphite-app graphite-app bot requested a review from a team July 2, 2025 14:52
@github-actions github-actions bot added the 🐛 bug Something isn't working label Jul 2, 2025
Copy link
Contributor

github-actions bot commented Jul 2, 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:

Unknown release type "FIX" found in pull request title "FIX: booking list item hook usage". 

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

@ddoemonn ddoemonn changed the title FIX: booking list item hook usage fix: booking list item hook usage Jul 2, 2025
Copy link

graphite-app bot commented Jul 2, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (07/02/25)

1 reviewer was added to this PR based on Keith Williams's automation.

"Add community label" took an action on this PR • (07/02/25)

1 label was added to this PR based on Keith Williams's automation.

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.

cubic found 2 issues across 3 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

Copy link
Contributor

@Devanshusharma2005 Devanshusharma2005 left a comment

Choose a reason for hiding this comment

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

Please address the cubic and yarn issues. Marking it draft for now. Feel free to rfr.

@anikdhabal anikdhabal added the Low priority Created by Linear-GitHub Sync label Jul 4, 2025
@anikdhabal anikdhabal requested a review from sean-brydon July 14, 2025 09:48
Copy link
Contributor

This PR is being marked as stale due to inactivity.

@github-actions github-actions bot added the Stale label Jul 29, 2025
Copy link
Contributor

coderabbitai bot commented Jul 29, 2025

Walkthrough

The changes introduce two new custom hooks, useDialogState and useBookingFormState, to centralize and manage dialog and form state within the BookingListItem component. All previous individual useState hooks for dialog visibility and form fields are removed from the component and replaced by these hooks. The new hooks encapsulate state logic and provide memoized actions for opening, closing, and querying dialogs, as well as updating form fields such as rejection reason, selected email, and no-show attendees. All dialog-related UI and event handlers are updated to utilize these centralized state management APIs, resulting in a refactored component with separated concerns and consistent state handling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Assessment against linked issues

Objective Addressed Explanation
Centralized state management using custom hooks (#22214)
Consistent API for dialog and form state management (#22214)
Separated concerns between UI rendering and state logic (#22214)
Testable and maintainable code structure following React best practices (#22214)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes were found. All modifications are directly related to the objectives of centralizing and refactoring state management in the BookingListItem component as described in the linked issue.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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: 0

♻️ Duplicate comments (2)
apps/web/components/booking/hooks/useBookingFormState.ts (2)

3-9: LGTM! Proper TypeScript interfaces implemented.

The BookingAttendee interface provides proper type safety with well-defined fields. This successfully addresses the previous concern about using any[] types.


49-58: LGTM! Actions object properly memoized.

The actions object is now correctly wrapped in useMemo with appropriate dependencies, ensuring a stable reference and preventing unnecessary re-renders. This addresses the previous performance concern.

🧹 Nitpick comments (1)
apps/web/components/booking/hooks/useDialogState.ts (1)

15-17: Improve type safety in DialogState interface.

The current DialogState interface uses generic string indexing, which reduces type safety. Consider using the DialogType union for stronger typing:

-interface DialogState {
-  [key: string]: boolean;
-}
+type DialogState = {
+  [K in DialogType]: boolean;
+};

This ensures only valid dialog types can be used as keys and provides better IntelliSense support.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa3086c and 8e3139e.

📒 Files selected for processing (3)
  • apps/web/components/booking/BookingListItem.tsx (19 hunks)
  • apps/web/components/booking/hooks/useBookingFormState.ts (1 hunks)
  • apps/web/components/booking/hooks/useDialogState.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.tsx

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • apps/web/components/booking/BookingListItem.tsx
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/web/components/booking/BookingListItem.tsx
  • apps/web/components/booking/hooks/useDialogState.ts
  • apps/web/components/booking/hooks/useBookingFormState.ts
**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/web/components/booking/hooks/useDialogState.ts
  • apps/web/components/booking/hooks/useBookingFormState.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
apps/web/components/booking/BookingListItem.tsx (1)

Learnt from: eunjae-lee
PR: #22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

apps/web/components/booking/hooks/useDialogState.ts (1)

Learnt from: alishaz-polymath
PR: #22304
File: packages/features/eventtypes/components/MultiplePrivateLinksController.tsx:92-94
Timestamp: 2025-07-16T06:42:27.024Z
Learning: In the MultiplePrivateLinksController component (packages/features/eventtypes/components/MultiplePrivateLinksController.tsx), the currentLink.maxUsageCount ?? 1 fallback in the openSettingsDialog function is intentional. Missing maxUsageCount values indicate old/legacy private links that existed before the expiration feature was added, and they should default to single-use behavior (1) for backward compatibility.

apps/web/components/booking/hooks/useBookingFormState.ts (3)

Learnt from: eunjae-lee
PR: #22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Learnt from: Anshumancanrock
PR: #22570
File: apps/web/modules/signup-view.tsx:253-253
Timestamp: 2025-07-21T21:33:23.371Z
Learning: In signup-view.tsx, when checking if redirectUrl contains certain strings, using explicit && checks (redirectUrl && redirectUrl.includes()) is preferred over optional chaining (redirectUrl?.includes()) to ensure the result is always a boolean rather than potentially undefined. This approach provides cleaner boolean contracts for downstream conditional logic.

Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.{ts,tsx} : Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

🔇 Additional comments (9)
apps/web/components/booking/hooks/useDialogState.ts (3)

27-38: LGTM! Well-structured state initialization.

The explicit initialization of all dialog states prevents undefined values and ensures consistent behavior. The TypeScript typing is properly applied.


40-67: LGTM! Proper memoization and functional updates.

The action functions are well-implemented with:

  • Correct use of functional state updates to prevent stale closures
  • Proper memoization with appropriate dependency arrays
  • Clear and explicit state management

69-81: LGTM! Excellent backward compatibility design.

The getDialogSetter function provides seamless compatibility with React's standard state setter pattern, handling both direct boolean values and updater functions correctly. This design allows easy migration from individual useState hooks.

apps/web/components/booking/hooks/useBookingFormState.ts (1)

33-47: LGTM! Well-implemented callback functions.

All state-modifying functions use proper functional updates and are correctly memoized with useCallback. The dependency arrays are appropriate for these implementations.

apps/web/components/booking/BookingListItem.tsx (5)

57-59: LGTM! Clean hook integration and centralized state management.

The import and initialization of both custom hooks successfully centralizes what were previously scattered useState calls throughout the component. The clear commenting helps document the architectural change.

Also applies to: 122-124


151-151: LGTM! Consistent dialog action usage.

All dialog actions follow a consistent pattern using the centralized dialogActions.openDialog() and dialogActions.closeDialog() methods. The dialog type strings match the DialogType union from the hook.

Also applies to: 223-223, 264-264, 274-274, 284-284, 295-295, 307-307, 329-329, 360-360


199-199: LGTM! Clean form state integration.

The form state usage consistently leverages the centralized formState for reading values and formActions for updates, successfully replacing scattered local state management.

Also applies to: 551-552


484-485: LGTM! Flexible dialog component integration.

The dialog components successfully integrate with the centralized state using both getDialogSetter() for direct compatibility and inline functions for explicit control. Both patterns work well with the new state management architecture.

Also applies to: 488-491, 500-501, 505-506, 511-512, 521-522, 530-534, 537-540, 752-754


112-760: Excellent refactoring that successfully centralizes state management.

This refactoring successfully achieves the PR objectives by:

  • Consolidating 15+ scattered useState hooks into two centralized custom hooks
  • Improving separation of concerns between UI and state logic
  • Maintaining full backward compatibility with existing functionality
  • Providing consistent APIs for dialog and form state management
  • Enhancing testability through isolated state logic

The implementation follows React best practices and significantly improves code maintainability without introducing any breaking changes.

@github-actions github-actions bot removed the Stale label Jul 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working community Created by Linear-GitHub Sync Low priority Created by Linear-GitHub Sync 💻 refactor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BookingListItem component needs state management refactoring for maintainability
3 participants