Skip to content

Conversation

@sean-brydon
Copy link
Member

@sean-brydon sean-brydon commented Aug 26, 2025

What does this PR do?

Updates the organization upgrade tip on the /teams page to show when users have one team instead of requiring two or more teams. Also adds conditional copy to use singular phrasing when there's exactly one team.

Changes:

  • Modified the gating condition from ORG_MINIMUM_PUBLISHED_TEAMS_SELF_SERVE_HELPER_DIALOGUE (≥2 teams) to ≥1 team
  • Added conditional title and description for the first upgrade card:
    • 1 team: "You have one team" + singular-friendly description
    • 2+ teams: "You have a lot of teams" + existing plural description
  • Added new i18n keys: you_have_one_team and consider_consolidating_one_team_org
  • Removed unused import of ORG_MINIMUM_PUBLISHED_TEAMS_SELF_SERVE_HELPER_DIALOGUE

Link to Devin run: https://app.devin.ai/sessions/6e2c14a347914f67ab75f116f38816d6
Requested by: Sean (@sean-brydon)

Visual Demo (For contributors especially)

Screenshots will be added after local testing to show the upgrade tip with 1 team vs multiple teams.

CleanShot 2025-08-29 at 10 44 01 CleanShot 2025-08-29 at 10 44 09

How should this be tested?

  1. Setup: Ensure you have a user account with exactly 1 team
  2. Test 1 team scenario:
    • Navigate to /teams
    • Verify the organization upgrade tip appears
    • Confirm the title shows "You have one team"
    • Confirm the description uses singular phrasing
  3. Test multiple teams scenario:
    • Create/add a second team
    • Navigate to /teams
    • Verify the tip still appears with plural copy ("You have a lot of teams")
  4. Test zero teams: Verify the tip doesn't appear (existing behavior should be unchanged)

Checklist

  • Test with exactly 1 team to ensure tip appears with singular copy
  • Test with 2+ teams to ensure existing plural copy still works
  • Verify other locale files don't break due to missing translation keys
  • Confirm ORG_MINIMUM_PUBLISHED_TEAMS_SELF_SERVE_HELPER_DIALOGUE constant isn't referenced elsewhere
  • Visual verification that the UI renders correctly in both scenarios

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.

@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

Walkthrough

This change updates organization self-serve helper behavior and related copy. A constants update renames usage to ORG_MINIMUM_PUBLISHED_TEAMS_SELF_SERVE_HELPER_DIALOGUE and lowers its threshold from 2 to 1. TeamList.tsx adjusts the first helper Card to render singular vs. plural messaging based on team count (exactly one team vs. multiple). Two new English i18n keys are added: you_have_one_team and consider_consolidating_one_team_org. No logic beyond conditional text rendering and constant usage/value changes is modified.


📜 Recent 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 d5ef876 and f1c717e.

📒 Files selected for processing (2)
  • apps/web/public/static/locales/en/common.json (2 hunks)
  • packages/features/ee/teams/components/TeamList.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/public/static/locales/en/common.json
  • packages/features/ee/teams/components/TeamList.tsx
⏰ 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
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1756229864-teams-upgrade-tip-one-team

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 @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit 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:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit 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 @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @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.

@vercel
Copy link

vercel bot commented Aug 29, 2025

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

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Aug 29, 2025 9:51am
cal-eu Ignored Ignored Aug 29, 2025 9:51am

@Amit91848 Amit91848 marked this pull request as ready for review August 29, 2025 07:27
@graphite-app graphite-app bot requested a review from a team August 29, 2025 07:27
@dosubot dosubot bot added i18n area: i18n, translations teams area: teams, round robin, collective, managed event-types labels Aug 29, 2025
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 (1)
packages/features/ee/teams/components/TeamList.tsx (1)

61-66: Bug: Card may not render if first array item is MEMBER.

Current logic ties rendering to i === 0. If the first team is a MEMBER and a later team is admin/owner, the upgrade Card won’t show.

Apply this diff to render once for the first non-MEMBER team and fix UL semantics (li instead of div):

