▍ humdrum codex / soft

TUI Scores: favorites grouped by status (Live/Yesterday/Later Today), not league

51ed50be40c1e5aab010a4029cf277ef1eb4cfd4
humdrum <me@humdrum.me> · 2026-07-08 19:34

parent 39346b10

TUI Scores: favorites grouped by status (Live/Yesterday/Later Today), not league

Favorites no longer split by league — just three status sections. Leagues tier
keeps its per-league grouping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

1 files changed

tui/dashboard.py +29 −17
@@ -446,42 +446,54 @@             pass
     return status, "dim"
 
 
+def _append_game_line(t: Text, g: dict) -> None:
+    lbl, lbl_style = _game_label(g)
+    t.append("    ")
+    t.append(f"{lbl:<18}", style=lbl_style)
+    t.append(f"{g.get('away', '?')} @ {g.get('home', '?')}\n")
+
+
+# Favorites are grouped by status, not league. state → section header.
+_FAV_SECTIONS = (("in", "Live"), ("post", "Yesterday"), ("pre", "Later Today"))
+
+
 def render_sports(p: dict) -> Text:
     games = p.get("games", [])
     if not games:
         return Text("No games.", style="dim italic")
 
     # The module scopes to now (yesterday + today + a favorite's next game) and
-    # tags favorites. Show my teams first, then any opted-in full leagues.
-    tiers = (
-        ("Favorites", [g for g in games if g.get("favorite")]),
-        ("Leagues", [g for g in games if not g.get("favorite")]),
-    )
+    # tags favorites.
+    favs = [g for g in games if g.get("favorite")]
+    leagues = [g for g in games if not g.get("favorite")]
     t = Text()
     first_section = True
 
-    for title, group in tiers:
-        if not group:
+    # Favorites: by status (Live / Yesterday / Later Today), no league split.
+    for state_key, label in _FAV_SECTIONS:
+        section = [g for g in favs if (g.get("state") or "pre") == state_key]
+        if not section:
             continue
         if not first_section:
             t.append("\n")
         first_section = False
-        t.append(f"{title}\n", style="bold")
+        t.append(f"{label}\n", style="bold")
+        for g in sorted(section, key=lambda g: g.get("startTime") or ""):
+            _append_game_line(t, g)
 
-        group = sorted(
-            group,
-            key=lambda g: (_game_order(g), g.get("startTime") or ""),
-        )
+    # Leagues: opted-in full slates, ordered by status and grouped by league.
+    if leagues:
+        if not first_section:
+            t.append("\n")
+        first_section = False
+        t.append("Leagues\n", style="bold")
         cur_league = None
-        for g in group:
+        for g in sorted(leagues, key=lambda g: (_game_order(g), g.get("startTime") or "")):
             lg = g.get("league", "").split("/")[-1].upper()
             if lg != cur_league:
                 cur_league = lg
                 t.append(f"  {lg}\n", style="dim")
-            lbl, lbl_style = _game_label(g)
-            t.append("    ")
-            t.append(f"{lbl:<18}", style=lbl_style)
-            t.append(f"{g.get('away', '?')} @ {g.get('home', '?')}\n")
+            _append_game_line(t, g)
 
     return t