"""
Portfolio sidebar widgets — earnings calendar, dividends, news.
Split from tab9_portfolio.py to stay under 300-line limit.
"""
import streamlit as st
from data.portfolio import (
get_earnings_calendar, get_dividend_schedule, get_portfolio_news,
)
def render_earnings(tickers: tuple):
"""Earnings calendar widget."""
st.markdown("#### Earnings Calendar")
events = get_earnings_calendar(tickers)
if not events:
st.caption("No upcoming earnings found.")
return
for ev in events[:8]:
d = ev["days_until"]
color = "#F87171" if d <= 3 else "#FBBF24" if d <= 7 else "#6B7280"
st.markdown(
f'
'
f'
D-{d}'
f'
{ev["name"]}'
f'
{ev["ticker"]} · {ev["date"]}
'
f'
', unsafe_allow_html=True
)
def render_dividends(tickers: tuple):
"""Dividend schedule widget."""
st.markdown("#### Dividend Schedule")
divs = get_dividend_schedule(tickers)
if not divs:
st.caption("No dividend data found.")
return
for d in divs[:8]:
st.markdown(
f''
f'{d["name"]}'
f' {d["ticker"]}
'
f'Yield: {d["yield_pct"]}'
f' · Ex-Date: {d["ex_date"]}'
f' · Annual: {d["amount"]}'
f'
', unsafe_allow_html=True
)
def render_news(tickers: tuple):
"""Recent news for portfolio stocks."""
st.markdown("#### Portfolio News")
news = get_portfolio_news(tickers, max_per_ticker=2)
if not news:
st.caption("No recent news.")
return
from datetime import datetime
for n in news[:10]:
ts = n.get("published", 0)
date_str = datetime.fromtimestamp(ts).strftime("%m/%d") if ts else ""
link = n.get("link", "#")
st.markdown(
f'', unsafe_allow_html=True
)