-        props.teams.map(
-          (team, i) =>
-            team.role !== "MEMBER" &&
-            i === 0 && (
-              <div className="bg-subtle p-4" key={team.id}>
-                <div className="grid-col-1 grid gap-2 md:grid-cols-3">
+        (() => {
+          const ownerTeam = props.teams.find((t) => t.role !== "MEMBER");
+          if (!ownerTeam) return null;
+          return (
+            <li className="bg-subtle p-4" key={ownerTeam.id}>
+              <div className="grid-col-1 grid gap-2 md:grid-cols-3">
                   <Card
-                    icon={<Icon name="building" className="h-5 w-5 text-red-700" />}
+                    icon={<Icon name="building" className="h-5 w-5 text-red-700" />}
                     variant="basic"
-                    title={props.teams.length === 1 ? t("you_have_one_team") : t("You have a lot of teams")}
+                    title={props.teams.length === 1 ? t("you_have_one_team") : t("You have a lot of teams")}
                     description={
-                      props.teams.length === 1
-                        ? t("consider_consolidating_one_team_org")
-                        : t(
-                            "Consider consolidating your teams in an organisation, unify billing, admin tools and analytics."
-                          )
+                      props.teams.length === 1
+                        ? t("consider_consolidating_one_team_org")
+                        : t(
+                            "Consider consolidating your teams in an organisation, unify billing, admin tools and analytics."
+                          )
                     }
                     actionButton={{
                       href: `/settings/organizations/new`,
                       child: t("set_up_your_organization"),
                       "data-testid": "setup_your_org_action_button",
                     }}
                   />
                   <Card
                     icon={<Icon name="paintbrush" className="h-5 w-5 text-orange-700" />}
                     variant="basic"
                     title={t("Get a clean subdomain")}
                     description={t(
                       "Right now, team member URLs are all over the place. Get a beautiful link and turn every email address into a scheduling link: [email protected] → acme.cal.com/anna"
                     )}
                     actionButton={{
                       href: "https://www.youtube.com/watch?v=G0Jd2dp7064",
                       child: t("learn_more"),
                     }}
                   />
                   <Card
                     icon={<Icon name="chart-line" className="h-5 w-5 text-green-700" />}
                     variant="basic"
                     title={t("Admin tools and analytics")}
                     description={t(
                       "As an organization owner, you are in charge of every team account. You can make changes with admin-only tools and see organization wide analytics in one place."
                     )}
                     actionButton={{
                       href: "https://go.cal.com/quote",
                       child: t("learn_more"),
                     }}
                   />
                 </div>
-              </div>
-            )
-        )}
+            </li>
+          );
+        })()}
🧹 Nitpick comments (1)
packages/features/ee/teams/components/TeamList.tsx (1)

71-78: Localize plural copy with keys and unify en-US spelling.

Consider adding keys for the plural variants and switching “organisation” → “organization” to match en/common.json style.

Example:

- title={props.teams.length === 1 ? t("you_have_one_team") : t("You have a lot of teams")}
+ title={props.teams.length === 1 ? t("you_have_one_team") : t("you_have_many_teams")}
...
- : t("Consider consolidating your teams in an organisation, unify billing, admin tools and analytics.")
+ : t("consider_consolidating_many_teams_org")

Then add those keys to en/common.json near the sentinel.

📜 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 191db51 and d5ef876.

📒 Files selected for processing (3)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/features/ee/teams/components/TeamList.tsx (2 hunks)
  • packages/lib/constants.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.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/constants.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/constants.ts
  • packages/features/ee/teams/components/TeamList.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:

  • packages/lib/constants.ts
  • packages/features/ee/teams/components/TeamList.tsx
**/*.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/ee/teams/components/TeamList.tsx
⏰ 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 (2)
packages/lib/constants.ts (1)

181-181: No leftover usages of the old constant. The ripgrep search for ORG_MINIMUM_PUBLISHED_TEAMS_SELF_SERVE_DIALOGUE returned zero matches, confirming the rename is complete.

packages/features/ee/teams/components/TeamList.tsx (1)

3-3: All usages migrated to HELPER constant
Search confirms only ORG_MINIMUM_PUBLISHED_TEAMS_SELF_SERVE_HELPER_DIALOGUE is imported/used; no legacy identifier remains.

description={
props.teams.length === 1
? t("consider_consolidating_one_team_org")
: t(
Copy link
Contributor

Choose a reason for hiding this comment

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

extract this? "Consider consolidating your teams in an organisation, unify billing, admin tools and analytics."

@eunjae-lee eunjae-lee enabled auto-merge (squash) August 29, 2025 09:55
@eunjae-lee eunjae-lee merged commit e7779bb into main Aug 29, 2025
37 of 38 checks passed
@eunjae-lee eunjae-lee deleted the devin/1756229864-teams-upgrade-tip-one-team branch August 29, 2025 10:11
@github-actions
Copy link
Contributor

E2E results are ready!

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

Labels

consumer core area: core, team members only i18n area: i18n, translations ready-for-e2e teams area: teams, round robin, collective, managed event-types

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants