|
13 | 13 | st.set_page_config(page_title="Weekly U.S. Petroleum Supply", layout="wide") |
14 | 14 |
|
15 | 15 | # ========================= |
16 | | -# Sidebar title |
| 16 | +# Sidebar title (above nav via CSS) |
17 | 17 | # ========================= |
18 | | -st.sidebar.markdown( |
| 18 | +st.markdown( |
19 | 19 | """ |
20 | | - <h1 style="font-size: 1.5rem; line-height: 1.2; margin-bottom: 0.2rem;"> |
21 | | - U.S. Petroleum & WTI Weekly Monitor |
22 | | - </h1> |
| 20 | + <style> |
| 21 | + [data-testid="stSidebar"] { |
| 22 | + background-color: #0D2B5E !important; |
| 23 | + } |
| 24 | + [data-testid="stSidebar"] * { |
| 25 | + color: white !important; |
| 26 | + } |
| 27 | + [data-testid="stSidebar"] input { |
| 28 | + color: #1A1A1A !important; |
| 29 | + } |
| 30 | + [data-testid="stSidebar"] .stDateInput input { |
| 31 | + color: #1A1A1A !important; |
| 32 | + background-color: #E4EBF4 !important; |
| 33 | + } |
| 34 | + [data-testid="stSidebarNav"] a { |
| 35 | + color: rgba(255,255,255,0.8) !important; |
| 36 | + } |
| 37 | + [data-testid="stSidebarNav"] a:hover { |
| 38 | + color: white !important; |
| 39 | + background-color: rgba(255,255,255,0.1) !important; |
| 40 | + } |
| 41 | + [data-testid="stSidebarNav"] { |
| 42 | + padding-top: 3.5rem; |
| 43 | + } |
| 44 | + [data-testid="stSidebarNav"]::before { |
| 45 | + content: "U.S. Petroleum & WTI Weekly Monitor"; |
| 46 | + display: block; |
| 47 | + position: absolute; |
| 48 | + top: 0; |
| 49 | + left: 0; |
| 50 | + right: 0; |
| 51 | + padding: 1rem 1.2rem 0.2rem 1.2rem; |
| 52 | + font-size: 1.05rem; |
| 53 | + font-weight: 600; |
| 54 | + line-height: 1.3; |
| 55 | + color: white !important; |
| 56 | + } |
| 57 | + </style> |
23 | 58 | """, |
24 | 59 | unsafe_allow_html=True, |
25 | 60 | ) |
26 | | -st.sidebar.caption("Source: EIA") |
27 | | -st.sidebar.divider() |
28 | 61 |
|
29 | 62 | # ========================= |
30 | 63 | # Main page header |
31 | 64 | # ========================= |
32 | 65 | st.title("Weekly U.S. Petroleum Supply") |
33 | | -st.subheader("Team Members: Irina, Indra") |
34 | | -st.caption("Source: U.S. Energy Information Administration (EIA)") |
| 66 | +st.caption("Team Members: Irina, Indra · Source: U.S. Energy Information Administration (EIA)") |
35 | 67 |
|
36 | 68 | # ========================= |
37 | 69 | # Project Proposal |
@@ -332,63 +364,71 @@ def compute_product_price_sensitivity( |
332 | 364 | st.divider() |
333 | 365 |
|
334 | 366 | # ========================= |
335 | | -# Two side-by-side charts |
| 367 | +# Stacked charts |
336 | 368 | # ========================= |
337 | | -left_col, right_col = st.columns(TWO_COLUMN_LAYOUT) |
| 369 | +st.subheader("Total Product Supplied") |
338 | 370 |
|
339 | | -with left_col: |
340 | | - st.subheader("Total Product Supplied") |
| 371 | +fig = px.line( |
| 372 | + filtered_total, |
| 373 | + x="week", |
| 374 | + y="total_supply", |
| 375 | + labels={"week": "Week", "total_supply": "Total Product Supplied"}, |
| 376 | +) |
| 377 | +fig.update_layout( |
| 378 | + hovermode="x unified", |
| 379 | + xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"), |
| 380 | + yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"), |
| 381 | + plot_bgcolor="rgba(0,0,0,0)", |
| 382 | + paper_bgcolor="rgba(0,0,0,0)", |
| 383 | +) |
| 384 | +fig.update_traces(hovertemplate="<b>%{x|%b %d, %Y}</b><br>Total Supply: %{y:,.0f}<extra></extra>") |
| 385 | +st.plotly_chart(fig, use_container_width=True) |
341 | 386 |
|
342 | | - fig = px.line( |
343 | | - filtered_total, |
| 387 | +with st.expander("Show total supply data table"): |
| 388 | + total_display = filtered_total.sort_values("week", ascending=False).copy() |
| 389 | + total_display["week"] = total_display["week"].dt.strftime("%Y-%m-%d") |
| 390 | + st.dataframe(total_display, width="stretch") |
| 391 | + |
| 392 | +st.divider() |
| 393 | + |
| 394 | +st.subheader("Product-Level Weekly Supply") |
| 395 | + |
| 396 | +if not selected_products: |
| 397 | + st.warning("Please select at least one product from the sidebar.") |
| 398 | +else: |
| 399 | + product_plot_df = filtered_product[ |
| 400 | + filtered_product["product_name"].isin(selected_products) |
| 401 | + ].copy() |
| 402 | + |
| 403 | + fig2 = px.line( |
| 404 | + product_plot_df, |
344 | 405 | x="week", |
345 | | - y="total_supply", |
346 | | - labels={"week": "Week", "total_supply": "Total Product Supplied"}, |
| 406 | + y="product_supplied", |
| 407 | + color="product_name", |
| 408 | + labels={ |
| 409 | + "week": "Week", |
| 410 | + "product_supplied": "Product Supplied", |
| 411 | + "product_name": "Product", |
| 412 | + }, |
347 | 413 | ) |
348 | | - fig.update_layout(hovermode="x unified") |
349 | | - fig.update_traces( |
350 | | - hovertemplate="<b>%{x|%b %d, %Y}</b><br>Total Supply: %{y:,.0f}<extra></extra>" |
| 414 | + fig2.update_layout( |
| 415 | + hovermode="x unified", |
| 416 | + xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"), |
| 417 | + yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"), |
| 418 | + plot_bgcolor="rgba(0,0,0,0)", |
| 419 | + paper_bgcolor="rgba(0,0,0,0)", |
351 | 420 | ) |
352 | | - st.plotly_chart(fig, use_container_width=True) |
353 | | - |
354 | | - with st.expander("Show total supply data table"): |
355 | | - total_display = filtered_total.sort_values("week", ascending=False).copy() |
356 | | - total_display["week"] = total_display["week"].dt.strftime("%Y-%m-%d") |
357 | | - st.dataframe(total_display, width="stretch") |
358 | | - |
359 | | -with right_col: |
360 | | - st.subheader("Product-Level Weekly Supply") |
361 | | - |
362 | | - if not selected_products: |
363 | | - st.warning("Please select at least one product from the sidebar.") |
364 | | - else: |
365 | | - product_plot_df = filtered_product[ |
366 | | - filtered_product["product_name"].isin(selected_products) |
367 | | - ].copy() |
368 | | - |
369 | | - fig2 = px.line( |
370 | | - product_plot_df, |
371 | | - x="week", |
372 | | - y="product_supplied", |
373 | | - color="product_name", |
374 | | - labels={ |
375 | | - "week": "Week", |
376 | | - "product_supplied": "Product Supplied", |
377 | | - "product_name": "Product", |
378 | | - }, |
379 | | - ) |
380 | | - fig2.update_layout(hovermode="x unified") |
381 | | - fig2.update_traces( |
382 | | - hovertemplate="<b>%{fullData.name}</b><br>%{x|%b %d, %Y}: %{y:,.0f}<extra></extra>" |
383 | | - ) |
384 | | - st.plotly_chart(fig2, use_container_width=True) |
385 | | - |
386 | | - with st.expander("Show product-level data table"): |
387 | | - product_display = product_plot_df.sort_values( |
388 | | - ["product_name", "week"], ascending=[True, False] |
389 | | - ).copy() |
390 | | - product_display["week"] = product_display["week"].dt.strftime("%Y-%m-%d") |
391 | | - st.dataframe(product_display, width="stretch") |
| 421 | + fig2.update_traces( |
| 422 | + hovertemplate="<b>%{fullData.name}</b><br>%{x|%b %d, %Y}: %{y:,.0f}<extra></extra>" |
| 423 | + ) |
| 424 | + st.plotly_chart(fig2, use_container_width=True) |
| 425 | + |
| 426 | + with st.expander("Show product-level data table"): |
| 427 | + product_display = product_plot_df.sort_values( |
| 428 | + ["product_name", "week"], ascending=[True, False] |
| 429 | + ).copy() |
| 430 | + product_display["week"] = product_display["week"].dt.strftime("%Y-%m-%d") |
| 431 | + st.dataframe(product_display, width="stretch") |
392 | 432 |
|
393 | 433 | st.divider() |
394 | 434 |
|
|
0 commit comments