1- import { AdjustmentsHorizontalIcon , CheckIcon , XMarkIcon } from "@heroicons/react/20/solid" ;
1+ import { CheckIcon , XMarkIcon } from "@heroicons/react/20/solid" ;
22import { type MetaFunction } from "@remix-run/react" ;
33import { type LoaderFunctionArgs } from "@remix-run/server-runtime" ;
44import type { RuntimeEnvironmentType } from "@trigger.dev/database" ;
@@ -7,8 +7,9 @@ import { typedjson, useTypedLoaderData } from "remix-typedjson";
77import { AdminDebugTooltip } from "~/components/admin/debugTooltip" ;
88import { EnvironmentCombo } from "~/components/environments/EnvironmentLabel" ;
99import { PageBody , PageContainer } from "~/components/layout/AppLayout" ;
10+ import { Feedback } from "~/components/Feedback" ;
1011import { Badge } from "~/components/primitives/Badge" ;
11- import { Callout } from "~/components/primitives/Callout " ;
12+ import { Button , LinkButton } from "~/components/primitives/Buttons " ;
1213import { Header2 } from "~/components/primitives/Headers" ;
1314import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
1415import { Paragraph } from "~/components/primitives/Paragraph" ;
@@ -38,7 +39,11 @@ import {
3839import { requireUserId } from "~/services/session.server" ;
3940import { cn } from "~/utils/cn" ;
4041import { formatNumber } from "~/utils/numberFormatter" ;
41- import { concurrencyPath , EnvironmentParamSchema } from "~/utils/pathBuilder" ;
42+ import {
43+ concurrencyPath ,
44+ EnvironmentParamSchema ,
45+ organizationBillingPath ,
46+ } from "~/utils/pathBuilder" ;
4247
4348export const meta : MetaFunction = ( ) => {
4449 return [
@@ -116,29 +121,20 @@ export default function Page() {
116121 </ PageAccessories >
117122 </ NavBar >
118123 < PageBody scrollable = { true } >
119- < div className = "mx-auto max-w-4xl p-4" >
124+ < div className = "mx-auto max-w-3xl p-4" >
120125 < div className = "flex flex-col gap-8" >
121- { /* Plan info */ }
122- { data . planName && (
123- < div className = "flex items-center gap-2" >
124- < Paragraph variant = "small" className = "text-text-dimmed" >
125- Current plan:
126- </ Paragraph >
127- < Badge variant = "small" > { data . planName } </ Badge >
128- </ div >
129- ) }
130-
131- { /* Concurrency Link Section */ }
132- < Callout
133- variant = "info"
134- icon = { < AdjustmentsHorizontalIcon className = "h-5 w-5 text-text-dimmed" /> }
135- to = { concurrencyPath ( organization , project , environment ) }
136- >
137- < Paragraph variant = "small" className = "text-text-bright" >
138- < span className = "font-medium" > Concurrency limits</ span > are managed on a dedicated
139- page where you can view and adjust limits for each environment.
140- </ Paragraph >
141- </ Callout >
126+ { /* Current Plan Section */ }
127+ { /* {data.planName && ( */ }
128+ < CurrentPlanSection
129+ planName = { `${ data . planName } Pro` }
130+ billingPath = { organizationBillingPath ( organization ) }
131+ />
132+ { /* )} */ }
133+
134+ { /* Concurrency Section */ }
135+ < ConcurrencySection
136+ concurrencyPath = { concurrencyPath ( organization , project , environment ) }
137+ />
142138
143139 { /* Rate Limits Section */ }
144140 < RateLimitsSection rateLimits = { data . rateLimits } environmentType = { environment . type } />
@@ -155,6 +151,58 @@ export default function Page() {
155151 ) ;
156152}
157153
154+ function CurrentPlanSection ( { planName, billingPath } : { planName : string ; billingPath : string } ) {
155+ const isPro = planName === "Pro" ;
156+
157+ return (
158+ < div className = "flex flex-col gap-3" >
159+ < Header2 > Current plan</ Header2 >
160+ < Table variant = "bright/no-hover" >
161+ < TableBody >
162+ < TableRow >
163+ < TableCell className = "w-full text-sm text-text-bright" > { planName } </ TableCell >
164+ < TableCell alignment = "right" >
165+ { isPro ? (
166+ < Feedback
167+ button = { < Button variant = "secondary/small" > Request Enterprise</ Button > }
168+ defaultValue = "help"
169+ />
170+ ) : (
171+ < LinkButton to = { billingPath } variant = "secondary/small" >
172+ View plans to upgrade
173+ </ LinkButton >
174+ ) }
175+ </ TableCell >
176+ </ TableRow >
177+ </ TableBody >
178+ </ Table >
179+ </ div >
180+ ) ;
181+ }
182+
183+ function ConcurrencySection ( { concurrencyPath } : { concurrencyPath : string } ) {
184+ return (
185+ < div className = "flex flex-col gap-3" >
186+ < Header2 className = "flex items-center gap-1" >
187+ Concurrency limits
188+ < InfoIconTooltip content = "Concurrency limits control how many runs execute at the same time." />
189+ </ Header2 >
190+ < Table variant = "bright/no-hover" >
191+ < TableBody >
192+ < TableRow >
193+ < TableCell className = "w-full text-sm text-text-bright" > Concurrency</ TableCell >
194+ < TableCell alignment = "right" >
195+ < LinkButton to = { concurrencyPath } variant = "secondary/small" >
196+ Manage concurrency
197+ </ LinkButton >
198+ </ TableCell >
199+ </ TableRow >
200+ </ TableBody >
201+ </ Table >
202+ </ div >
203+ ) ;
204+ }
205+
158206function RateLimitsSection ( {
159207 rateLimits,
160208 environmentType,
0 commit comments