cloud_api_types: Add `ZedBusiness` variant to `Plan` (#51329)

Marshall Bowers created

This PR adds a `ZedBusiness` variant to the `Plan` enum.

Closes CLO-480.

Release Notes:

- N/A

Change summary

crates/agent_ui/src/agent_configuration.rs   |  1 +
crates/ai_onboarding/src/ai_onboarding.rs    | 19 +++++++++++++++++++
crates/ai_onboarding/src/ai_upsell_card.rs   | 20 ++++++++++++++++++++
crates/ai_onboarding/src/plan_definitions.rs |  6 ++++++
crates/cloud_api_types/src/plan.rs           |  1 +
crates/title_bar/src/plan_chip.rs            |  1 +
6 files changed, 48 insertions(+)

Detailed changes

crates/agent_ui/src/agent_configuration.rs 🔗

@@ -501,6 +501,7 @@ impl AgentConfiguration {
                 Plan::ZedFree => ("Free", Color::Default, free_chip_bg),
                 Plan::ZedProTrial => ("Pro Trial", Color::Accent, pro_chip_bg),
                 Plan::ZedPro => ("Pro", Color::Accent, pro_chip_bg),
+                Plan::ZedBusiness => ("Business", Color::Accent, pro_chip_bg),
                 Plan::ZedStudent => ("Student", Color::Accent, pro_chip_bg),
             };
 

crates/ai_onboarding/src/ai_onboarding.rs 🔗

@@ -266,6 +266,20 @@ impl ZedAiOnboarding {
             .into_any_element()
     }
 
+    fn render_business_plan_state(&self, _cx: &mut App) -> AnyElement {
+        v_flex()
+            .gap_1()
+            .child(Headline::new("Welcome to Zed Business"))
+            .child(
+                Label::new("Here's what you get:")
+                    .color(Color::Muted)
+                    .mb_2(),
+            )
+            .child(PlanDefinitions.business_plan())
+            .children(self.render_dismiss_button())
+            .into_any_element()
+    }
+
     fn render_student_plan_state(&self, _cx: &mut App) -> AnyElement {
         v_flex()
             .gap_1()
@@ -289,6 +303,7 @@ impl RenderOnce for ZedAiOnboarding {
                 Some(Plan::ZedFree) => self.render_free_plan_state(cx),
                 Some(Plan::ZedProTrial) => self.render_trial_state(cx),
                 Some(Plan::ZedPro) => self.render_pro_plan_state(cx),
+                Some(Plan::ZedBusiness) => self.render_business_plan_state(cx),
                 Some(Plan::ZedStudent) => self.render_student_plan_state(cx),
             }
         } else {
@@ -353,6 +368,10 @@ impl Component for ZedAiOnboarding {
                         "Pro Plan",
                         onboarding(SignInStatus::SignedIn, Some(Plan::ZedPro), false),
                     ),
+                    single_example(
+                        "Business Plan",
+                        onboarding(SignInStatus::SignedIn, Some(Plan::ZedBusiness), false),
+                    ),
                 ])
                 .into_any_element(),
         )

crates/ai_onboarding/src/ai_upsell_card.rs 🔗

@@ -250,6 +250,15 @@ impl RenderOnce for AiUpsellCard {
                             .mb_2(),
                     )
                     .child(PlanDefinitions.pro_plan()),
+                Some(Plan::ZedBusiness) => card
+                    .child(certified_user_stamp)
+                    .child(Label::new("You're in the Zed Business plan").size(LabelSize::Large))
+                    .child(
+                        Label::new("Here's what you get:")
+                            .color(Color::Muted)
+                            .mb_2(),
+                    )
+                    .child(PlanDefinitions.business_plan()),
                 Some(Plan::ZedStudent) => card
                     .child(certified_user_stamp)
                     .child(Label::new("You're in the Zed Student plan").size(LabelSize::Large))
@@ -368,6 +377,17 @@ impl Component for AiUpsellCard {
                             }
                             .into_any_element(),
                         ),
+                        single_example(
+                            "Business Plan",
+                            AiUpsellCard {
+                                sign_in_status: SignInStatus::SignedIn,
+                                sign_in: Arc::new(|_, _| {}),
+                                account_too_young: false,
+                                user_plan: Some(Plan::ZedBusiness),
+                                tab_index: Some(1),
+                            }
+                            .into_any_element(),
+                        ),
                     ],
                 ))
                 .into_any_element(),

crates/ai_onboarding/src/plan_definitions.rs 🔗

@@ -36,6 +36,12 @@ impl PlanDefinitions {
             .child(ListBulletItem::new("Usage-based billing beyond $5"))
     }
 
+    pub fn business_plan(&self) -> impl IntoElement {
+        List::new()
+            .child(ListBulletItem::new("Unlimited edit predictions"))
+            .child(ListBulletItem::new("Usage-based billing"))
+    }
+
     pub fn student_plan(&self) -> impl IntoElement {
         List::new()
             .child(ListBulletItem::new("Unlimited edit predictions"))

crates/title_bar/src/plan_chip.rs 🔗

@@ -33,6 +33,7 @@ impl RenderOnce for PlanChip {
             Plan::ZedFree => ("Free", Color::Default, free_chip_bg),
             Plan::ZedProTrial => ("Pro Trial", Color::Accent, pro_chip_bg),
             Plan::ZedPro => ("Pro", Color::Accent, pro_chip_bg),
+            Plan::ZedBusiness => ("Business", Color::Accent, pro_chip_bg),
             Plan::ZedStudent => ("Student", Color::Accent, pro_chip_bg),
         };