Skip to content

Surface team seat mismatch UX#506

Merged
AnthonyRonning merged 4 commits into
masterfrom
team-seat-mismatch-ux
May 21, 2026
Merged

Surface team seat mismatch UX#506
AnthonyRonning merged 4 commits into
masterfrom
team-seat-mismatch-ux

Conversation

@AnthonyRonning
Copy link
Copy Markdown
Contributor

@AnthonyRonning AnthonyRonning commented May 6, 2026

Summary

Adds persistent team seat mismatch detection and alerting across the app when team members exceed purchased seats.

New files:

  • utils/teamSeats.ts — Pure helpers (getTeamSeatCounts, getTeamSeatMismatch, formatTeamSeatMismatchMessage) that normalize seat counts from multiple API fields and detect overage via client-side count comparison OR the server's seat_limit_exceeded flag.
  • billing/billingPortal.ts — Shared openBillingPortal() helper (replaces duplicated platform-specific logic in TeamInviteDialog).
  • components/team/TeamSeatMismatchAlert.tsx — Fixed-position toast alert rendered at app root; shows admin/member-appropriate messaging with a "Manage Team" / "Team Info" CTA.

Modified files:

  • AccountMenu — Badge changes from warning (Setup Required) to destructive (Paused) when seat mismatch detected.
  • TeamDashboard — Admin view gets mismatch banner with "Manage Members" and "Add Seats" buttons; member view gets read-only warning. Seat usage bar turns destructive on mismatch. Invite button disabled during mismatch.
  • TeamInviteDialog — Billing portal logic replaced with shared helper; type="button" added to prevent form submission; canOpenBillingPortal check tightened.
  • types/team.tsTeamStatus extended with billed_seat_count and team_member_count.
  • app.tsx — Renders <TeamSeatMismatchAlert /> at app root.

Bug fixes from review:

  • Added memberCount > billedSeatCount guard to both formatTeamSeatMismatchMessage and the alert summary to prevent contradictory display (e.g. "3 members, 5 paid seats" alongside "more members than paid seats") when seat_limit_exceeded is stale.
  • Added type="button" to billing CTA in invite dialog to prevent it from also submitting the invite form.

Review & Testing Checklist for Human

  • Verify mismatch alert with a real team account — Requires a team where seat_limit_exceeded is true or team_member_count > billed_seat_count. Confirm the fixed-position alert appears, shows correct counts, and the "Manage Team" button opens the team dialog.
  • Verify alert does NOT appear for healthy teams — Log in with a team account where seats are sufficient and confirm no alert renders.
  • Test billing portal from all entry points — Dashboard "Add Seats" button, invite dialog "Manage Subscription" button. Confirm portal opens externally on desktop/mobile and that billingStatus + teamStatus queries refresh afterward.
  • Check admin vs member experience — Admin should see "Manage Team" + "Add Seats" + "Manage Members" actions. Non-admin should see "Team Info" + read-only warning asking them to contact their admin.
  • Verify canOpenBillingPortal edge cases — The check changed from stripe_customer_id !== null to !!stripe_customer_id with fallback to has_team_subscription. Confirm users without Stripe accounts don't see billing buttons.

Recommended test plan: Use a team account, temporarily set seat_limit_exceeded: true server-side (or add more members than seats), and walk through all surfaces: app-level alert, account menu badge, team dashboard, and invite dialog.

Notes

  • The mismatch detection is dual-path: triggers on client-side count comparison (memberCount > billedSeatCount) OR the server's seat_limit_exceeded flag. When the server flag fires but exact counts aren't available or don't confirm overage, a generic message is shown without specific numbers.
  • Not tested end-to-end — requires a team account in a specific seat mismatch state that wasn't available during development.

Link to Devin session: https://app.devin.ai/sessions/3297c6fa90564002a802713f48b3e22c
Requested by: @AnthonyRonning

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds seat-count utilities and messaging, an openBillingPortal helper, a TeamSeatMismatchAlert component, and UI changes (AccountMenu, TeamDashboard, TeamInviteDialog, app) to detect and surface when team members exceed purchased seats.

