Skip to content

Conversation

bandhan-majumder
Copy link
Contributor

@bandhan-majumder bandhan-majumder commented Aug 19, 2025

What does this PR do?

refactors

Visual Demo (For contributors especially)

UPDATED (As per requested changes)
1
image
2
image

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 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?

  • Are there environment variables that should be set?
  • What are the minimal test data to have?
  • What is expected (happy path) to have (input and output)?
  • Any other important info that could help to test that PR

Checklist

  • I haven't read the contributing guide
  • 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

Copy link
Contributor

coderabbitai bot commented Aug 19, 2025

Warning

Rate limit exceeded

@eunjae-lee has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 32 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 3ad481d and 66cde51.

📒 Files selected for processing (1)
  • apps/web/public/static/locales/ta/common.json (0 hunks)

Walkthrough

The PR adds “completed bookings” insights: two new client components (MostCompletedTeamMembersTable, LeastCompletedTeamMembersTable), corresponding TRPC endpoints (membersWithMostCompletedBookings, membersWithLeastCompletedBookings) using dateTarget "startTime", and expands InsightsBookingBaseService to support filtering by status "accepted". Existing “Most/Least Booked” chart titles are renamed via locale keys. The insights page layout is reorganized to include the new components and reposition existing tables. English locale gains four new keys; many other locale files have EOF newline changes, one removes a placeholder key, and Tamil removes two keys.

Assessment against linked issues

