4.9 KiB
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_namethemes: which theme(s) this symbol belongs to (from THEME_SYMBOLS) + each theme's factor reading + surprise contributionfundamentals: 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-scoredcombined= 0.6theme_score + 0.4siamchart_score (with the actual numbers, not just final)
price: latest close + date
- Deterministic, reuses
themes.combine_scorelogic per-symbol; NO new magic.
Task B5: Long-form per-theme narrative
- Add a
narrativefield 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-tablea 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/40hint; addcombinedto the sortable keys (already havesetSort('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/AOTreturns 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.