Files
set50-system/.hermes/plans/2026-08-25_dashboard-polish-table-theme-symbol-detail.md

4.9 KiB

Dashboard Polish — Table UX, Per-Theme Narrative, Per-Symbol Analysis Page

For Hermes: This plan covers the 7-point UX + analysis-transparency review. No code until user approves.

Goal: Make the stock table informative & sortable, explain each theme's analysis in narrative (not just a number), and give every symbol a dedicated detail view showing HOW the system analyzed it (weights, components, combined-score derivation) so the user can verify the analysis honours the agreed methodology.


The 7 complaints → fix

# Complaint Fix Effort
1 Table header text เบียด/ไม่เต็มพื้นที่ Full-width header, better line-height/whitespace CSS
2 "รวม" column ไม่ชัดว่าคืออะไร + เรียงไม่ได้ Rename → "คะแนนรวม"; make it sortable; add tooltip "60% ธีม + 40% พื้นฐาน" FE + sort
3 ธีม กับ 05/บันทึกการวิเคราะห์ ซ้ำ Remove 05/บันทึกการวิเคราะห์ (theme panel already has thesis) FE remove
4 section-kicker ต้อง format เดียวกัน ("07 /" ออก) Remove numeric prefixes → plain Thai kickers FE
5 Theme ต้องการคำอธิบาย/บรรยายผลวิเคราะห์ Long-form narrative per theme (auto hon 3) BE + FE
6 ตารางหุ้น ต้องมี column theme Add "ธีม" column showing which theme(s) each symbol belongs to FE
7 แต่ละหุ้นต้องมี หน้า detail: คลิก แล้วเห็นการวิเคราะห์ทุกอย่าง ต่อหุ้น (ข้อมูล→น้ำหนัก→ที่มาคะแนนรวม) New per-symbol endpoint + detail view (modal or page) BE + FE

Backend tasks

Task B7: Per-symbol analysis breakdown endpoint

  • GET /api/v1/symbols/<symbol> returns for one symbol:
    • symbol, company_name
    • themes: which theme(s) this symbol belongs to (from THEME_SYMBOLS) + each theme's factor reading + surprise contribution
    • fundamentals: PE, EPS, EPS YoY, dividend_yield, PBV, ROE (Siamchart)
    • score_breakdown:
      • theme_score = mean of the theme surprise scores covering this symbol (with per-theme lines)
      • siamchart_score = growth + yield*2, z-scored
      • combined = 0.6theme_score + 0.4siamchart_score (with the actual numbers, not just final)
    • price: latest close + date
  • Deterministic, reuses themes.combine_score logic per-symbol; NO new magic.

Task B5: Long-form per-theme narrative

  • Add a narrative field to each theme read: 2-4 sentence Thai explanation of what the factor means, whether it's positive/negative, and what it implies for stocks in that group. Built deterministically from the factor reading + surprise sign (not hardcoded, not an LLM).

Frontend tasks

Task F1: Table header full-width (complaint 1)

  • Give .stock-panel/.factor-table a max-width-safe full-width layout, better padding/line-height so the subtitle + controls breathe.

Task F2: Rename + sort "รวม" (complaint 2)

  • Header "รวม" → "คะแนนรวม" with a small 60/40 hint; add combined to the sortable keys (already have setSort('combined') — wire it to actually sort by combined score desc default).

Task F3: Remove 05/บันทึกการวิเคราะห์ (complaint 3)

  • Delete the bottom-grid thesis section (superseded by theme panel narratives).

Task F4: Uniform section-kicker (complaint 4)

  • Strip "07 /", "05 /" etc. → plain Thai kickers ("การจำลองการลงทุน", "ธีม", "ที่มาของข้อมูล", "ตารางหุ้น").

Task F6: Add Theme column (complaint 6)

  • In stock table add a "ธีม" column: for each symbol show compact chips of the theme(s) it belongs to (e.g. "โรงกลั่น", "—" if none). Reuse boardBySymbol / THEME lookup.

Task F7: Per-symbol detail view (complaint 7)

  • Clicking a symbol row opens a detail panel/modal showing the full /api/v1/symbols/<symbol> breakdown: themes + fundamentals + score components + how combined was derived (60/40). This is the transparent-analysis view.

Verification

  • Backend: full suite passes; GET /api/v1/symbols/AOT returns full breakdown with correct combined derivation.
  • Frontend: npm run build; browser shows full-width table, "คะแนนรวม" sortable, theme column, no 05 section, uniform kickers, per-symbol modal works & shows derivation.
  • Screenshot evidence; push after user OK.

Open questions

None blocking — methodology is deterministic and already implemented in themes.combine_score; this plan surfaces it transparently rather than changing it.