Rebuild the dashboard with a distinctive editorial identity (Bricolage Grotesque
display + JetBrains Mono tickers + paper canvas + vermilion signal accent, ruled
layout, grain, staggered load) scoped to .fd-dash so other pages keep the SaaS
theme. UX is action-first:
- action bar: 미검토/떡상 후보/재가공 대기 with primary CTAs (real counts)
- 떡상 후보 leaderboard wired to real /api/dashboard/summary outperformers, with
working per-row 재가공(/rework/{id}) and 제외(status EXCLUDED) actions
- pipeline funnel with bottleneck callout + 칸반 CTA
- source/format + publish with empty-state guidance
Light/dark aware. Editorial fonts loaded in base.html.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase A+dashboard of the UI redesign:
- variables.css: light-default tokens + [data-theme=dark] overrides; old var
names aliased to theme tokens so existing markup adapts to both themes
- style.css: refined components (card/btn/nav/badge/bar/table/forms), tokenized
the dark-assuming rgba colors
- theme toggle: pre-paint init in base.html <head> + toggleTheme() in common.js,
persisted to localStorage; toggle button in sidebar
- sidebar.html: labeled nav with sections (분석/파이프라인/제작), active state,
account; Korean labels
- dashboard.html: tokenized inline colors; verified light & dark with real data
Spec: docs/superpowers/specs/2026-06-12-ui-redesign-design.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add GET /api/dashboard/summary aggregating pipeline status, category
distribution, publish summary, and outperformers in one call. Rewrite
dashboard.html with 5 KPI cards, pipeline funnel, publish status, and
category/source-format breakdowns (CSS bars, no chart lib).
Backend: ChannelVideoRepository counts (shorts/uncategorized),
PublishPackageRepository.countByStatus, pipelineStats shorts/longForm,
CategoryService.distribution, PublishService.dashboardSummary, new
DashboardService + DashboardApiController.
Fix: PublishService.list(null) hit UnsupportedOperationException because
findAll(Sort) uses Criteria, which rejects nullsLast precedence. Route the
no-status path through a @Query method so Sort is appended as HQL ORDER BY
(supports NULLS LAST). Also fixes the latent bug in /api/v1/publish all-list.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>