Skip to content

feat: add contract admin view link for B2B managers#3369

Open
daniellefrappier18 wants to merge 2 commits into
mainfrom
daniellef/11446-b2b-contract-dashboard-phase-1
Open

feat: add contract admin view link for B2B managers#3369
daniellefrappier18 wants to merge 2 commits into
mainfrom
daniellef/11446-b2b-contract-dashboard-phase-1

Conversation

@daniellefrappier18
Copy link
Copy Markdown
Contributor

What are the relevant tickets?

Closes https://github.com/mitodl/hq/issues/11446

Description (What does it do?)

  • Adds a new Contract Admin page at /organization/[orgSlug]/contract/[contractSlug]/admin
  • Adds a "Manage" button to the learner contract dashboard header, visible only to users who are managers of the org for that contract
  • Both the button and the admin page are gated behind the b2b-contract-manager-dashboard PostHog feature flag so this can be rolled out incrementally
  • Fixes matchOrganizationBySlug to anchor the org- prefix strip to the start of the slug (/^org-/) rather than stripping it from anywhere in the string

The admin page currently shows: org logo, org name, contract name, and total seat count (loading skeleton while fetching detail). More content will follow in subsequent phases.

Screenshots (if appropriate):

  • Desktop screenshots
  • Mobile width screenshots
Screenshot 2026-05-22 at 3 01 24 PM Screenshot 2026-05-22 at 3 01 16 PM

How can this be tested?

Setup: You'll need a user account that is a manager of at least one B2B org in MITxOnline, and the b2b-contract-manager-dashboard feature flag toggled in PostHog.

Feature flag off (default state)

  • Navigate to a contract dashboard as a manager. The "Manage" button should not appear
  • Attempt to navigate directly to /organization/[orgSlug]/contract/[contractSlug]/admin. Should get a 403/forbidden error page

Feature flag on, authenticated manager

  • Navigate to the learner contract dashboard. The "Manage" button should appear in the contract header
  • Click "Manage" this should navigate to /organization/[orgSlug]/contract/[contractSlug]/admin
  • Admin page should show: org logo (or fallback graduate image), org name, contract name, and seat count
  • If the org has no logo, the fallback graduate image renders

Feature flag on, authenticated non-manager

  • Navigate to the learner contract dashboard for a contract where the user is not a manager. The "Manage" button should not appear
  • Attempt to navigate directly to the admin URL for an org they don't manage. Should get a 404 "Organization not found" error

Feature flag on, unauthenticated user

  • Attempt to navigate to the admin URL. Should be redirected to login.

Error states

  • Navigate to the admin page with a valid orgSlug but an invalid contractSlug. Should show "Contract not found" 404 error
  • Navigate to the admin page with an invalid orgSlug. Should show "Organization not found" 404 error

Regression

  • Navigate to a contract dashboard as a non-manager with flag on. No "Manage" button, page loads normally
  • Navigate to a contract dashboard with flag off. Page loads normally, no visual changes

Additional Context

@daniellefrappier18 daniellefrappier18 marked this pull request as ready for review May 22, 2026 19:36
Copilot AI review requested due to automatic review settings May 22, 2026 19:36
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 22, 2026

OpenAPI Changes

No changes detected

View full changelog

Unexpected changes? Ensure your branch is up-to-date with main (consider rebasing).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an organization contract “admin” view for B2B managers and exposes navigation to it from the learner contract dashboard, with rollout controlled via a PostHog feature flag.

Changes:

  • Introduces /organization/[orgSlug]/contract/[contractSlug]/admin (authenticated route) and a new ContractAdminPage that loads manager orgs + contract detail.
  • Adds a feature-flagged “Manage” button on the contract dashboard header, shown only when the viewer is a manager for that org.
  • Fixes matchOrganizationBySlug to only strip the org- prefix when it appears at the start of the slug.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
frontends/main/src/common/utils.ts Anchors org- prefix stripping in matchOrganizationBySlug.
frontends/main/src/common/urls.ts Adds CONTRACT_ADMIN_VIEW + contractAdminView() URL helper.
frontends/main/src/common/feature_flags.ts Registers B2BContractManagerDashboard feature flag.
frontends/main/src/app/(site)/organization/[orgSlug]/contract/[contractSlug]/admin/page.tsx Adds App Router page wiring to ContractAdminPage.
frontends/main/src/app/(site)/organization/[orgSlug]/contract/[contractSlug]/admin/layout.tsx Adds auth restriction + metadata for the admin route.
frontends/main/src/app-pages/DashboardPage/ContractContent.tsx Adds manager/flag-gated “Manage” button and supporting query.
frontends/main/src/app-pages/ContractAdminPage/ContractAdminPage.tsx Implements initial admin page header + seat count fetch, flag-gated.
frontends/api/src/mitxonline/hooks/organizations/queries.ts Adds manager org/contract query options + keys; refactors prior attach mutation out.
frontends/api/src/mitxonline/hooks/organizations/index.ts Re-homes useB2BAttachMutation, exports manager org queries.

Comment on lines 408 to +463
@@ -436,6 +453,14 @@ const ContractContentInternal: React.FC<ContractContentInternalProps> = ({
<Stack>
<ContractHeaderSection>
<ContractHeader org={org} contract={contract} />
{managerDashboardFlag && isManager && (
<ButtonLink
size="small"
href={contractAdminView(orgSlug, contractSlug)}
>
Manage
</ButtonLink>
)}
Comment on lines +159 to +173
const ContractAdminPage: React.FC<ContractAdminPageProps> = ({
orgSlug,
contractSlug,
}) => {
const flagEnabled = useFeatureFlagEnabled(
FeatureFlags.B2BContractManagerDashboard,
)

if (flagEnabled === false) {
throw new ForbiddenError("Not enabled.")
}

if (!flagEnabled) {
return null
}
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.

2 participants