Changes

Team Seat Mismatch Detection & Billing Integration

Layer / File(s) Summary
Data Shape
frontend/src/types/team.ts
TeamStatus extended with billed_seat_count and team_member_count.
Utility Calculation
frontend/src/utils/teamSeats.ts
New types TeamSeatCounts and TeamSeatMismatch with helpers getTeamSeatCounts, getTeamSeatMismatch, and formatTeamSeatMismatchMessage.
Billing Portal Helper
frontend/src/billing/billingPortal.ts
New openBillingPortal fetches portal URL from billing service and opens it externally.
Alert component
frontend/src/components/team/TeamSeatMismatchAlert.tsx
New component queries team status, computes mismatch, and renders a fixed destructive alert with admin/member messaging and a TeamManagementDialog toggle.
Account menu wiring
frontend/src/components/AccountMenu.tsx
Imports mismatch helper, computes showTeamAttentionAlert, updates account badge and Manage Team badge to show Paused/Setup Required states.
Dashboard UX & billing flow
frontend/src/components/team/TeamDashboard.tsx
Computes seat metrics, shows admin/member banners, colors usage bar on mismatch, adds member-section navigation, and implements handleOpenBilling to open portal and refresh queries.
Invite dialog flow
frontend/src/components/team/TeamInviteDialog.tsx
Replaces platform-specific portal open with openBillingPortal, clamps seatsAvailable, computes canOpenBillingPortal, and invalidates queries after opening.
App integration
frontend/src/app.tsx
Renders <TeamSeatMismatchAlert /> in the app root after DeepLinkHandler.

Sequence Diagram

sequenceDiagram
    participant App as App
    participant Alert as TeamSeatMismatchAlert
    participant BillingService as BillingService
    participant PortalHelper as openBillingPortal
    participant Browser as ExternalBrowser
    participant Dashboard as TeamDashboard

    App->>Alert: render component
    Alert->>BillingService: getTeamStatus()
    BillingService-->>Alert: teamStatus
    Alert->>Alert: compute mismatch (getTeamSeatMismatch)
    alt Mismatch detected
        Alert->>App: render banner + "Manage" button
    end

    Dashboard->>PortalHelper: handleOpenBilling()
    PortalHelper->>BillingService: getPortalUrl()
    BillingService-->>PortalHelper: portalUrl
    PortalHelper->>Browser: openExternalUrl(portalUrl)
    Browser-->>Dashboard: user manages subscription externally
    Dashboard->>BillingService: invalidate billingStatus & teamStatus
    BillingService-->>Dashboard: refreshed data
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Poem

🐰 I count the seats beneath the moonlit beam,

When paid seats lag behind the team, I scream a banner bright and keen,
"Manage members" or "Add seats" — a click to mend the seam,
The rabbit cheers as teams align and billing hums serene.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Surface team seat mismatch UX' directly and clearly describes the main change: adding user-facing UI components and alerts to communicate team seat mismatches, which is the primary focus of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch team-seat-mismatch-ux

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 6, 2026

Deploying maple with  Cloudflare Pages  Cloudflare Pages

Latest commit: e43eb88
Status: ✅  Deploy successful!
Preview URL: https://71a3af4d.maple-ca8.pages.dev
Branch Preview URL: https://team-seat-mismatch-ux.maple-ca8.pages.dev

View logs

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@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)
frontend/src/components/team/TeamInviteDialog.tsx (1)

188-197: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Mark the billing CTA as type="button".

This button lives inside the invite form, so clicking it also triggers handleInvite() today.
That can surface a bogus validation error while the user is trying to open billing.

