onboarding: Add young account treatment to AI upsell card (#35785)

Danilo Leal created

Release Notes:

- N/A

Change summary

crates/ai_onboarding/src/ai_upsell_card.rs | 213 +++++++++++++++--------
crates/onboarding/src/ai_setup_page.rs     |   1 
2 files changed, 139 insertions(+), 75 deletions(-)

Detailed changes

crates/ai_onboarding/src/ai_upsell_card.rs 🔗

@@ -1,26 +1,33 @@
 use std::{sync::Arc, time::Duration};
 
-use client::{Client, zed_urls};
+use client::{Client, UserStore, zed_urls};
 use cloud_llm_client::Plan;
 use gpui::{
-    Animation, AnimationExt, AnyElement, App, IntoElement, RenderOnce, Transformation, Window,
-    percentage,
+    Animation, AnimationExt, AnyElement, App, Entity, IntoElement, RenderOnce, Transformation,
+    Window, percentage,
 };
 use ui::{Divider, Vector, VectorName, prelude::*};
 
-use crate::{SignInStatus, plan_definitions::PlanDefinitions};
+use crate::{SignInStatus, YoungAccountBanner, plan_definitions::PlanDefinitions};
 
 #[derive(IntoElement, RegisterComponent)]
 pub struct AiUpsellCard {
     pub sign_in_status: SignInStatus,
     pub sign_in: Arc<dyn Fn(&mut Window, &mut App)>,
+    pub account_too_young: bool,
     pub user_plan: Option<Plan>,
     pub tab_index: Option<isize>,
 }
 
 impl AiUpsellCard {
-    pub fn new(client: Arc<Client>, user_plan: Option<Plan>) -> Self {
+    pub fn new(
+        client: Arc<Client>,
+        user_store: &Entity<UserStore>,
+        user_plan: Option<Plan>,
+        cx: &mut App,
+    ) -> Self {
         let status = *client.status().borrow();
+        let store = user_store.read(cx);
 
         Self {
             user_plan,
@@ -32,6 +39,7 @@ impl AiUpsellCard {
                 })
                 .detach_and_log_err(cx);
             }),
+            account_too_young: store.account_too_young(),
             tab_index: None,
         }
     }
