Skip to content

refactor(console): Settings — tabs, real approval-policy state, invite copy-link, integrations#53

Merged
hitakshiA merged 2 commits into
mainfrom
codex/39-settings
Jul 10, 2026
Merged

refactor(console): Settings — tabs, real approval-policy state, invite copy-link, integrations#53
hitakshiA merged 2 commits into
mainfrom
codex/39-settings

Conversation

@hitakshiA

@hitakshiA hitakshiA commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Closes #39. Splits Settings into tabs — Team / Approval policy / Recovery / Payees / Integrations — under an org header (name + country + KYB badge). Fixes the approval-policy contradiction: when none exists you get a real "No approval policy configured" empty state with Create default policy (then a "created — review and activate" draft), instead of copy that contradicts the dashboard; the existing require-N-over-$X editor persists via updatePolicy. The team list is now a Member · Email · Role · Status · Actions table (role = neutral MetaPill). Pending invites no longer expose the raw claim URL — Copy link / Resend / Revoke actions instead. Integrations become a Integration · Connected account · Last sync · Status · Actions table with actionable errors (Reconnect on error, Connect on disconnected). Roles matrix behavior is unchanged. Gates: build ✓ · typecheck ✓ (Settings suite updated + green). Part of tracker #41.

Greptile Summary

This PR refactors the Settings screen into five tabs (Team, Approval policy, Recovery, Payees, Integrations) under a new org-identity header, and introduces a "Create default policy" empty state that replaces the misleading "no policy yet" copy. The approval-policy flow now distinguishes between a freshly created session-local draft and a persisted store policy, with honest feedback when the backend create path is absent.

  • Tab layout & tables: Member list, payees, and integrations are each promoted from simple list rows to proper <table> layouts with headers; pending invites hide the raw claim URL behind Copy link / Resend / Revoke actions.
  • Approval policy create flow: createDefault() seeds a local policy with a synthetic ID; save() attempts api.updatePolicy with that ID and degrades gracefully to a session-only warning on failure.
  • Test update: A single fireEvent.click("Approval policy") is added before the existing policy assertions to navigate the new tab gate.

Confidence Score: 4/5

Safe to merge for UI-only audiences, but several action buttons (Resend, Reconnect, Connect, and Activate policy on a newly created default) produce success-toned feedback without making any backend call, which will mislead users in a production environment until the API integrations are wired up.

The tab restructuring and table layouts are straightforward and well-tested. The main concern is that multiple user-facing actions across the screen fire confirmatory toasts while silently doing nothing on the backend — a pattern that creates incorrect expectations in production. These gaps are documented in earlier review threads but remain unaddressed in this changeset.

apps/console/src/screens/Settings.tsx — specifically the invite Resend handler, the integration Reconnect/Connect handlers, and the Activate policy success path for session-local drafts.

Important Files Changed

Filename Overview
apps/console/src/screens/Settings.tsx Large UI refactor splitting settings into five tabs with a new org header, member table, integrations table, and approval-policy create/activate flow. Several action handlers (Reconnect, Connect, Resend) are known UI stubs that show feedback without making API calls, and the "Activate policy" success path is session-local; these are pre-existing concerns flagged in earlier review threads. Minor: org subtitle can render a leading separator when org.name is absent.
apps/console/src/screens/Settings.test.tsx Minimal one-hunk change — adds a tab-click before the approval-policy assertions to account for content now being tab-gated. Correct and sufficient for the changed behaviour.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[SettingsScreen] --> B{tab state}
    B -->|team| C[TeamCard]
    B -->|policy| D[ApprovalPolicyCard]
    B -->|recovery| E[RecoveryCard]
    B -->|payees| F[PayeesCard]
    B -->|integrations| G[IntegrationsCard]

    D --> H{storePolicy exists?}
    H -->|No| I[Empty state\nCreate default policy]
    H -->|Yes| J[Editor\nAmount + N steppers]
    I --> K[createDefault\nsetLocalPolicy fake-id]
    K --> L[Draft banner + Editor]
    L --> M[Activate policy]
    M --> N{api.updatePolicy\nfake id}
    N -->|success| O[refresh → storePolicy set\nActivated toast]
    N -->|catch| P[localPolicy persisted\nSession-only warning toast]

    J --> Q[dirty + amountValid?]
    Q -->|yes| R[api.updatePolicy\nreal id]
    R --> S[refresh → toast saved]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[SettingsScreen] --> B{tab state}
    B -->|team| C[TeamCard]
    B -->|policy| D[ApprovalPolicyCard]
    B -->|recovery| E[RecoveryCard]
    B -->|payees| F[PayeesCard]
    B -->|integrations| G[IntegrationsCard]

    D --> H{storePolicy exists?}
    H -->|No| I[Empty state\nCreate default policy]
    H -->|Yes| J[Editor\nAmount + N steppers]
    I --> K[createDefault\nsetLocalPolicy fake-id]
    K --> L[Draft banner + Editor]
    L --> M[Activate policy]
    M --> N{api.updatePolicy\nfake id}
    N -->|success| O[refresh → storePolicy set\nActivated toast]
    N -->|catch| P[localPolicy persisted\nSession-only warning toast]

    J --> Q[dirty + amountValid?]
    Q -->|yes| R[api.updatePolicy\nreal id]
    R --> S[refresh → toast saved]
Loading

Reviews (2): Last reviewed commit: "fix(console): Settings — make invite res..." | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@hitakshiA, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e9dbbc66-c02d-47ed-ace3-af09d29c316d

📥 Commits

Reviewing files that changed from the base of the PR and between 42f6c3e and 73b5064.

📒 Files selected for processing (2)
  • apps/console/src/screens/Settings.test.tsx
  • apps/console/src/screens/Settings.tsx
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/39-settings

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

Comment thread apps/console/src/screens/Settings.tsx Outdated
Comment thread apps/console/src/screens/Settings.tsx
Comment thread apps/console/src/screens/Settings.tsx
Comment thread apps/console/src/screens/Settings.tsx Outdated
@hitakshiA

Copy link
Copy Markdown
Contributor Author

Addressed the Greptile honesty findings in 73b5064 (Settings.tsx only):

  1. Resend invite no longer fakes an email send — it reuses the copy-link path (copyTextToClipboard) and toasts "Invite link copied — send it to your teammate." (There is no resendInvite endpoint.)
  2. Integration Connect/Reconnect no longer show a fake "connecting…" — they now surface an honest muted toast (" connects/reconnects through the API — not wired up in this build."). No pretend progress.
  3. Activate policy now actually attempts to persist: the !storePolicy && localPolicy branch calls api.updatePolicy + refresh. If this build has no create/upsert path (updatePolicy rejects an unknown id), it keeps the draft for the session and says so honestly ("Session-only default — not yet saved to your workspace.") instead of claiming it's activated.
  4. "You" badge now matches by unique id (m.id === session.member.id), dropping the name/email fallback that could mislabel on a name collision.

Gates: build ✓ · typecheck ✓ · lint ✓ (exit 0, no Settings.tsx diagnostics) · test ✓ (68 passing, incl. the 4 Settings tests). No test changes needed.

@hitakshiA
hitakshiA merged commit ac9a065 into main Jul 10, 2026
3 checks passed
@hitakshiA
hitakshiA deleted the codex/39-settings branch July 10, 2026 10:34
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.

refactor(console): Settings — tabs, real approval-policy state (fix contradiction), invite copy-link, integrations

1 participant