💡 Suggested fix
                 {canOpenBillingPortal && (
                   <Button
+                    type="button"
                     variant="outline"
                     size="sm"
                     className="w-full"
                     onClick={handleManageSubscription}
                     disabled={isPortalLoading}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/team/TeamInviteDialog.tsx` around lines 188 - 197,
The billing CTA Button inside the invite form is missing an explicit type so
clicking it triggers the form submit (invoking handleInvite); update the Button
component rendering for the billing action (the instance that calls
handleManageSubscription and uses isPortalLoading/ CreditCard) to include
type="button" to prevent form submission and avoid spurious validation errors.
🧹 Nitpick comments (2)
frontend/src/components/team/TeamSeatMismatchAlert.tsx (1)

9-9: ⚡ Quick win

Use the repo alias for this import.

Keeping new TSX imports on @/components/... avoids path churn when the component tree moves.

♻️ Suggested change
-import { TeamManagementDialog } from "./TeamManagementDialog";
+import { TeamManagementDialog } from "@/components/team/TeamManagementDialog";

As per coding guidelines, Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/team/TeamSeatMismatchAlert.tsx` at line 9, The import
in TeamSeatMismatchAlert.tsx uses a relative path; update the import of
TeamManagementDialog to use the repo path alias (rooted at `@/`) so it follows the
TypeScript/React guideline—replace the current import of TeamManagementDialog
with the alias-based import (e.g., import from
"@/components/team/TeamManagementDialog") so future file moves won't break
paths.
frontend/src/app.tsx (1)

18-18: ⚡ Quick win

Switch this new import to the @/ alias.

That keeps the app entrypoint aligned with the repo's TS import convention and avoids brittle
relative paths.

♻️ Suggested change
-import { TeamSeatMismatchAlert } from "./components/team/TeamSeatMismatchAlert";
+import { TeamSeatMismatchAlert } from "@/components/team/TeamSeatMismatchAlert";

As per coding guidelines, Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/app.tsx` at line 18, Replace the relative import of
TeamSeatMismatchAlert in frontend/src/app.tsx with the repository path-alias
form; locate the import statement importing TeamSeatMismatchAlert and change it
to use the "@/..." alias (which maps to ./src/) so the module is imported via
the alias rather than a relative path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/team/TeamInviteDialog.tsx`:
- Around line 35-38: The code currently sets seatsAvailable using only
teamStatus.seats_available and defaults missing data to 0, causing false "no
seats" when the API supplies billed_seat_count or team_member_count instead;
update the normalization logic used to compute seatsAvailable (the variable
computed from teamStatus) to derive available seats from the available fields in
order of preference: use teamStatus.seats_available if present, else compute
seats from teamStatus.billed_seat_count minus teamStatus.team_member_count (or
other business-rule delta) and clamp to Math.max(0, ...), and keep existing
usage sites (e.g., canOpenBillingPortal) unchanged so UI enables invites when
seats remain.

---

Outside diff comments:
In `@frontend/src/components/team/TeamInviteDialog.tsx`:
- Around line 188-197: The billing CTA Button inside the invite form is missing
an explicit type so clicking it triggers the form submit (invoking
handleInvite); update the Button component rendering for the billing action (the
instance that calls handleManageSubscription and uses isPortalLoading/
CreditCard) to include type="button" to prevent form submission and avoid
spurious validation errors.

---

Nitpick comments:
In `@frontend/src/app.tsx`:
- Line 18: Replace the relative import of TeamSeatMismatchAlert in
frontend/src/app.tsx with the repository path-alias form; locate the import
statement importing TeamSeatMismatchAlert and change it to use the "@/..." alias
(which maps to ./src/) so the module is imported via the alias rather than a
relative path.

In `@frontend/src/components/team/TeamSeatMismatchAlert.tsx`:
- Line 9: The import in TeamSeatMismatchAlert.tsx uses a relative path; update
the import of TeamManagementDialog to use the repo path alias (rooted at `@/`) so
it follows the TypeScript/React guideline—replace the current import of
TeamManagementDialog with the alias-based import (e.g., import from
"@/components/team/TeamManagementDialog") so future file moves won't break
paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b47fd06f-0741-41dc-94c1-2ea0da651265

📥 Commits

Reviewing files that changed from the base of the PR and between 715b13d and 712a1b1.

📒 Files selected for processing (8)
  • frontend/src/app.tsx
  • frontend/src/billing/billingPortal.ts
  • frontend/src/components/AccountMenu.tsx
  • frontend/src/components/team/TeamDashboard.tsx
  • frontend/src/components/team/TeamInviteDialog.tsx
  • frontend/src/components/team/TeamSeatMismatchAlert.tsx
  • frontend/src/types/team.ts
  • frontend/src/utils/teamSeats.ts

Comment on lines +35 to +38
const seatsAvailable = Math.max(0, teamStatus?.seats_available || 0);
const canOpenBillingPortal = billingStatus
? !!billingStatus.stripe_customer_id
: !!teamStatus?.has_team_subscription;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Normalize seat availability instead of defaulting missing data to 0.

This dialog still reads only teamStatus.seats_available. If the API returns the new
billed_seat_count / team_member_count fields but omits seats_available, this will render
0 available seats, disable invites, and push admins into the billing flow even when seats remain.

💡 Suggested fix
 import { getBillingService } from "@/billing/billingService";
 import { openBillingPortal } from "@/billing/billingPortal";
 import { useLocalState } from "@/state/useLocalState";
 import type { TeamStatus } from "@/types/team";
+import { getTeamSeatCounts } from "@/utils/teamSeats";
@@
-  const seatsAvailable = Math.max(0, teamStatus?.seats_available || 0);
+  const seatCounts = getTeamSeatCounts(teamStatus);
+  const seatsAvailable =
+    seatCounts.seatsAvailable ??
+    (seatCounts.memberCount !== null && seatCounts.billedSeatCount !== null
+      ? Math.max(0, seatCounts.billedSeatCount - seatCounts.memberCount)
+      : 0);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/team/TeamInviteDialog.tsx` around lines 35 - 38, The
code currently sets seatsAvailable using only teamStatus.seats_available and
defaults missing data to 0, causing false "no seats" when the API supplies
billed_seat_count or team_member_count instead; update the normalization logic
used to compute seatsAvailable (the variable computed from teamStatus) to derive
available seats from the available fields in order of preference: use
teamStatus.seats_available if present, else compute seats from
teamStatus.billed_seat_count minus teamStatus.team_member_count (or other
business-rule delta) and clamp to Math.max(0, ...), and keep existing usage
sites (e.g., canOpenBillingPortal) unchanged so UI enables invites when seats
remain.

Copy link
Copy Markdown

@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.

Caution

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

⚠️ Outside diff range comments (1)
frontend/src/utils/teamSeats.ts (1)

57-78: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use a neutral fallback when exact counts do not prove an overage.

If seat_limit_exceeded is true but the exact counts are present and memberCount <= billedSeatCount, this now skips the detailed branch and still falls through to a message claiming the team has more members than paid seats. That leaves the edge case misleading; the fallback should avoid asserting the cause unless the counts confirm it.

💡 Suggested change
   return audience === "admin"
-    ? "This team has more members than paid seats. Team usage is paused until seats are added or members are removed."
-    : "This team has more members than paid seats. Contact your team admin to add paid seats or remove members.";
+    ? "This team's seat usage needs attention. Team usage is paused until seats are added or members are removed."
+    : "This team's seat usage needs attention. Contact your team admin to review seats and membership.";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/utils/teamSeats.ts` around lines 57 - 78, The fallback message
wrongly asserts "more members than paid seats" even when mismatch.hasExactCounts
is true and the counts (mismatch.memberCount and mismatch.billedSeatCount) do
not indicate an overage; update the logic in the function that returns the team
seats message so if mismatch.hasExactCounts is true but memberCount <=
billedSeatCount it returns a neutral fallback (based on audience) rather than
the assertive overage string — locate the branch using mismatch.hasExactCounts,
mismatch.memberCount, mismatch.billedSeatCount and audience and add a
conditional to return a neutral message when exact counts contradict an overage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@frontend/src/utils/teamSeats.ts`:
- Around line 57-78: The fallback message wrongly asserts "more members than
paid seats" even when mismatch.hasExactCounts is true and the counts
(mismatch.memberCount and mismatch.billedSeatCount) do not indicate an overage;
update the logic in the function that returns the team seats message so if
mismatch.hasExactCounts is true but memberCount <= billedSeatCount it returns a
neutral fallback (based on audience) rather than the assertive overage string —
locate the branch using mismatch.hasExactCounts, mismatch.memberCount,
mismatch.billedSeatCount and audience and add a conditional to return a neutral
message when exact counts contradict an overage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 93529ee0-f452-4c15-96d2-f42d86723eda

📥 Commits

Reviewing files that changed from the base of the PR and between 712a1b1 and f549745.

📒 Files selected for processing (2)
  • frontend/src/components/team/TeamInviteDialog.tsx
  • frontend/src/utils/teamSeats.ts

AnthonyRonning and others added 3 commits May 20, 2026 22:44
Co-Authored-By: tony@opensecret.cloud <TonyGiorgio@protonmail.com>
Co-Authored-By: tony@opensecret.cloud <TonyGiorgio@protonmail.com>
@devin-ai-integration devin-ai-integration Bot force-pushed the team-seat-mismatch-ux branch from 0188cfc to 0c72fe3 Compare May 20, 2026 22:44
Copy link
Copy Markdown

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

♻️ Duplicate comments (1)
frontend/src/components/team/TeamInviteDialog.tsx (1)

35-38: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Normalize seat availability from all supported seat fields, not just seats_available.

Lines 35-38 can still produce false 0 available seats when seats_available is missing but exact billed/member counts are present, which incorrectly blocks invites.

🐛 Proposed fix
 import { openBillingPortal } from "`@/billing/billingPortal`";
 import { useLocalState } from "`@/state/useLocalState`";
 import type { TeamStatus } from "`@/types/team`";
+import { getTeamSeatCounts } from "`@/utils/teamSeats`";
@@
-  const seatsAvailable = Math.max(0, teamStatus?.seats_available || 0);
+  const seatCounts = getTeamSeatCounts(teamStatus);
+  const seatsAvailable =
+    seatCounts.seatsAvailable ??
+    (seatCounts.memberCount !== null && seatCounts.billedSeatCount !== null
+      ? Math.max(0, seatCounts.billedSeatCount - seatCounts.memberCount)
+      : 0);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/team/TeamInviteDialog.tsx` around lines 35 - 38, Fix
seatsAvailable calculation to consider all supported seat fields on teamStatus
instead of only seats_available: when computing seatsAvailable (the const
currently set to Math.max(0, teamStatus?.seats_available || 0)), check fallbacks
like billed_seats, seats, total_seats (or similarly named exact billed/member
count fields available on teamStatus) and, if member counts exist (member_count
or users_count), subtract current members to derive available seats, then clamp
with Math.max(0, ...). Update the seatsAvailable binding to use this normalized
logic so missing seats_available doesn't yield a false zero while leaving
canOpenBillingPortal logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/app.tsx`:
- Line 18: The import for TeamSeatMismatchAlert in app.tsx uses a relative path;
update the import to use the project path alias by replacing the current
relative import with the alias form (import { TeamSeatMismatchAlert } from
"`@/components/team/TeamSeatMismatchAlert`";) so it follows the "`@/`..." mapping
used across the TypeScript/React codebase and matches the coding guidelines.

In `@frontend/src/components/team/TeamSeatMismatchAlert.tsx`:
- Line 9: The import in TeamSeatMismatchAlert.tsx currently uses a relative path
for TeamManagementDialog; change it to use the project path alias by replacing
the relative import with the alias-based import (e.g., import {
TeamManagementDialog } from "`@/components/team/TeamManagementDialog`") so it
follows the coding guideline that `@/*` maps to `./src/*` and keeps imports
consistent; update the import statement where TeamManagementDialog is
referenced.

---

Duplicate comments:
In `@frontend/src/components/team/TeamInviteDialog.tsx`:
- Around line 35-38: Fix seatsAvailable calculation to consider all supported
seat fields on teamStatus instead of only seats_available: when computing
seatsAvailable (the const currently set to Math.max(0,
teamStatus?.seats_available || 0)), check fallbacks like billed_seats, seats,
total_seats (or similarly named exact billed/member count fields available on
teamStatus) and, if member counts exist (member_count or users_count), subtract
current members to derive available seats, then clamp with Math.max(0, ...).
Update the seatsAvailable binding to use this normalized logic so missing
seats_available doesn't yield a false zero while leaving canOpenBillingPortal
logic unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cb91ab5a-5ecd-4da4-9c3d-44674c444a28

📥 Commits

Reviewing files that changed from the base of the PR and between 0188cfc and 0c72fe3.

📒 Files selected for processing (8)
  • frontend/src/app.tsx
  • frontend/src/billing/billingPortal.ts
  • frontend/src/components/AccountMenu.tsx
  • frontend/src/components/team/TeamDashboard.tsx
  • frontend/src/components/team/TeamInviteDialog.tsx
  • frontend/src/components/team/TeamSeatMismatchAlert.tsx
  • frontend/src/types/team.ts
  • frontend/src/utils/teamSeats.ts

Comment thread frontend/src/app.tsx
import { ThemeProvider } from "./contexts/ThemeContext";
import { ProxyEventListener } from "./components/ProxyEventListener";
import { UpdateEventListener } from "./components/UpdateEventListener";
import { TeamSeatMismatchAlert } from "./components/team/TeamSeatMismatchAlert";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Switch the new TeamSeatMismatchAlert import to the @/ path alias.

Line 18 should use the project alias instead of a relative import.

♻️ Proposed fix
-import { TeamSeatMismatchAlert } from "./components/team/TeamSeatMismatchAlert";
+import { TeamSeatMismatchAlert } from "`@/components/team/TeamSeatMismatchAlert`";

As per coding guidelines "Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { TeamSeatMismatchAlert } from "./components/team/TeamSeatMismatchAlert";
import { TeamSeatMismatchAlert } from "`@/components/team/TeamSeatMismatchAlert`";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/app.tsx` at line 18, The import for TeamSeatMismatchAlert in
app.tsx uses a relative path; update the import to use the project path alias by
replacing the current relative import with the alias form (import {
TeamSeatMismatchAlert } from "`@/components/team/TeamSeatMismatchAlert`";) so it
follows the "`@/`..." mapping used across the TypeScript/React codebase and
matches the coding guidelines.

import { getBillingService } from "@/billing/billingService";
import type { TeamStatus } from "@/types/team";
import { formatTeamSeatMismatchMessage, getTeamSeatMismatch } from "@/utils/teamSeats";
import { TeamManagementDialog } from "./TeamManagementDialog";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use path alias for the TeamManagementDialog import.

Line 9 should use the @/ alias instead of a relative import.

♻️ Proposed fix
-import { TeamManagementDialog } from "./TeamManagementDialog";
+import { TeamManagementDialog } from "`@/components/team/TeamManagementDialog`";

As per coding guidelines "Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { TeamManagementDialog } from "./TeamManagementDialog";
import { TeamManagementDialog } from "`@/components/team/TeamManagementDialog`";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/team/TeamSeatMismatchAlert.tsx` at line 9, The import
in TeamSeatMismatchAlert.tsx currently uses a relative path for
TeamManagementDialog; change it to use the project path alias by replacing the
relative import with the alias-based import (e.g., import { TeamManagementDialog
} from "`@/components/team/TeamManagementDialog`") so it follows the coding
guideline that `@/*` maps to `./src/*` and keeps imports consistent; update the
import statement where TeamManagementDialog is referenced.

devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: tony@opensecret.cloud <TonyGiorgio@protonmail.com>
@AnthonyRonning AnthonyRonning merged commit f67c025 into master May 21, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant