11import reflex as rx
2-
2+ from reflex . experimental . client_state import ClientStateVar
33from pcweb .components .tabs import tabs
4+ import reflex_ui as ui
5+
6+ collapsed_calculator_cs = ClientStateVar .create ("collapsed_calculator" , default = True )
7+
8+ CREDITS_PER_HOUR_CPU = 0.2
9+ CREDITS_PER_HOUR_GB = 0.5
410
511COMPUTE_TABLE = {
6- "c1m.5" : {"vcpu" : 1 , "ram" : 0.5 , "pph" : 0.046 },
7- "c1m1" : {"vcpu" : 1 , "ram" : 1 , "pph" : 0.083 },
8- "c1m2" : {"vcpu" : 1 , "ram" : 2 , "pph" : 0.157 },
9- "c2m2" : {"vcpu" : 2 , "ram" : 2 , "pph" : 0.166 },
10- "c2m4" : {"vcpu" : 2 , "ram" : 4 , "pph" : 0.312 },
11- "c4m4" : {"vcpu" : 4 , "ram" : 4 , "pph" : 0.332 },
12- "c4m8" : {"vcpu" : 4 , "ram" : 8 , "pph" : 0.625 },
12+ "c1m.5" : {"vcpu" : 1 , "ram" : 0.5 },
13+ "c1m1" : {"vcpu" : 1 , "ram" : 1 },
14+ "c1m2" : {"vcpu" : 1 , "ram" : 2 },
15+ "c2m2" : {"vcpu" : 2 , "ram" : 2 },
16+ "c2m4" : {"vcpu" : 2 , "ram" : 4 },
17+ "c4m4" : {"vcpu" : 4 , "ram" : 4 },
18+ "c4m8" : {"vcpu" : 4 , "ram" : 8 },
1319}
1420
1521
@@ -18,20 +24,30 @@ def table_header(cost_text: str) -> rx.Component:
1824 rx .text ("Machine" , class_name = "text-sm font-semibold text-slate-12" ),
1925 rx .text ("vCPU" , class_name = "text-sm font-semibold text-slate-12" ),
2026 rx .text ("GB RAM" , class_name = "text-sm font-semibold text-slate-12" ),
21- rx .text (cost_text , class_name = "text-sm font-semibold text-slate-12 text-end" ),
27+ rx .el .div (
28+ ui .icon ("StarCircleIcon" , class_name = "text-slate-9 size-4" ),
29+ rx .text (
30+ cost_text , class_name = "text-sm font-semibold text-slate-12 text-end"
31+ ),
32+ class_name = "flex flex-row gap-1 items-center justify-end" ,
33+ ),
2234 class_name = "grid grid-cols-4 gap-4 px-6 py-3 border-b border-slate-4" ,
2335 )
2436
2537
26- def table_row (name : str , cpu : str , ram : str , cost : str ) -> rx .Component :
38+ def table_row (name : str , cpu : str , ram : str , cost : str | rx . Component ) -> rx .Component :
2739 return rx .box (
2840 rx .box (
2941 name ,
3042 class_name = "px-2 w-fit text-slate-12 border-slate-6 h-5 rounded-md border justify-start items-center gap-0.5 inline-flex bg-slate-1 text-sm font-medium shrink-0" ,
3143 ),
3244 rx .text (cpu , class_name = "font-medium text-sm text-slate-9" ),
3345 rx .text (ram , class_name = "font-medium text-sm text-slate-9" ),
34- rx .text (cost , class_name = "font-medium text-sm text-slate-9 text-end" ),
46+ (
47+ rx .text (cost , class_name = "font-medium text-sm text-slate-9 text-end" )
48+ if isinstance (cost , str )
49+ else cost
50+ ),
3551 class_name = "grid grid-cols-4 gap-4 px-6 py-2 border-b border-slate-4 hover:bg-slate-2" ,
3652 )
3753
@@ -48,7 +64,6 @@ def learn_more():
4864 " only when your app is being used." ,
4965 class_name = "text-sm font-medium text-slate-9" ,
5066 ),
51- class_name = "px-6 py-4 border-b border-slate-4 hover:bg-slate-2" ,
5267 )
5368
5469
@@ -60,11 +75,16 @@ def min_table(cost_text: str, description: bool = False) -> rx.Component:
6075 name ,
6176 str (specs ["vcpu" ]),
6277 str (specs ["ram" ]),
63- f"${ specs ['pph' ] / 60 :.6f} " ,
78+ rx .el .span (
79+ rx .el .span (
80+ f"{ (specs ['vcpu' ] * CREDITS_PER_HOUR_CPU + specs ['ram' ] * CREDITS_PER_HOUR_GB ) / 60 :.3f} " ,
81+ class_name = "font-medium text-sm text-slate-9" ,
82+ ),
83+ class_name = "flex flex-row gap-1 items-center justify-end" ,
84+ ),
6485 )
6586 for name , specs in COMPUTE_TABLE .items ()
6687 ],
67- learn_more () if description else rx .fragment (),
6888 class_name = "w-full" ,
6989 )
7090
@@ -77,11 +97,16 @@ def hour_table(cost_text: str, description: bool = False) -> rx.Component:
7797 name ,
7898 str (specs ["vcpu" ]),
7999 str (specs ["ram" ]),
80- f"${ specs ['pph' ]:.3f} " ,
100+ rx .el .span (
101+ rx .el .span (
102+ f"{ specs ['vcpu' ] * CREDITS_PER_HOUR_CPU + specs ['ram' ] * CREDITS_PER_HOUR_GB :.3f} " ,
103+ class_name = "font-medium text-sm text-slate-9" ,
104+ ),
105+ class_name = "flex flex-row gap-1 items-center justify-end" ,
106+ ),
81107 )
82108 for name , specs in COMPUTE_TABLE .items ()
83109 ],
84- learn_more () if description else rx .fragment (),
85110 class_name = "w-full" ,
86111 )
87112
@@ -94,7 +119,13 @@ def month_table(cost_text: str) -> rx.Component:
94119 name ,
95120 str (specs ["vcpu" ]),
96121 str (specs ["ram" ]),
97- f"${ specs ['price_per_min' ] * 60 * 24 * 30 :.2f} " ,
122+ rx .el .span (
123+ rx .el .span (
124+ f"{ specs ['vcpu' ] * CREDITS_PER_HOUR_CPU + specs ['ram' ] * CREDITS_PER_HOUR_GB :.3f} " ,
125+ class_name = "font-medium text-sm text-slate-9" ,
126+ ),
127+ class_name = "flex flex-row gap-1 items-center justify-end" ,
128+ ),
98129 )
99130 for name , specs in COMPUTE_TABLE .items ()
100131 ],
@@ -106,17 +137,7 @@ def compute_table() -> rx.Component:
106137 return rx .box (
107138 tabs .root (
108139 rx .box (
109- rx .box (
110- rx .el .h3 (
111- "Compute Pricing" ,
112- class_name = "text-slate-12 text-3xl font-semibold" ,
113- ),
114- rx .el .p (
115- "Only pay when your app is being used, nothing more." ,
116- class_name = "text-slate-9 text-lg font-semibold text-center lg:text-start text-balance" ,
117- ),
118- class_name = "flex flex-col gap-1 justify-center items-center lg:items-start lg:justify-start" ,
119- ),
140+ learn_more (),
120141 tabs .list (
121142 tabs .tab (
122143 "Per min" ,
@@ -131,16 +152,17 @@ def compute_table() -> rx.Component:
131152 class_name = "flex flex-col lg:flex-row gap-4 items-center justify-center lg:justify-between p-6 border-b border-slate-4" ,
132153 ),
133154 tabs .panel (
134- min_table ("Cost / min" , description = True ),
155+ min_table ("Credits / min" , description = True ),
135156 value = "min" ,
136157 ),
137158 tabs .panel (
138- hour_table ("Cost / hour" , description = True ),
159+ hour_table ("Credits / hour" , description = True ),
139160 value = "hour" ,
140161 ),
141162 default_value = "min" ,
142163 ),
143- class_name = "flex flex-col w-full mt-5 py-24" ,
164+ class_name = "flex flex-col w-full relative data-[collapsed=true]:max-h-[11.5rem] data-[collapsed=true]:overflow-hidden transition-all" ,
165+ data_collapsed = collapsed_calculator_cs .value ,
144166 )
145167
146168
@@ -171,11 +193,11 @@ def compute_table_base() -> rx.Component:
171193 class_name = "flex flex-row gap-2 items-center justify-end pb-6 border-b border-slate-4" ,
172194 ),
173195 tabs .panel (
174- min_table ("Cost / min" ),
196+ min_table ("Credits / min" ),
175197 value = "min" ,
176198 ),
177199 tabs .panel (
178- hour_table ("Cost / hour" ),
200+ hour_table ("Credits / hour" ),
179201 value = "hour" ,
180202 ),
181203 default_value = "min" ,
@@ -187,5 +209,35 @@ def compute_table_base() -> rx.Component:
187209def calculator_section () -> rx .Component :
188210 return rx .el .section (
189211 compute_table (),
190- class_name = "flex flex-col w-full max-w-[64.19rem] 2xl:border-x border-slate-4 2xl:border-t 2xl:border-b pb-[6rem] justify-center items-center" ,
212+ rx .el .div (
213+ rx .cond (
214+ collapsed_calculator_cs .value ,
215+ rx .el .div (
216+ class_name = "from-slate-1 to-transparent absolute z-10 transition-opacity pointer-events-none opacity-100 bg-linear-to-t -top-27 left-0 w-full h-29" ,
217+ ),
218+ ),
219+ ui .button (
220+ ui .icon (
221+ "ArrowDown01Icon" ,
222+ size = 16 ,
223+ class_name = (
224+ "transition-all" ,
225+ rx .cond (collapsed_calculator_cs .value , "" , "rotate-180" ),
226+ ),
227+ ),
228+ rx .cond (
229+ collapsed_calculator_cs .value ,
230+ "Expand Compute Pricing" ,
231+ "Collapse Compute Pricing" ,
232+ ),
233+ on_click = collapsed_calculator_cs .set_value (
234+ ~ collapsed_calculator_cs .value
235+ ),
236+ size = "sm" ,
237+ variant = "outline" ,
238+ class_name = "w-full" ,
239+ ),
240+ class_name = "w-full p-2 relative" ,
241+ ),
242+ class_name = "flex flex-col w-full max-w-[64.19rem] 2xl:border-x border-slate-4 2xl:border-b pb-[6rem] justify-center items-center" ,
191243 )
0 commit comments