Objective ([#23176, CAL-6275]) Addressed Explanation
Rename existing “Most Booked” and “Least Booked” chart titles to “Most/Least Bookings Scheduled”
Add two new charts (UI components) for completed bookings
Add corresponding TRPC handlers for completed bookings
Modify InsightsBookingBaseService to support completed status filtering
Use startTime as dateTarget and ensure only completed bookings are counted

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Reorganized multiple cards/grids including moving PopularEventsTable and rated members tables (apps/web/modules/insights/insights-view.tsx) Layout rearrangement is not part of renaming charts or adding completed-bookings charts/handlers/service changes.
Removal of Tamil keys most_booked_members and least_booked_members (apps/web/public/static/locales/ta/common.json) Linked objectives do not call for deleting existing locale keys; may cause locale regressions unrelated to feature.
Removal of placeholder key ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS (apps/web/public/static/locales/el/common.json) Cleanup of placeholder translation key is unrelated to the specified objectives.

Possibly related PRs

✨ Finishing Touches
🧪 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@github-actions github-actions bot added consumer insights area: insights, analytics 🧹 Improvements Improvements to existing features. Mostly UX/UI labels Aug 19, 2025
Copy link

vercel bot commented Aug 19, 2025

@bandhan-majumder is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@bandhan-majumder
Copy link
Contributor Author

bandhan-majumder commented Aug 19, 2025

edit: all the required changes are made. Testing now.

@bandhan-majumder bandhan-majumder marked this pull request as ready for review August 21, 2025 05:33
@graphite-app graphite-app bot requested a review from a team August 21, 2025 05:33
@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Aug 21, 2025
Copy link

graphite-app bot commented Aug 21, 2025

Graphite Automations

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

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

"Add community label" took an action on this PR • (08/21/25)

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

"Add foundation team as reviewer" took an action on this PR • (08/22/25)

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

"Add ready-for-e2e label" took an action on this PR • (08/25/25)

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

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: 5

🧹 Nitpick comments (8)
packages/features/insights/server/trpc-router.ts (2)

322-324: Question the new status param on createInsightsBookingService.

Only the new “completed bookings” endpoints use this, and the status is later implemented via an extra column filter (time-based), not an actual booking status. If we switch endpoints to request “completed” directly from the service (see below), this parameter can be dropped to keep the helper simple and avoid param creep.

Apply this minimal simplification if you adopt the endpoint fix below:

-function createInsightsBookingService(
-  ctx: { user: { id: number; organizationId: number | null } },
-  input: z.infer<typeof bookingRepositoryBaseInputSchema>,
-  dateTarget: "createdAt" | "startTime" = "createdAt",
-  status: "completed" | "all" = "all"
-) {
+function createInsightsBookingService(
+  ctx: { user: { id: number; organizationId: number | null } },
+  input: z.infer<typeof bookingRepositoryBaseInputSchema>,
+  dateTarget: "createdAt" | "startTime" = "createdAt"
+) {

354-354: Use columnFilters as-is (after removing the “completed” time hack).

Once the time-based hack is removed, pass through columnFilters as provided by input to avoid unexpected server-side mutations.

-      ...(updatedColumnFilters && { columnFilters: updatedColumnFilters }),
+      ...(updatedColumnFilters && { columnFilters: updatedColumnFilters }),

Note: keep the local name or inline columnFilters if you revert the earlier block entirely.

packages/features/insights/components/booking/index.ts (1)

14-15: Exports Verified and Named Exports Match

Both components exist in packages/features/insights/components/booking and correctly export the expected tables:

  • packages/features/insights/components/booking/MostCompletedBookings.tsx
    • Exports MostCompletedTeamMembersTable
  • packages/features/insights/components/booking/LeastCompletedBookings.tsx
    • Exports LeastCompletedTeamMembersTable

You can safely import these in the insights view without breaking existing code.

Optional: If these tables fetch or render large datasets, consider lazy-loading them in the insights view to reduce the initial bundle size.

apps/web/modules/insights/insights-view.tsx (1)

93-96: Make layout consistent with other 2-up grids (span 2 cols at md).
In earlier sections, two-wide items span two columns on md (4-col grid) for better readability. These two tables currently render at 1/4 width each on md. Consider matching the pattern used for BookingsByHour/AverageEventDuration.

-        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
-          <MostCompletedTeamMembersTable />
-          <LeastCompletedTeamMembersTable />
-        </div>
+        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
+          <div className="sm:col-span-2">
+            <MostCompletedTeamMembersTable />
+          </div>
+          <div className="sm:col-span-2">
+            <LeastCompletedTeamMembersTable />
+          </div>
+        </div>
packages/features/insights/components/booking/LeastCompletedBookings.tsx (2)

28-34: Consider a lightweight error/empty state instead of silent null.
Returning null on error/empty makes the UI “blink out.” If there’s a shared or , use it for user feedback; otherwise, a small inline message suffices.


15-24: Centralize TRPC query options and maintain existing batching behavior
The inline TRPC options (staleTime, refetchOnWindowFocus, and trpc.context.skipBatch) are duplicated across nearly all insights booking tables and charts. Extract these into a shared constant to ensure consistency and simplify future tweaks:

• Create a new file for shared options, for example:

// packages/features/insights/constants.ts
export const INSIGHTS_QUERY_OPTIONS = {
  staleTime: 180_000,              // 3 minutes
  refetchOnWindowFocus: false,
  trpc: { context: { skipBatch: true } },
} as const;

• Update each component (e.g. LeastCompletedBookings.tsx):

-import { trpc } from '...';
+import { trpc } from '...';
+import { INSIGHTS_QUERY_OPTIONS } from 'packages/features/insights/constants';

   // ...
-  const { data, isSuccess, isPending } =
-    trpc.viewer.insights.membersWithLeastCompletedBookings.useQuery(
-      insightsBookingParams,
-      {
-        staleTime: 180000,
-        refetchOnWindowFocus: false,
-        trpc: { context: { skipBatch: true } },
-      }
-    );
+  const { data, isSuccess, isPending } =
+    trpc.viewer.insights.membersWithLeastCompletedBookings.useQuery(
+      insightsBookingParams,
+      INSIGHTS_QUERY_OPTIONS
+    );

Since skipBatch: true is already applied uniformly across all insights queries, this refactor preserves existing behavior. If you later determine that batching is safe, you can remove or adjust it centrally.

packages/features/insights/components/booking/MostCompletedBookings.tsx (2)

28-34: Optional: non-null fallback for errors/empty data.
To avoid silent disappearance, consider rendering a small Empty/Error component if available.


15-24: DRY-Up tRPC Query Options and Reevaluate skipBatch

Centralize the common query configuration into a shared constant and confirm whether you still need to disable batching for these insights endpoints.

  • Extract the inline options (staleTime, refetchOnWindowFocus, trpc.context.skipBatch) into a single INSIGHTS_QUERY_OPTS constant.
  • Apply the same extraction in both MostCompletedBookings.tsx and LeastCompletedBookings.tsx to avoid divergence.
  • Since both server handlers invoke
    createInsightsBookingService(ctx, input, "startTime", "completed")
    with no special batching constraints, verify if you can safely remove skipBatch to leverage tRPC’s default request batching.
+const INSIGHTS_QUERY_OPTS = {
+  staleTime: 180_000,
+  refetchOnWindowFocus: false,
+  trpc: { context: { skipBatch: true } }, // ← consider removing if batching works
+} as const;

-const { data, isSuccess, isPending } = trpc.viewer.insights.membersWithMostCompletedBookings.useQuery(
-  insightsBookingParams,
-  {
-    staleTime: 180000,
-    refetchOnWindowFocus: false,
-    trpc: { context: { skipBatch: true } },
-  }
-);
+const { data, isSuccess, isPending } =
+  trpc.viewer.insights.membersWithMostCompletedBookings.useQuery(
+    insightsBookingParams,
+    INSIGHTS_QUERY_OPTS
+  );

• Repeat this change in packages/features/insights/components/booking/LeastCompletedBookings.tsx.
• After extraction, test without skipBatch and confirm via performance metrics or error logs that batching introduces no regressions.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b9aee3b and 39c6ca4.

📒 Files selected for processing (8)
  • apps/web/modules/insights/insights-view.tsx (2 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/features/insights/components/booking/LeastBookedTeamMembersTable.tsx (1 hunks)
  • packages/features/insights/components/booking/LeastCompletedBookings.tsx (1 hunks)
  • packages/features/insights/components/booking/MostBookedTeamMembersTable.tsx (1 hunks)
  • packages/features/insights/components/booking/MostCompletedBookings.tsx (1 hunks)
  • packages/features/insights/components/booking/index.ts (1 hunks)
  • packages/features/insights/server/trpc-router.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.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:

  • packages/features/insights/components/booking/MostBookedTeamMembersTable.tsx
  • packages/features/insights/components/booking/MostCompletedBookings.tsx
  • packages/features/insights/components/booking/LeastCompletedBookings.tsx
  • packages/features/insights/components/booking/LeastBookedTeamMembersTable.tsx
  • apps/web/modules/insights/insights-view.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:

  • packages/features/insights/components/booking/MostBookedTeamMembersTable.tsx
  • packages/features/insights/components/booking/MostCompletedBookings.tsx
  • packages/features/insights/components/booking/index.ts
  • packages/features/insights/components/booking/LeastCompletedBookings.tsx
  • packages/features/insights/components/booking/LeastBookedTeamMembersTable.tsx
  • apps/web/modules/insights/insights-view.tsx
  • packages/features/insights/server/trpc-router.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit Configuration File

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/features/insights/components/booking/MostBookedTeamMembersTable.tsx
  • packages/features/insights/components/booking/MostCompletedBookings.tsx
  • packages/features/insights/components/booking/index.ts
  • packages/features/insights/components/booking/LeastCompletedBookings.tsx
  • packages/features/insights/components/booking/LeastBookedTeamMembersTable.tsx
  • apps/web/modules/insights/insights-view.tsx
  • packages/features/insights/server/trpc-router.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:

  • packages/features/insights/components/booking/index.ts
  • packages/features/insights/server/trpc-router.ts
🧠 Learnings (2)
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • packages/features/insights/server/trpc-router.ts
📚 Learning: 2025-07-15T12:58:40.539Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/RoutingFunnel.tsx:15-17
Timestamp: 2025-07-15T12:58:40.539Z
Learning: In the insights routing funnel component (packages/features/insights/components/RoutingFunnel.tsx), the useColumnFilters exclusions are intentionally different from the general useInsightsParameters exclusions. RoutingFunnel specifically excludes only ["createdAt"] while useInsightsParameters excludes ["bookingUserId", "formId", "createdAt", "eventTypeId"]. This difference is by design.

Applied to files:

  • packages/features/insights/server/trpc-router.ts
🧬 Code Graph Analysis (6)
packages/features/insights/components/booking/MostBookedTeamMembersTable.tsx (1)
packages/features/insights/components/ChartCard.tsx (1)
  • ChartCard (16-58)
packages/features/insights/components/booking/MostCompletedBookings.tsx (2)
packages/features/insights/hooks/useInsightsBookingParameters.ts (1)
  • useInsightsBookingParameters (14-46)
apps/web/app/_trpc/trpc.ts (1)
  • trpc (7-7)
packages/features/insights/components/booking/LeastCompletedBookings.tsx (3)
packages/features/insights/components/booking/index.ts (1)
  • LeastCompletedTeamMembersTable (15-15)
packages/features/insights/hooks/useInsightsBookingParameters.ts (1)
  • useInsightsBookingParameters (14-46)
apps/web/app/_trpc/trpc.ts (1)
  • trpc (7-7)
packages/features/insights/components/booking/LeastBookedTeamMembersTable.tsx (1)
packages/features/insights/components/ChartCard.tsx (1)
  • ChartCard (16-58)
apps/web/modules/insights/insights-view.tsx (3)
packages/features/insights/components/booking/MostCompletedBookings.tsx (1)
  • MostCompletedTeamMembersTable (11-35)
packages/features/insights/components/booking/index.ts (2)
  • MostCompletedTeamMembersTable (14-14)
  • LeastCompletedTeamMembersTable (15-15)
packages/features/insights/components/booking/LeastCompletedBookings.tsx (1)
  • LeastCompletedTeamMembersTable (11-35)
packages/features/insights/server/trpc-router.ts (1)
packages/features/insights/server/raw-data.schema.ts (1)
  • bookingRepositoryBaseInputSchema (73-80)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Install dependencies / Yarn install & cache
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (6)
packages/features/insights/server/trpc-router.ts (1)

587-597: No change needed for completed‐bookings endpoint
The getMembersStatsWithCount method in InsightsBookingBaseService.ts only accepts a first argument of "all" | "cancelled" | "noShow" (defaulting to "all"). Passing "completed" would break the type signature. Since you’re already initializing the service with "completed" via createInsightsBookingService(ctx, input, "startTime", "completed"), using getMembersStatsWithCount("all", "DESC") correctly returns stats for completed bookings. Leave the code as is.

Likely an incorrect or invalid review comment.

packages/features/insights/components/booking/MostBookedTeamMembersTable.tsx (1)

31-31: LGTM: label now reflects “Most Bookings Scheduled”.

The translation key change aligns with the PR’s renaming objective and uses t(), as required by our TSX localization guideline.

packages/features/insights/components/booking/LeastBookedTeamMembersTable.tsx (1)

31-31: LGTM: label now reflects “Least Bookings Scheduled”.

Consistent with the renaming objective and uses t(). No concerns.

apps/web/modules/insights/insights-view.tsx (1)

21-22: LGTM – named exports and re-exports are correctly set up

Re-export verification confirms that both components are exposed from the booking index:

  • packages/features/insights/components/booking/index.ts
    • Line 14 exports MostCompletedTeamMembersTable
    • Line 15 exports LeastCompletedTeamMembersTable

✅ Approving code changes.

packages/features/insights/components/booking/LeastCompletedBookings.tsx (1)

11-35: Solid, idiomatic TRPC + localized ChartCard composition.
Component structure, named export, loading/null guards, and translation usage look good and consistent with existing insights widgets.

packages/features/insights/components/booking/MostCompletedBookings.tsx (1)

11-35: Mirrors LeastCompleted… pattern correctly; good reuse and localization.
The component follows the established insights pattern and uses the correct translation key.

Copy link
Contributor

@eunjae-lee eunjae-lee left a comment

Choose a reason for hiding this comment

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

Thanks for the work !

While this works, I don't want to add logic into this createInsightsBookingService() function as it's supposed be a direct translation of ctx and input into an instance of the service.

  1. Let's manipulate the date range at the component level.
    1-1. It should still keep startDate as-is (we don't want to query bookings that started years ago.)
    1-2. Let's modify manipulate endDate to be the current time

  2. The type of getMembersStatsWithCount method in InsightsBookingBaseService could have accepted type.

Then the frontend's date range + accepted type <- this is what we want as completed bookings.

Let me know what you think!


edit: also, could you re-order charts? this would look better ↓

Most Bookings Scheduled | Least Bookings Scheduled | Most Bookings Completed | Least Bookings Completed

Popular Events | Most Cancelled | Most No-Show

Highest Rated | Lowest Rated | Recent Ratings

@graphite-app graphite-app bot requested a review from a team August 22, 2025 14:11
@bandhan-majumder
Copy link
Contributor Author

bandhan-majumder commented Aug 22, 2025

@eunjae-lee

yeah you are correct. That is a more clean approach I think. Changes are made as per the suggestions.


off topic:
I had also found a way to do that in the getMembersStatsWithCount with like having

else if (type === "accepted") {
      additionalCondition = Prisma.sql`AND "endTime" < now()`;
    }

for "accepted" case. But that is not needed now as component is responsible for modifying endDate as current date and we are just adding the "accepted" type later on.

Copy link
Contributor

@eunjae-lee eunjae-lee left a comment

Choose a reason for hiding this comment

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

Left some comments.

Also regarding your comment, I wouldn't handle endTime with additionalCondition, then the condition for endTime in baseConditions will conflict with it.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/lib/server/service/InsightsBookingBaseService.ts (2)

925-931: Null-safe MD5 to avoid runtime errors and ensure consistency.

Elsewhere you guard with md5(user.email || ""). Mirror that here to avoid a possible null/undefined crash.

       return {
         userId: booking.userId,
         user,
-        emailMd5: md5(user.email),
+        emailMd5: md5(user.email || ""),
         count: booking.count,
       };
       return {
         userId: booking.userId,
         user,
-        emailMd5: md5(user.email),
+        emailMd5: md5(user.email || ""),
         rating: booking.rating,
         feedback: booking.ratingFeedback,
       };

Also applies to: 999-1004


804-816: Enforce “completed” invariant in the service layer

Don’t rely on callers (or the UI) to clamp endDate for completed bookings. Instead, ensure on the server that “accepted” bookings are only those whose end time has passed.

• In InsightsBookingBaseService.getMembersStatsWithCount, update the accepted branch to include a server-side time check:

   if (type === "cancelled") {
     additionalCondition = Prisma.sql`AND status = 'cancelled'`;
   } else if (type === "noShow") {
     additionalCondition = Prisma.sql`AND "noShowHost" = true`;
-  } else if (type === "accepted") {
-    additionalCondition = Prisma.sql`AND status = 'accepted'`;
+  } else if (type === "accepted") {
+    additionalCondition = Prisma.sql`
+      AND status = 'accepted'
+      AND "endTime" <= NOW()
+    `;
   }

• This guarantees that “completed” metrics (what callers label as “accepted”) always reflect bookings that have actually finished, regardless of input dateRange.
• All current TRPC endpoints (e.g. membersWithMostCompletedBookings and membersWithLeastCompletedBookings)—which pass "accepted"—will automatically benefit from this invariant.

♻️ Duplicate comments (1)
packages/lib/server/service/InsightsBookingBaseService.ts (1)

804-806: Accepted type support added — resolves prior review ask.

The union now includes "accepted" and the signature default remains "all". This addresses the earlier feedback about handling the accepted type.

🧹 Nitpick comments (3)
packages/lib/server/service/InsightsBookingBaseService.ts (3)

63-91: Strengthen schema typing for status to prevent invalid values slipping through.

status is declared as z.string() but represents BookingStatus. Use Prisma’s enum for compile-time safety and better validation.

-    status: z.string(), // BookingStatus enum
+    status: z.nativeEnum(Prisma.BookingStatus),

Optional: if there’s a well-defined set for timeStatus (e.g., "completed" | "rescheduled" | "cancelled" | "uncompleted"), consider a z.enum([...]) for it as well to catch typos early.


16-31: Avatar fallback may produce "/null/avatar.png" when username is null.

Guard username to avoid broken URLs until the AVATAR_FALLBACK migration lands.

-      avatarUrl: user.avatarUrl || `/${user.username}/avatar.png`,
+      avatarUrl: user.avatarUrl || (user.username ? `/${user.username}/avatar.png` : "/avatar.png"),

If there’s a shared avatar fallback constant/util elsewhere, prefer reusing it here.


818-832: Potential index needs for new query shape.

The accepted/completed path will filter on userId + status/timeStatus + date target. To keep this snappy on large datasets, ensure DB has supporting indexes on the view’s base tables:

  • Composite index on BookingTimeStatusDenormalized(userId, status, timeStatus, startTime)
  • For hour-of-day stats: index on (status, startTime)

If the view is materialized/denormalized by a job, ensure those indexes exist on the underlying table/view as applicable.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1959603 and c5e21ac.

📒 Files selected for processing (3)
  • packages/features/insights/components/booking/LeastCompletedBookings.tsx (1 hunks)
  • packages/features/insights/components/booking/MostCompletedBookings.tsx (1 hunks)
  • packages/lib/server/service/InsightsBookingBaseService.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/features/insights/components/booking/MostCompletedBookings.tsx
  • packages/features/insights/components/booking/LeastCompletedBookings.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*Service.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Service files must include Service suffix, use PascalCase matching exported class, and avoid generic names (e.g., MembershipService.ts)

Files:

  • packages/lib/server/service/InsightsBookingBaseService.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:

  • packages/lib/server/service/InsightsBookingBaseService.ts
**/*.{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:

  • packages/lib/server/service/InsightsBookingBaseService.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/lib/server/service/InsightsBookingBaseService.ts
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache

eunjae-lee
eunjae-lee previously approved these changes Aug 25, 2025
Copy link
Contributor

@eunjae-lee eunjae-lee left a comment

Choose a reason for hiding this comment

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

Looks good. Thanks for the contribution !

@eunjae-lee eunjae-lee enabled auto-merge (squash) August 25, 2025 09:00
@eunjae-lee eunjae-lee disabled auto-merge August 25, 2025 09:08
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: 1

🧹 Nitpick comments (2)
apps/web/modules/insights/insights-view.tsx (2)

89-90: Clarify date basis: global UI filter = createdAt, completed charts = startTime.

To avoid user confusion, consider a subtle hint on the completed charts (e.g., “Based on event start time”) or updating the page’s date filter label/tooltip to indicate createdAt is used for scheduled charts while completed charts use startTime. This aligns with the accepted-booking approach (endDate <= now) and the learning to avoid SQL-level endTime constraints.

Suggested manual check:

  • Create a booking with createdAt in August but startTime in September.
  • Set the page date range to August only.
  • Expected: “Most/Least Bookings Scheduled” respect createdAt; “Completed” charts (none yet) use startTime and should not include September events until the range covers September and the booking has ended.

35-43: Prefer named export over default (module, not a page).

This module isn’t a top-level Next.js page/layout, so named exports are encouraged for tree-shaking and refactors.

Apply when low-risk to update import sites:

-export default function InsightsPage({ timeZone }: { timeZone: string }) {
+export function InsightsPage({ timeZone }: { timeZone: string }) {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c5e21ac and cd17408.

📒 Files selected for processing (4)
  • apps/web/modules/insights/insights-view.tsx (2 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/features/insights/server/trpc-router.ts (1 hunks)
  • packages/lib/server/service/InsightsBookingBaseService.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/lib/server/service/InsightsBookingBaseService.ts
  • apps/web/public/static/locales/en/common.json
  • packages/features/insights/server/trpc-router.ts
🧰 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/modules/insights/insights-view.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/modules/insights/insights-view.tsx
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • apps/web/modules/insights/insights-view.tsx
🧠 Learnings (1)
📓 Common learnings
Learnt from: bandhan-majumder
PR: calcom/cal.com#23192
File: packages/lib/server/service/InsightsBookingBaseService.ts:814-816
Timestamp: 2025-08-22T16:38:00.182Z
Learning: In the InsightsBookingBaseService (packages/lib/server/service/InsightsBookingBaseService.ts), when filtering for "accepted" bookings in getMembersStatsWithCount(), using `endTime <= now()` in the SQL condition should be avoided as it conflicts with existing date filtering logic. The components already handle completion filtering by setting `endDate: currentTime` in their query parameters, making additional SQL-level endTime filtering unnecessary and potentially problematic.
🧬 Code graph analysis (1)
apps/web/modules/insights/insights-view.tsx (8)
packages/features/insights/components/booking/MostCompletedBookings.tsx (1)
  • MostCompletedTeamMembersTable (15-51)
packages/features/insights/components/booking/index.ts (7)
  • MostCompletedTeamMembersTable (14-14)
  • LeastCompletedTeamMembersTable (15-15)
  • MostCancelledBookingsTables (10-10)
  • HighestNoShowHostTable (4-4)
  • PopularEventsTable (11-11)
  • HighestRatedMembersTable (5-5)
  • LowestRatedMembersTable (8-8)
packages/features/insights/components/booking/LeastCompletedBookings.tsx (1)
  • LeastCompletedTeamMembersTable (15-51)
packages/features/insights/components/booking/MostCancelledBookingsTables.tsx (1)
  • MostCancelledBookingsTables (11-35)
packages/features/insights/components/booking/HighestNoShowHostTable.tsx (1)
  • HighestNoShowHostTable (11-35)
packages/features/insights/components/booking/PopularEventsTable.tsx (1)
  • PopularEventsTable (10-47)
packages/features/insights/components/booking/HighestRatedMembersTable.tsx (1)
  • HighestRatedMembersTable (11-37)
packages/features/insights/components/booking/LowestRatedMembersTable.tsx (1)
  • LowestRatedMembersTable (11-37)
🔇 Additional comments (2)
apps/web/modules/insights/insights-view.tsx (2)

96-98: Popular events spans two columns — LGTM.

The wrapper with sm:col-span-2 is consistent with the earlier KPI/Chart layout approach and improves readability.


102-103: Move ratings to a separate grid — LGTM; validate empty-state layout.

Highest/Lowest rated tables render nothing on empty data. Please sanity-check that the grid still flows nicely when one or both are empty (RecentFeedbackTable should remain full-width in md:col-span-2 without awkward gaps).

Comment on lines +22 to +23
MostCompletedTeamMembersTable,
LeastCompletedTeamMembersTable,
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Completed-bookings components imported — looks good; verify wiring (exports, routes, locales).

The imports align with the PR goal to surface completed-bookings insights. Please run the quick checks below to ensure nothing’s dangling (public exports, TRPC routes, service filter, and locale keys).


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Check booking index exports for completed tables"
rg -nP '\bexport\s*\{[^}]*\bMostCompletedTeamMembersTable\b' packages/features/insights/components/booking/index.ts -C2
rg -nP '\bexport\s*\{[^}]*\bLeastCompletedTeamMembersTable\b' packages/features/insights/components/booking/index.ts -C2

echo -e "\n2) Check TRPC endpoints exist"
rg -n 'membersWithMostCompletedBookings|membersWithLeastCompletedBookings' packages/features/insights/server/trpc-router.ts -C3

echo -e "\n3) Check service supports accepted status in getMembersStatsWithCount()"
rg -nP '(?s)\bgetMembersStatsWithCount\b.*status\s*=\s*\'?accepted\'?' packages/lib/server/service/InsightsBookingBaseService.ts || true

echo -e "\n4) Ensure new locale keys are present (EN at minimum) and old keys unused"
rg -n '"(most|least)_bookings_(scheduled|completed)"' apps/web/public/static/locales/en/common.json
# Report any lingering usages of removed keys outside locale files
rg -n 'most_booked_members|least_booked_members' -g '!apps/web/public/static/locales/**' || true

Length of output: 2033


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "3) Check service supports accepted status in getMembersStatsWithCount()"
rg -nP "(?s)\bgetMembersStatsWithCount\b.*status\s*=\s*['\"]accepted['\"]" packages/lib/server/service/InsightsBookingBaseService.ts || true

echo -e "\n4) Ensure new locale keys are present (EN at minimum) and old keys unused"
rg -n '"most_bookings_scheduled"' apps/web/public/static/locales/en/common.json || true
rg -n '"most_bookings_completed"' apps/web/public/static/locales/en/common.json || true
rg -n '"least_bookings_scheduled"' apps/web/public/static/locales/en/common.json || true
rg -n '"least_bookings_completed"' apps/web/public/static/locales/en/common.json || true

echo -e "\nChecking for old keys usages outside locale files"
rg -n 'most_booked_members|least_booked_members' -g '!apps/web/public/static/locales/**' || true

Length of output: 1556


Action Required: Address missing status filter & update locale usages

Verified that imports and TRPC endpoints are wired correctly. However, two critical issues need your attention:

• Service filter – In packages/lib/server/service/InsightsBookingBaseService.ts, the getMembersStatsWithCount() method currently does not filter bookings by status 'accepted'. Please add or verify a line such as:

status: 'accepted',

within the query options passed to your data layer so only completed (accepted) bookings are counted.
• Stale locale keys – Although the new keys (most_bookings_completed, least_bookings_completed, etc.) are present in
apps/web/public/static/locales/en/common.json, the old keys are still referenced in:

  • i18n.lock (lines 2170–2171):
    most_booked_members
    least_booked_members
  • packages/emails/src/templates/MonthlyDigestEmail.tsx:160:
    <p style={{ fontWeight: 500 }}>
      {props.language("most_booked_members")}
    </p>

Update these usages to the new keys (most_bookings_completed and least_bookings_completed), then regenerate your i18n lock file.

Once these fixes are in place, rerun your locale and service tests to confirm everything surfaces correctly.

🤖 Prompt for AI Agents
In apps/web/modules/insights/insights-view.tsx around lines 22–23 (and related
service code in packages/lib/server/service/InsightsBookingBaseService.ts where
getMembersStatsWithCount is implemented), add a status filter so the data layer
only counts completed bookings by ensuring the query options include status:
'accepted'; also update stale locale key usages: replace most_booked_members →
most_bookings_completed and least_booked_members → least_bookings_completed in
packages/emails/src/templates/MonthlyDigestEmail.tsx (around line ~160) and
remove/update the same keys in i18n.lock (lines ~2170–2171), then regenerate the
i18n lock file and rerun locale and service tests to validate the changes.

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
apps/web/public/static/locales/ro/common.json (1)

2173-2174: Add missing Romanian translations for new Insight keys

The following four i18n keys are present in all other locales but missing in apps/web/public/static/locales/ro/common.json, causing an English fallback for Romanian users:

  • most_bookings_scheduled
  • least_bookings_scheduled
  • most_bookings_completed
  • least_bookings_completed

Please insert them alongside the existing Insights entries (around bookings_by_hour, most_booked_members, least_booked_members):

  "bookings_by_hour": "Rezervări pe oră",
+ "most_bookings_scheduled": "Cele mai multe rezervări programate",
+ "least_bookings_scheduled": "Cele mai puține rezervări programate",
+ "most_bookings_completed": "Cele mai multe rezervări finalizate",
+ "least_bookings_completed": "Cele mai puține rezervări finalizate",
  "most_booked_members": "Cei mai rezervați membri",
  "least_booked_members": "Cei mai puțin rezervați membri",

Locations needing update:

  • File: apps/web/public/static/locales/ro/common.json
  • Insert between lines ~2170–2175, immediately after "bookings_by_hour": "Rezervări pe oră".
apps/web/public/static/locales/tr/common.json (1)

2173-2176: Add missing Insights translation keys to Turkish locale

Verification shows that only en/common.json contains the new keys, while apps/web/public/static/locales/tr/common.json (and every other locale) is missing them. Without these entries, the UI will fallback to English or display raw keys on the /insights page, causing a user-facing regression. Please add the following four keys immediately above the sentinel line in apps/web/public/static/locales/tr/common.json:

@@ -2172,6 +2172,10
   "usage_based_expiration_description_plural": "Bu bağlantı {{count}} rezervasyon için kullanılabilir",
+  "most_bookings_scheduled": "En Çok Planlanan Rezervasyonlar",
+  "least_bookings_scheduled": "En Az Planlanan Rezervasyonlar",
+  "most_bookings_completed": "En Çok Tamamlanan Rezervasyonlar",
+  "least_bookings_completed": "En Az Tamamlanan Rezervasyonlar",
   "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni dizelerinizi yukarıya ekleyin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"

– File: apps/web/public/static/locales/tr/common.json
– Lines: ~2173–2176

(The same keys are currently missing across all other locale files as well; please coordinate with localization teams to propagate translations in those languages.)

apps/web/public/static/locales/vi/common.json (1)

2171-2176: Add missing Insights chart keys to all locale files

The four new chart title keys introduced in en/common.jsonmost_bookings_scheduled, least_bookings_scheduled, most_bookings_completed, and least_bookings_completed—are currently present only in English. Our script confirms they’re missing in Vietnamese and every other locale, which will cause runtime fallbacks across the board. Please add these keys (with appropriate translations) to each apps/web/public/static/locales/<locale>/common.json.

Key locations to update:

  • apps/web/public/static/locales/vi/common.json
  • apps/web/public/static/locales/ar/common.json
  • apps/web/public/static/locales/az/common.json
  • …and so on for each directory under apps/web/public/static/locales except en

Suggested diff for Vietnamese (insert immediately after "bookings_by_hour"):

   "bookings_by_hour": "Lịch hẹn theo giờ",
+  "most_bookings_scheduled": "Lịch hẹn được lên lịch nhiều nhất",
+  "least_bookings_scheduled": "Lịch hẹn được lên lịch ít nhất",
+  "most_bookings_completed": "Lịch hẹn hoàn thành nhiều nhất",
+  "least_bookings_completed": "Lịch hẹn hoàn thành ít nhất",
   "most_booked_members": "Thành viên được đặt nhiều nhất",
   "least_booked_members": "Thành viên được đặt ít nhất",

Apply analogous inserts—with correct translations—in every common.json under apps/web/public/static/locales/* so all UIs stay in sync with en.

apps/web/public/static/locales/bg/common.json (1)

2169-2186: Ensure BG locale includes new keys & update components to use them

The BG translation is missing all four of the new booking‐breakdown keys, and there’s still one lingering reference to an old key in the email template. Please:

• In apps/web/public/static/locales/bg/common.json, add the following entries (with appropriate Bulgarian translations):

 {
   …  
+    "most_bookings_scheduled": "<translation…>",
+    "least_bookings_scheduled": "<translation…>",
+    "most_bookings_completed": "<translation…>",
+    "least_bookings_completed": "<translation…>",
   …
 }

• In packages/emails/src/templates/MonthlyDigestEmail.tsx (line 160), replace:

- props.language("most_booked_members")
+ props.language("most_bookings_scheduled")

(or the appropriate new key for this context; ensure you also update any least_booked_members usage likewise)

You may keep the old keys in the locale file for backward compatibility, but all UI/TSX components should be refactored to use the new keys.

🧹 Nitpick comments (3)
apps/web/public/static/locales/ru/common.json (1)

2169-2176: Add missing booking translation keys to Russian locale

The locale comparison shows that the following keys used by the new Insights UI are absent in apps/web/public/static/locales/ru/common.json:

  • most_bookings_scheduled
  • least_bookings_scheduled
  • most_bookings_completed
  • least_bookings_completed

Without these, users will see fallbacks or raw keys in the UI. Please insert them near the existing Insights strings (e.g., after "least_booked_members"):

--- a/apps/web/public/static/locales/ru/common.json
+++ b/apps/web/public/static/locales/ru/common.json
@@ ... "least_booked_members": "Наименее востребованные",
+  "most_bookings_scheduled": "Наибольшее количество запланированных бронирований",
+  "least_bookings_scheduled": "Наименьшее количество запланированных бронирований",
+  "most_bookings_completed": "Наибольшее количество завершённых бронирований",
+  "least_bookings_completed": "Наименьшее количество завершённых бронирований",
apps/web/public/static/locales/no/common.json (1)

3421-3422: Add missing Norwegian translations for new insights keys

The following four keys introduced in the PR are missing from the Norwegian locale, causing a fallback to English in the UI. Please insert them above the ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS guard in apps/web/public/static/locales/no/common.json:

   "usage_based_expiration_description_plural": "Denne lenken kan brukes for {{count}} bestillinger",
+  "most_bookings_scheduled": "Flest planlagte bookinger",
+  "least_bookings_scheduled": "Færrest planlagte bookinger",
+  "most_bookings_completed": "Flest fullførte bookinger",
+  "least_bookings_completed": "Færrest fullførte bookinger",
   "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Legg til dine nye strenger over her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
  • File: apps/web/public/static/locales/no/common.json
  • Insert above the ADD_NEW_STRINGS… line at the end of the file.

This ensures the UI displays proper Norwegian translations rather than defaulting to English.

apps/web/public/static/locales/bg/common.json (1)

2171-2176: Add the four new Insights titles to keep BG locale in sync with EN and the new charts

The PR introduces/renames charts to “Most/Least Bookings Scheduled” and adds “Most/Least Bookings Completed”, with EN keys present. BG locale is missing these keys, so users on BG will see EN fallbacks or raw keys. Add the strings near the existing insights keys.

Apply this diff (place above the “ADD_NEW_STRINGS…” sentinel and alongside the existing insights keys):

   "most_booked_members": "Най-резервирани",
   "least_booked_members": "Най-малко резервирани",
+  "most_bookings_scheduled": "Най-много планирани резервации",
+  "least_bookings_scheduled": "Най-малко планирани резервации",
+  "most_bookings_completed": "Най-много завършени резервации",
+  "least_bookings_completed": "Най-малко завършени резервации",
   "events_created": "Създадени събития",
   "events_completed": "Завършени събития",
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between cd17408 and 3ad481d.

📒 Files selected for processing (33)
  • apps/web/public/static/locales/ar/common.json (1 hunks)
  • apps/web/public/static/locales/az/common.json (1 hunks)
  • apps/web/public/static/locales/bg/common.json (1 hunks)
  • apps/web/public/static/locales/bn/common.json (1 hunks)
  • apps/web/public/static/locales/ca/common.json (1 hunks)
  • apps/web/public/static/locales/cs/common.json (1 hunks)
  • apps/web/public/static/locales/da/common.json (1 hunks)
  • apps/web/public/static/locales/el/common.json (1 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • apps/web/public/static/locales/es-419/common.json (1 hunks)
  • apps/web/public/static/locales/et/common.json (1 hunks)
  • apps/web/public/static/locales/eu/common.json (1 hunks)
  • apps/web/public/static/locales/fi/common.json (1 hunks)
  • apps/web/public/static/locales/he/common.json (1 hunks)
  • apps/web/public/static/locales/hu/common.json (1 hunks)
  • apps/web/public/static/locales/ja/common.json (1 hunks)
  • apps/web/public/static/locales/km/common.json (1 hunks)
  • apps/web/public/static/locales/ko/common.json (1 hunks)
  • apps/web/public/static/locales/nl/common.json (1 hunks)
  • apps/web/public/static/locales/no/common.json (1 hunks)
  • apps/web/public/static/locales/pt-BR/common.json (1 hunks)
  • apps/web/public/static/locales/pt/common.json (1 hunks)
  • apps/web/public/static/locales/ro/common.json (1 hunks)
  • apps/web/public/static/locales/ru/common.json (1 hunks)
  • apps/web/public/static/locales/sk-SK/common.json (1 hunks)
  • apps/web/public/static/locales/sr/common.json (1 hunks)
  • apps/web/public/static/locales/sv/common.json (1 hunks)
  • apps/web/public/static/locales/ta/common.json (1 hunks)
  • apps/web/public/static/locales/tr/common.json (1 hunks)
  • apps/web/public/static/locales/uk/common.json (1 hunks)
  • apps/web/public/static/locales/vi/common.json (1 hunks)
  • apps/web/public/static/locales/zh-CN/common.json (1 hunks)
  • apps/web/public/static/locales/zh-TW/common.json (1 hunks)
✅ Files skipped from review due to trivial changes (9)
  • apps/web/public/static/locales/sv/common.json
  • apps/web/public/static/locales/ar/common.json
  • apps/web/public/static/locales/da/common.json
  • apps/web/public/static/locales/nl/common.json
  • apps/web/public/static/locales/eu/common.json
  • apps/web/public/static/locales/az/common.json
  • apps/web/public/static/locales/ja/common.json
  • apps/web/public/static/locales/et/common.json
  • apps/web/public/static/locales/he/common.json
🚧 Files skipped from review as they are similar to previous changes (15)
  • apps/web/public/static/locales/zh-CN/common.json
  • apps/web/public/static/locales/ta/common.json
  • apps/web/public/static/locales/pt-BR/common.json
  • apps/web/public/static/locales/es-419/common.json
  • apps/web/public/static/locales/bn/common.json
  • apps/web/public/static/locales/cs/common.json
  • apps/web/public/static/locales/ko/common.json
  • apps/web/public/static/locales/fi/common.json
  • apps/web/public/static/locales/ca/common.json
  • apps/web/public/static/locales/uk/common.json
  • apps/web/public/static/locales/el/common.json
  • apps/web/public/static/locales/sr/common.json
  • apps/web/public/static/locales/km/common.json
  • apps/web/public/static/locales/zh-TW/common.json
  • apps/web/public/static/locales/en/common.json
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: bandhan-majumder
PR: calcom/cal.com#23192
File: packages/lib/server/service/InsightsBookingBaseService.ts:814-816
Timestamp: 2025-08-22T16:38:00.182Z
Learning: In the InsightsBookingBaseService (packages/lib/server/service/InsightsBookingBaseService.ts), when filtering for "accepted" bookings in getMembersStatsWithCount(), using `endTime <= now()` in the SQL condition should be avoided as it conflicts with existing date filtering logic. The components already handle completion filtering by setting `endDate: currentTime` in their query parameters, making additional SQL-level endTime filtering unnecessary and potentially problematic.
🔇 Additional comments (10)
apps/web/public/static/locales/pt/common.json (1)

2173-2175: Retain legacy i18n keys used by the monthly-digest email

The grep output confirms that the old keys are still in active use and must remain alongside the newly introduced ones:

  • In packages/emails/src/templates/MonthlyDigestEmail.tsx (around line 160) the template calls props.language("most_booked_members") (and similarly for the “least_booked_members” label).
  • Both keys are present in the auto-generated i18n.lock and populated across every locale’s common.json.

Because the email template depends on these legacy labels, we should leave them (and their translations) intact for now. Once the email views are migrated to the new keys, we can safely drop the old entries in a dedicated cleanup PR.

apps/web/public/static/locales/hu/common.json (1)

3422-3423: Missing Hungarian translations for new insight labels

The PR adds new insight keys (most_bookings_scheduled, least_bookings_scheduled, most_bookings_completed, least_bookings_completed) to en/common.json but these are not present in hu/common.json, so Hungarian users will see English fallbacks.

• File apps/web/public/static/locales/hu/common.json is missing:

  • most_bookings_scheduled
  • least_bookings_scheduled
  • most_bookings_completed
  • least_bookings_completed

Please either add Hungarian translations for these keys in a follow-up or confirm that English fallbacks are acceptable for the Hungarian locale.

apps/web/public/static/locales/ro/common.json (1)

3422-3422: LGTM: trailing newline added

File now ends with a newline (POSIX-friendly); no functional changes introduced.

apps/web/public/static/locales/ru/common.json (1)

3422-3422: No-op formatting change looks good.

End-of-file newline addition only. No runtime impact.

apps/web/public/static/locales/no/common.json (1)

3422-3422: EOF newline added — OK

Trailing newline at EOF is harmless and matches common formatting conventions.

apps/web/public/static/locales/tr/common.json (1)

3422-3422: LGTM: harmless EOF newline change.

No functional impact. However, see next comment regarding missing new i18n keys required by this PR.

apps/web/public/static/locales/vi/common.json (1)

3422-3422: No-op: only a trailing newline was added.

This is harmless and improves POSIX-friendliness. Nothing else functionally changes in this file.

apps/web/public/static/locales/bg/common.json (1)

3421-3422: No-op change (newline at EOF) — OK

Only a trailing newline/closing brace touched here. No functional impact.

apps/web/public/static/locales/sk-SK/common.json (2)

3422-3422: Missing SK strings added—no further action needed

Verification confirms that all four new Insight chart i18n keys (most_bookings_scheduled, least_bookings_scheduled, most_bookings_completed, least_bookings_completed) are present in every common.json locale file. Thanks for adding these above the sentinel.


2173-2175: Translation keys update – keep in use, retire unused

  • Found usage of the old key in the email template:
    • packages/emails/src/templates/MonthlyDigestEmail.tsx:160
    {props.language("most_booked_members")}
  • No code references least_booked_members outside the locale files.

Action items:

  • Retain "most_booked_members" as it’s still in use.
  • Remove "least_booked_members" in a follow-up i18n cleanup, since it’s unused.
  • When you migrate to the new keys (most_bookings_scheduled / least_bookings_scheduled) across all locales, mark the old keys deprecated before finally removing them.

}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

No functional change here, but PT locale is missing the four new Insights keys (will fall back to EN).

The only diff in this file is a trailing newline. However, the PR adds four new locale keys in EN for the chart renames/new charts:

  • most_bookings_scheduled
  • least_bookings_scheduled
  • most_bookings_completed
  • least_bookings_completed

They are absent in this PT file, so the UI will render English for PT users. Please add the PT translations right above the sentinel line to avoid merge conflicts. Suggested additions:

   "usage_based_expiration_description_plural": "Este link pode ser usado para {{count}} agendamentos",
+  "most_bookings_scheduled": "Mais reservas agendadas",
+  "least_bookings_scheduled": "Menos reservas agendadas",
+  "most_bookings_completed": "Mais reservas concluídas",
+  "least_bookings_completed": "Menos reservas concluídas",
   "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
 }

These follow existing terminology in this file (“Reservas”, “agendadas”, “concluídas”) for consistency.

I can propagate the same four keys to other locales touched by this PR to keep i18n coverage consistent—want me to open a follow-up patch?

Run this to confirm the new keys exist in EN and are missing in PT, and to spot any other gaps:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

EN=apps/web/public/static/locales/en/common.json
PT=apps/web/public/static/locales/pt/common.json

# Ensure files exist
test -f "$EN" && test -f "$PT"

echo "New EN insight keys and their presence in PT:"
for k in most_bookings_scheduled least_bookings_scheduled most_bookings_completed least_bookings_completed; do
  echo "- $k: EN=$(jq -r --arg k "$k" '.[$k] // "MISSING"' "$EN")"
  echo "       PT=$(jq -r --arg k "$k" '.[$k] // "MISSING"' "$PT")"
done

echo
echo "Other missing PT keys compared to EN (top 20):"
comm -23 <(jq -r 'keys[]' "$EN" | sort) <(jq -r 'keys[]' "$PT" | sort) | head -20

Length of output: 2637


Add missing PT translations for new Insights keys

Verified that the following keys exist in apps/web/public/static/locales/en/common.json but are absent in apps/web/public/static/locales/pt/common.json, causing English fallbacks for PT users. Please add them above the ADD_NEW_STRINGS_ABOVE_THIS_LINE sentinel:

• File: apps/web/public/static/locales/pt/common.json
Insert these lines between "usage_based_expiration_description_plural" and the sentinel:

   "usage_based_expiration_description_plural": "Este link pode ser usado para {{count}} agendamentos",
+  "most_bookings_scheduled": "Mais reservas agendadas",
+  "least_bookings_scheduled": "Menos reservas agendadas",
+  "most_bookings_completed": "Mais reservas concluídas",
+  "least_bookings_completed": "Menos reservas concluídas",
   "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"

These translations follow the existing terminology (“Reservas”, “agendadas”, “concluídas”) for consistency.

Let me know if you’d like me to propagate these additions to the other locales touched by this PR.

Committable suggestion skipped: line range outside the PR's diff.

@eunjae-lee eunjae-lee enabled auto-merge (squash) August 25, 2025 09:31
Copy link
Contributor

github-actions bot commented Aug 25, 2025

E2E results are ready!

@eunjae-lee eunjae-lee merged commit efca905 into calcom:main Aug 25, 2025
56 of 62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community Created by Linear-GitHub Sync consumer 🧹 Improvements Improvements to existing features. Mostly UX/UI insights area: insights, analytics ready-for-e2e 💻 refactor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve Most Booked & Least Booked
2 participants