@@ -40,6 +48,7 @@ impl AiUpsellCard {
 impl RenderOnce for AiUpsellCard {
     fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
         let plan_definitions = PlanDefinitions;
+        let young_account_banner = YoungAccountBanner;
 
         let pro_section = v_flex()
             .flex_grow()
@@ -158,36 +167,70 @@ impl RenderOnce for AiUpsellCard {
             SignInStatus::SignedIn => match self.user_plan {
                 None | Some(Plan::ZedFree) => card
                     .child(Label::new("Try Zed AI").size(LabelSize::Large))
-                    .child(
-                        div()
-                            .max_w_3_4()
-                            .mb_2()
-                            .child(Label::new(description).color(Color::Muted)),
-                    )
-                    .child(plans_section)
-                    .child(
-                        footer_container
-                            .child(
-                                Button::new("start_trial", "Start 14-day Free Pro Trial")
-                                    .full_width()
-                                    .style(ButtonStyle::Tinted(ui::TintColor::Accent))
-                                    .when_some(self.tab_index, |this, tab_index| {
-                                        this.tab_index(tab_index)
-                                    })
-                                    .on_click(move |_, _window, cx| {
-                                        telemetry::event!(
-                                            "Start Trial Clicked",
-                                            state = "post-sign-in"
-                                        );
-                                        cx.open_url(&zed_urls::start_trial_url(cx))
-                                    }),
+                    .map(|this| {
+                        if self.account_too_young {
+                            this.child(young_account_banner).child(
+                                v_flex()
+                                    .mt_2()
+                                    .gap_1()
+                                    .child(
+                                        h_flex()
+                                            .gap_2()
+                                            .child(
+                                                Label::new("Pro")
+                                                    .size(LabelSize::Small)
+                                                    .color(Color::Accent)
+                                                    .buffer_font(cx),
+                                            )
+                                            .child(Divider::horizontal()),
+                                    )
+                                    .child(plan_definitions.pro_plan(true))
+                                    .child(
+                                        Button::new("pro", "Get Started")
+                                            .full_width()
+                                            .style(ButtonStyle::Tinted(ui::TintColor::Accent))
+                                            .on_click(move |_, _window, cx| {
+                                                telemetry::event!(
+                                                    "Upgrade To Pro Clicked",
+                                                    state = "young-account"
+                                                );
+                                                cx.open_url(&zed_urls::upgrade_to_zed_pro_url(cx))
+                                            }),
+                                    ),
                             )
+                        } else {
+                            this.child(
+                                div()
+                                    .max_w_3_4()
+                                    .mb_2()
+                                    .child(Label::new(description).color(Color::Muted)),
+                            )
+                            .child(plans_section)
                             .child(
-                                Label::new("No credit card required")
-                                    .size(LabelSize::Small)
-                                    .color(Color::Muted),
-                            ),
-                    ),
+                                footer_container
+                                    .child(
+                                        Button::new("start_trial", "Start 14-day Free Pro Trial")
+                                            .full_width()
+                                            .style(ButtonStyle::Tinted(ui::TintColor::Accent))
+                                            .when_some(self.tab_index, |this, tab_index| {
+                                                this.tab_index(tab_index)
+                                            })
+                                            .on_click(move |_, _window, cx| {
+                                                telemetry::event!(
+                                                    "Start Trial Clicked",
+                                                    state = "post-sign-in"
+                                                );
+                                                cx.open_url(&zed_urls::start_trial_url(cx))
+                                            }),
+                                    )
+                                    .child(
+                                        Label::new("No credit card required")
+                                            .size(LabelSize::Small)
+                                            .color(Color::Muted),
+                                    ),
+                            )
+                        }
+                    }),
                 Some(Plan::ZedProTrial) => card
                     .child(pro_trial_stamp)
                     .child(Label::new("You're in the Zed Pro Trial").size(LabelSize::Large))
@@ -255,48 +298,68 @@ impl Component for AiUpsellCard {
         Some(
             v_flex()
                 .gap_4()
-                .children(vec![example_group(vec![
-                    single_example(
-                        "Signed Out State",
-                        AiUpsellCard {
-                            sign_in_status: SignInStatus::SignedOut,
-                            sign_in: Arc::new(|_, _| {}),
-                            user_plan: None,
-                            tab_index: Some(0),
-                        }
-                        .into_any_element(),
-                    ),
-                    single_example(
-                        "Free Plan",
-                        AiUpsellCard {
-                            sign_in_status: SignInStatus::SignedIn,
-                            sign_in: Arc::new(|_, _| {}),
-                            user_plan: Some(Plan::ZedFree),
-                            tab_index: Some(1),
-                        }
-                        .into_any_element(),
-                    ),
-                    single_example(
-                        "Pro Trial",
-                        AiUpsellCard {
-                            sign_in_status: SignInStatus::SignedIn,
-                            sign_in: Arc::new(|_, _| {}),
-                            user_plan: Some(Plan::ZedProTrial),
-                            tab_index: Some(1),
-                        }
-                        .into_any_element(),
-                    ),
-                    single_example(
-                        "Pro Plan",
-                        AiUpsellCard {
-                            sign_in_status: SignInStatus::SignedIn,
-                            sign_in: Arc::new(|_, _| {}),
-                            user_plan: Some(Plan::ZedPro),
-                            tab_index: Some(1),
-                        }
-                        .into_any_element(),
-                    ),
-                ])])
+                .items_center()
+                .max_w_4_5()
+                .child(single_example(
+                    "Signed Out State",
+                    AiUpsellCard {
+                        sign_in_status: SignInStatus::SignedOut,
+                        sign_in: Arc::new(|_, _| {}),
+                        account_too_young: false,
+                        user_plan: None,
+                        tab_index: Some(0),
+                    }
+                    .into_any_element(),
+                ))
+                .child(example_group_with_title(
+                    "Signed In States",
+                    vec![
+                        single_example(
+                            "Free Plan",
+                            AiUpsellCard {
+                                sign_in_status: SignInStatus::SignedIn,
+                                sign_in: Arc::new(|_, _| {}),
+                                account_too_young: false,
+                                user_plan: Some(Plan::ZedFree),
+                                tab_index: Some(1),
+                            }
+                            .into_any_element(),
+                        ),
+                        single_example(
+                            "Free Plan but Young Account",
+                            AiUpsellCard {
+                                sign_in_status: SignInStatus::SignedIn,
+                                sign_in: Arc::new(|_, _| {}),
+                                account_too_young: true,
+                                user_plan: Some(Plan::ZedFree),
+                                tab_index: Some(1),
+                            }
+                            .into_any_element(),
+                        ),
+                        single_example(
+                            "Pro Trial",
+                            AiUpsellCard {
+                                sign_in_status: SignInStatus::SignedIn,
+                                sign_in: Arc::new(|_, _| {}),
+                                account_too_young: false,
+                                user_plan: Some(Plan::ZedProTrial),
+                                tab_index: Some(1),
+                            }
+                            .into_any_element(),
+                        ),
+                        single_example(
+                            "Pro Plan",
+                            AiUpsellCard {
+                                sign_in_status: SignInStatus::SignedIn,
+                                sign_in: Arc::new(|_, _| {}),
+                                account_too_young: false,
+                                user_plan: Some(Plan::ZedPro),
+                                tab_index: Some(1),
+                            }
+                            .into_any_element(),
+                        ),
+                    ],
+                ))
                 .into_any_element(),
         )
     }

crates/onboarding/src/ai_setup_page.rs 🔗

@@ -286,6 +286,7 @@ pub(crate) fn render_ai_setup_page(
                 .child(AiUpsellCard {
                     sign_in_status: SignInStatus::SignedIn,
                     sign_in: Arc::new(|_, _| {}),
+                    account_too_young: user_store.read(cx).account_too_young(),
                     user_plan: user_store.read(cx).plan(),
                     tab_index: Some({
                         tab_index += 1;