user_spending.rs

  1use gpui::{Entity, Render};
  2use ui::{ProgressBar, prelude::*};
  3
  4#[derive(RegisterComponent)]
  5pub struct UserSpending {
  6    free_tier_current: u32,
  7    free_tier_cap: u32,
  8    over_tier_current: u32,
  9    over_tier_cap: u32,
 10    free_tier_progress: Entity<ProgressBar>,
 11    over_tier_progress: Entity<ProgressBar>,
 12}
 13
 14impl UserSpending {
 15    pub fn new(
 16        free_tier_current: u32,
 17        free_tier_cap: u32,
 18        over_tier_current: u32,
 19        over_tier_cap: u32,
 20        cx: &mut App,
 21    ) -> Self {
 22        let free_tier_capped = free_tier_current == free_tier_cap;
 23        let free_tier_near_capped =
 24            free_tier_current as f32 / 100.0 >= free_tier_cap as f32 / 100.0 * 0.9;
 25        let over_tier_capped = over_tier_current == over_tier_cap;
 26        let over_tier_near_capped =
 27            over_tier_current as f32 / 100.0 >= over_tier_cap as f32 / 100.0 * 0.9;
 28
 29        let free_tier_progress = cx.new(|cx| {
 30            ProgressBar::new(
 31                "free_tier",
 32                free_tier_current as f32,
 33                free_tier_cap as f32,
 34                cx,
 35            )
 36        });
 37        let over_tier_progress = cx.new(|cx| {
 38            ProgressBar::new(
 39                "over_tier",
 40                over_tier_current as f32,
 41                over_tier_cap as f32,
 42                cx,
 43            )
 44        });
 45
 46        if free_tier_capped {
 47            free_tier_progress.update(cx, |progress_bar, cx| {
 48                progress_bar.fg_color(cx.theme().status().error);
 49            });
 50        } else if free_tier_near_capped {
 51            free_tier_progress.update(cx, |progress_bar, cx| {
 52                progress_bar.fg_color(cx.theme().status().warning);
 53            });
 54        }
 55
 56        if over_tier_capped {
 57            over_tier_progress.update(cx, |progress_bar, cx| {
 58                progress_bar.fg_color(cx.theme().status().error);
 59            });
 60        } else if over_tier_near_capped {
 61            over_tier_progress.update(cx, |progress_bar, cx| {
 62                progress_bar.fg_color(cx.theme().status().warning);
 63            });
 64        }
 65
 66        Self {
 67            free_tier_current,
 68            free_tier_cap,
 69            over_tier_current,
 70            over_tier_cap,
 71            free_tier_progress,
 72            over_tier_progress,
 73        }
 74    }
 75}
 76
 77impl Render for UserSpending {
 78    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
 79        let formatted_free_tier = format!(
 80            "${} / ${}",
 81            self.free_tier_current as f32 / 100.0,
 82            self.free_tier_cap as f32 / 100.0
 83        );
 84        let formatted_over_tier = format!(
 85            "${} / ${}",
 86            self.over_tier_current as f32 / 100.0,
 87            self.over_tier_cap as f32 / 100.0
 88        );
 89
 90        v_group()
 91            .elevation_2(cx)
 92            .py_1p5()
 93            .px_2p5()
 94            .w(px(360.))
 95            .child(
 96                v_flex()
 97                    .child(
 98                        v_flex()
 99                            .p_1p5()
100                            .gap_0p5()
101                            .child(
102                                h_flex()
103                                    .justify_between()
104                                    .child(Label::new("Free Tier Usage").size(LabelSize::Small))
105                                    .child(
106                                        Label::new(formatted_free_tier)
107                                            .size(LabelSize::Small)
108                                            .color(Color::Muted),
109                                    ),
110                            )
111                            .child(self.free_tier_progress.clone()),
112                    )
113                    .child(
114                        v_flex()
115                            .p_1p5()
116                            .gap_0p5()
117                            .child(
118                                h_flex()
119                                    .justify_between()
120                                    .child(Label::new("Current Spending").size(LabelSize::Small))
121                                    .child(
122                                        Label::new(formatted_over_tier)
123                                            .size(LabelSize::Small)
124                                            .color(Color::Muted),
125                                    ),
126                            )
127                            .child(self.over_tier_progress.clone()),
128                    ),
129            )
130    }
131}
132
133impl Component for UserSpending {
134    fn scope() -> ComponentScope {
135        ComponentScope::None
136    }
137
138    fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
139        let new_user = cx.new(|cx| UserSpending::new(0, 2000, 0, 2000, cx));
140        let free_capped = cx.new(|cx| UserSpending::new(2000, 2000, 0, 2000, cx));
141        let free_near_capped = cx.new(|cx| UserSpending::new(1800, 2000, 0, 2000, cx));
142        let over_near_capped = cx.new(|cx| UserSpending::new(2000, 2000, 1800, 2000, cx));
143        let over_capped = cx.new(|cx| UserSpending::new(1000, 2000, 2000, 2000, cx));
144
145        Some(
146            v_flex()
147                .gap_6()
148                .p_4()
149                .children(vec![example_group(vec![
150                    single_example(
151                        "New User",
152                        div().size_full().child(new_user.clone()).into_any_element(),
153                    ),
154                    single_example(
155                        "Free Tier Capped",
156                        div()
157                            .size_full()
158                            .child(free_capped.clone())
159                            .into_any_element(),
160                    ),
161                    single_example(
162                        "Free Tier Near Capped",
163                        div()
164                            .size_full()
165                            .child(free_near_capped.clone())
166                            .into_any_element(),
167                    ),
168                    single_example(
169                        "Over Tier Near Capped",
170                        div()
171                            .size_full()
172                            .child(over_near_capped.clone())
173                            .into_any_element(),
174                    ),
175                    single_example(
176                        "Over Tier Capped",
177                        div()
178                            .size_full()
179                            .child(over_capped.clone())
180                            .into_any_element(),
181                    ),
182                ])])
183                .into_any_element(),
184        )
185    }
186}