Skip to content

[Feature/#145] 플랫폼별 대시보드 상단/하단 지표 UI 구현 - #158

Merged
YermIm merged 20 commits into
developfrom
feature/#145
Apr 6, 2026
Merged

YermIm merged 20 commits into
developfrom
feature/#145

Conversation

@YermIm

@YermIm YermIm commented Apr 4, 2026

Copy link
Copy Markdown
Collaborator

🚨 관련 이슈

close #145

✨ 변경사항

  • 🐞 BugFix Something isn't working
  • 💻 CrossBrowsing Browser compatibility
  • 🌏 Deploy Deploy
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (storybook, jest, etc.)

✏️ 작업 내용

스크린샷 2026-04-04 오후 9 35 58 스크린샷 2026-04-04 오후 9 36 12

1. UX/UI

  • 전체보기/플랫폼 선택 버튼 + 드롭다운
  • 카드 배치 및 스켈레톤 UI 적용

2. 광고 소재 현황

  • 세그먼트 바 형태의 커스텀 차트
  • 우측 상단-총 광고 소재 개수 뱃지
  • 각 플랫폼별 소재 개수를 전체 합계로 나누어 데이터 계산

3. 플랫폼별 성과 효율 비교

  • ApexCharts : 복합 차트
  • 플랫폼별 성과 기여도 -> 플랫폼별 성과 효율 비교 타이틀 변경
  • 기존 디자인에서 클릭률/전환율/노출 수 모두 막대였지만 노출수가 단위가 달라 동일 방식으로 나타내기에는 어려움
    -> y축 왼쪽을 %로 하여 클릭률/전환율 막대, y축 오른쪽을 수치로 하여 노출 수 점으로 표시

4. 개별 플랫폼 상세 카드

  • 실시간 클릭수 제거 (실시간 트래픽 변화와 겹침)
  • 노출수, 클릭수, 전환율, ROAS 지표

😅 미완성 작업

N/A

📢 논의 사항 및 참고 사항

범위가 좀 넓어진 것 같습니다ㅠㅠ 기존 디자인과 달라진 부분이 있으니 확인 후 피드백 주시면 감사하겠습니다!

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

  • 새로운 기능

    • 플랫폼 대시보드 완성: 플랫폼 선택, 로딩 스켈레톤 및 실제 데이터 렌더링
    • 광고 상태 차트, 성과 효율성 혼합 차트, 개별 플랫폼 상세 카드, ROAS 순위 목록 추가
    • 대시보드용 모의 데이터 세트 및 다양한 로딩 스켈레톤 컴포넌트 추가
  • 개선사항

    • 드롭다운 메뉴에 메뉴 패널 스타일 커스터마이징 옵션 추가
    • 차트 범례에 인라인 색상 지정 옵션 추가

@YermIm YermIm self-assigned this Apr 4, 2026
@YermIm YermIm added the 🎨 Html&css 마크업 & 스타일링 label Apr 4, 2026
@YermIm
YermIm requested review from Seojegyeong and jjjsun April 4, 2026 13:11
@YermIm YermIm added the ✨ Feature 기능 개발 label Apr 4, 2026
@coderabbitai

coderabbitai Bot commented Apr 4, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e793d8b3-f0c2-409e-89e9-1704c1b21531

📥 Commits

Reviewing files that changed from the base of the PR and between 9c07eba and bd4362e.

📒 Files selected for processing (2)
  • src/components/dashboard/charts/performanceEfficiencyChart.config.ts
  • src/pages/dashboard/platform/PlatformDashboard.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/components/dashboard/charts/performanceEfficiencyChart.config.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/dashboard/platform/PlatformDashboard.tsx

📝 Walkthrough

Walkthrough

플랫폼 대시보드 관련 타입·모의데이터와 차트(AdStatus/PerformanceEfficiency), 플랫폼 상세/순위 리스트 및 스켈레톤 UI를 추가하고, PlatformDashboard를 상태 기반(선택 플랫폼, 로딩 타이머)으로 교체했으며 DropdownMenu에 메뉴 패널 클래스 주입용 prop(menuClassName)을 추가함.

Changes

Cohort / File(s) Summary
타입 & 모의 데이터
src/types/dashboard/platform.ts, src/pages/dashboard/platform/platformDashboard.mock.ts
플랫폼 관련 타입/인터페이스(TPlatformProvider, IRoasRanking, IPlatformPerformance 등)와 PLATFORM_MAP 추가. 대시보드용 roasRankingMock, adStatusMock, performanceEfficiencyMock 모의 데이터 추가.
차트 컴포넌트
src/components/dashboard/charts/AdStatusChart.tsx, src/components/dashboard/charts/PerformanceEfficiencyChart.tsx, src/components/dashboard/charts/performanceEfficiencyChart.config.ts
Ad 상태 세그먼트 바 컴포넌트 추가. ApexCharts 기반 혼합 차트 컴포넌트 및 옵션 팩토리(getMixedChartOptions) 추가; PerformanceEfficiencyChart는 lazy + Suspense로 렌더링.
플랫폼 UI 컴포넌트
src/components/dashboard/platform/PlatformDetailCard.tsx, src/components/dashboard/platform/TopPerformanceList.tsx
플랫폼별 상세 카드(로고·핵심 지표·트렌드)와 ROAS 상위 플랫폼 리스트(순위·로고·ROAS·트렌드 배지) 추가.
스켈레톤 로딩 UI
src/components/dashboard/platform/skeleton/PlatformSkeleton.tsx
TopPerformanceListSkeleton, PlatformDetailCardSkeleton, AdStatusChartSkeleton, PerformanceEfficiencyChartSkeleton, TrafficChartSkeleton, BadgeSkeleton 등 로딩 플레이스홀더 컴포넌트 추가.
페이지 변경: PlatformDashboard
src/pages/dashboard/platform/PlatformDashboard.tsx
정적 페이지에서 상태 기반 대시보드로 전환: selectedPlatform/isLoading 상태, 1600ms 페이크 로딩 useEffect, 로딩 중 스켈레톤·로딩 UI, 완료 시 차트·리스트·카드 렌더링 및 모의데이터 연결.
공용 컴포넌트 개선
src/components/common/dropdownmenu/DropdownMenu.tsx
드롭다운에 menuClassName?: string prop 추가; 내부 메뉴 패널 클래스에 twMerge(baseClasses, menuClassName) 적용해 스타일 오버라이드 허용.
공용 차트 레전드 타입
src/components/common/chart/ChartLegend.tsx
IChartLegendItem.colorClass를 옵셔널로 변경하고 color?: string 추가; 색상 스와치에 inline backgroundColor 적용 가능하도록 수정.

Sequence Diagram

sequenceDiagram
    participant User
    participant PlatformDashboard
    participant useEffect_Timer
    participant SkeletonComponents
    participant DataComponents

    User->>PlatformDashboard: 접근 (초기 렌더)
    PlatformDashboard->>PlatformDashboard: set selectedPlatform / set isLoading(true)
    PlatformDashboard->>SkeletonComponents: 렌더(스켈레톤 표시)
    SkeletonComponents-->>User: 로딩 플레이스홀더 노출

    PlatformDashboard->>useEffect_Timer: useEffect 타이머 시작 (1600ms)
    useEffect_Timer->>useEffect_Timer: 대기
    useEffect_Timer->>PlatformDashboard: set isLoading(false)

    PlatformDashboard->>DataComponents: 렌더(차트·리스트·카드)
    DataComponents-->>User: 실제 데이터 UI 표시
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • jjjsun
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 이슈 #145와 일치하며, 플랫폼 대시보드의 상단/하단 지표 UI 구현이라는 주요 변경사항을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿을 따르고 있으며, 관련 이슈 (#145), 변경사항(🎨 Design, ✨ Feature 체크), 작업 내용(스크린샷 포함), 그리고 검토자 가이드(P-Rules)가 모두 포함되어 있습니다.
Linked Issues check ✅ Passed PR의 모든 코드 변경사항이 이슈 #145의 요구사항을 충족합니다: 페이지 레이아웃(PlatformDashboard.tsx), 성과 우수 플랫폼 카드(TopPerformanceList), 광고 소재 현황 카드(AdStatusChart), 플랫폼별 성과 효율 비교(PerformanceEfficiencyChart), 플랫폼별 상세 카드(PlatformDetailCard) 등이 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed DropdownMenu의 menuClassName props 추가와 ChartLegend의 color 필드 추가는 새로운 컴포넌트들(AdStatusChart, PerformanceEfficiencyChart 등)을 지원하기 위한 필수 확장입니다. 모든 변경사항이 이슈 #145의 범위 내에 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#145

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Apr 4, 2026

Copy link
Copy Markdown

📚 Storybook 배포 완료

항목 링크
📖 Storybook https://69a147b60a56365d9e2185ef-ujfcolwcii.chromatic.com/
🔍 Chromatic https://www.chromatic.com/build?appId=69a147b60a56365d9e2185ef&number=194

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/dashboard/charts/AdStatusChart.tsx`:
- Around line 13-16: In AdStatusChart, the computed total from useMemo (const
total = useMemo(() => data.reduce((acc, curr) => acc + curr.count, 0), [data]))
can be zero which causes NaN when calculating percent widths; update the
percent/width calculation where you compute (item.count / total * 100) (lines
around 25/38) to guard against division by zero—e.g., treat percent as 0 when
total === 0 or default to 0 using a conditional or short-circuit so the rendered
width and displayed percentage never become NaN and instead show 0% for empty
data.

In `@src/components/dashboard/charts/PerformanceEfficiencyChart.tsx`:
- Around line 21-26: The CTR series calculation in
PerformanceEfficiencyChart.tsx (the series constant where data.map computes
(d.clicks / d.impressions) * 100) doesn't guard against impressions === 0;
update that mapping to return 0 (or another safe default) when d.impressions is
0 or falsy to avoid Infinity/NaN in the chart and tooltips, i.e., add a
conditional check inside the data.map callback so it computes (d.clicks /
d.impressions) * 100 only when d.impressions is truthy and otherwise returns 0.

In `@src/components/dashboard/platform/PlatformDetailCard.tsx`:
- Around line 52-53: The change-rate badge treats 0 as "down"; update
PlatformDetailCard so zero is neutral: for each rate variable
(impressionChangeRate, clicksChangeRate, ctrChangeRate, spendChangeRate) add a
guard that skips/hides the badge when the rate === 0, otherwise compute
direction as rate > 0 ? "up" : "down" and keep the value as `${Math.abs(rate *
100).toFixed(1)}%`; locate the existing expressions that set direction and value
(the blocks around impressionChangeRate, clicksChangeRate, ctrChangeRate,
spendChangeRate) and implement this conditional rendering instead of relying on
the current `> 0` check.
- Around line 33-35: The Tailwind important markers in the innerCardClass string
are using trailing "!" which v4 doesn't recognize; update the innerCardClass
constant in PlatformDetailCard (the string assigned to innerCardClass) so each
class uses prefix "!" syntax (e.g. "!shadow-none" and for hover use
"hover:!shadow-none", and convert "rounded-component-md!", "p-2!", "gap-2!" to
"!rounded-component-md", "!p-2", "!gap-2") so the important modifiers are
applied correctly.

In `@src/components/dashboard/platform/TopPerformanceList.tsx`:
- Around line 35-56: The code coerces item.diffRate null to 0 which hides the
difference between "no data" and "0%"; change the rendering logic in
TopPerformanceList so you read the raw value (e.g., diffRateRaw = item.diffRate)
and only compute isUp and render TrendBadge when diffRateRaw !== null/undefined;
when diffRateRaw is null render nothing or a placeholder like "-" instead of
TrendBadge; update references to diffRate/isUp/Tre ndBadge so calculations use
the non-null checked value (e.g., use Math.abs(diffRateRaw) only after the null
check).

In `@src/pages/dashboard/platform/platformDashboard.mock.ts`:
- Around line 13-31: The diffRate signs in the mock data objects are inverted
relative to the PR description—update the diffRate numeric signs so positive
changes are positive (e.g., GOOGLE diffRate should be +12 instead of -12) across
all provider objects (look for entries with provider names like "GOOGLE",
"NAVER", "META" and their diffRate fields) and likewise correct the diffRate
values in the lower card mock entries (the block referenced as lines 50-79) so
the sign matches the intended up/down arrow direction in the UI.

In `@src/pages/dashboard/platform/PlatformDashboard.tsx`:
- Around line 35-41: The platform selection UI updates selectedPlatform but the
rendered cards always use performanceEfficiencyMock, so wire the selection into
the data source: in the component use selectedPlatform (and isAllView) to
compute a filtered array (e.g., filteredPerformance = isAllView ?
performanceEfficiencyMock : performanceEfficiencyMock.filter(p => p.platform ===
selectedPlatformOrNormalized)) and render that instead of
performanceEfficiencyMock; ensure platformItems labels/values align with the
mock’s platform field (normalize "NAVER"/"Naver" casing or map labels to values)
and update any rendering logic that currently ignores selectedPlatform
(references: selectedPlatform, isAllView, platformItems,
performanceEfficiencyMock).
- Around line 189-191: The "실시간 트래픽 변화" Card renders null when isLoading is
false, leaving an empty card; update the PlatformDashboard component to render
the actual traffic content (e.g., the live chart component) or a minimal
empty-state instead of null. Replace the ternary that currently returns
isLoading ? <TrafficChartSkeleton /> : null with logic that shows <TrafficChart
/> (or an EmptyState/placeholder component) when isLoading is false, ensuring
the Card always contains meaningful content; look for the Card with title "실시간
트래픽 변화", the isLoading variable, and the TrafficChartSkeleton reference to make
the change.
- Around line 32-40: selectedPlatform casing is inconsistent (platformItems uses
label "NAVER" but onClick sets "Naver"), causing display/compare/filter bugs;
fix by defining a Platform literal union type (e.g. type Platform = "전체" |
"Google" | "NAVER" | "Meta"), change the useState hook to
useState<Platform>("전체"), and update platformItems so both labels and
setSelectedPlatform calls use the same canonical casing (use "NAVER"
everywhere); update any comparisons (e.g., isAllView) to rely on the Platform
type to catch future typos at compile time.

In `@src/types/dashboard/platform.ts`:
- Around line 3-9: PLATFORM_MAP is missing the KAKAO entry and is typed too
loosely (Record<string,string>), so update PLATFORM_MAP to include the "KAKAO"
-> "Kakao" mapping and tighten its type to Record<TPlatformProvider, string> (or
a mapped type over TProviderType + "META") so missing keys are caught at compile
time; also change IRoasRanking.provider from string to TPlatformProvider (to
match IAdCount and IPlatformPerformance) so consumers reliably use the same
platform union type and the UI label lookup against PLATFORM_MAP cannot return
undefined.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0aac8923-5234-4702-99ab-20be78480949

📥 Commits

Reviewing files that changed from the base of the PR and between 5a44fd4 and d665192.

⛔ Files ignored due to path filters (1)
  • src/assets/logo/social-logo/circle/meta-circle.svg is excluded by !**/*.svg and included by src/**
📒 Files selected for processing (10)
  • src/components/common/dropdownmenu/DropdownMenu.tsx
  • src/components/dashboard/charts/AdStatusChart.tsx
  • src/components/dashboard/charts/PerformanceEfficiencyChart.tsx
  • src/components/dashboard/charts/performanceEfficiencyChart.config.ts
  • src/components/dashboard/platform/PlatformDetailCard.tsx
  • src/components/dashboard/platform/TopPerformanceList.tsx
  • src/components/dashboard/platform/skeleton/PlatformSkeleton.tsx
  • src/pages/dashboard/platform/PlatformDashboard.tsx
  • src/pages/dashboard/platform/platformDashboard.mock.ts
  • src/types/dashboard/platform.ts

Comment thread src/components/dashboard/charts/AdStatusChart.tsx
Comment thread src/components/dashboard/charts/PerformanceEfficiencyChart.tsx
Comment thread src/components/dashboard/platform/PlatformDetailCard.tsx
Comment thread src/components/dashboard/platform/PlatformDetailCard.tsx Outdated
Comment thread src/components/dashboard/platform/TopPerformanceList.tsx Outdated
Comment thread src/pages/dashboard/platform/platformDashboard.mock.ts Outdated
Comment thread src/pages/dashboard/platform/PlatformDashboard.tsx
Comment thread src/pages/dashboard/platform/PlatformDashboard.tsx
Comment thread src/pages/dashboard/platform/PlatformDashboard.tsx
Comment thread src/types/dashboard/platform.ts
@YermIm
YermIm removed request for Seojegyeong and jjjsun April 4, 2026 13:22
@YermIm
YermIm requested review from Seojegyeong and jjjsun April 4, 2026 17:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/components/dashboard/charts/PerformanceEfficiencyChart.tsx (3)

41-44: Suspense fallback에 로딩 인디케이터를 추가하면 UX가 개선됩니다.

현재 fallback이 빈 div로 설정되어 있어 차트 로딩 중 사용자에게 시각적 피드백이 없습니다. 스켈레톤 UI나 로딩 스피너를 사용하면 로딩 상태를 명확하게 전달할 수 있습니다.

♻️ 제안 예시

기존 PerformanceEfficiencyChartSkeleton을 재사용하거나, 간단한 로딩 인디케이터를 추가:

-      <Suspense fallback={<div className="h-40" />}>
+      <Suspense fallback={<div className="h-40 animate-pulse bg-gray-100 rounded" />}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/dashboard/charts/PerformanceEfficiencyChart.tsx` around lines
41 - 44, Replace the empty Suspense fallback with a visible loading indicator by
reusing the existing PerformanceEfficiencyChartSkeleton (or a spinner) so users
see feedback while the Chart (used with props options and series) loads; update
the Suspense wrapper around Chart in the PerformanceEfficiencyChart component to
render <PerformanceEfficiencyChartSkeleton /> (or a centered spinner) as the
fallback instead of the empty div.

21-39: series도 useMemo로 메모이제이션하면 일관성이 높아집니다.

categoriesoptions는 useMemo로 감싸져 있지만 series는 매 렌더마다 새로 생성됩니다. 컴포넌트가 memo로 감싸져 있어서 실질적인 성능 문제는 크지 않지만, 동일한 패턴을 유지하면 코드 일관성과 가독성이 향상됩니다.

♻️ 제안 수정안
+    const series = useMemo(
+      () => [
-    const series = [
       {
         name: "클릭률(CTR)",
         type: "column",
         data: data.map((d) =>
           d.impressions > 0 ? (d.clicks / d.impressions) * 100 : 0,
         ),
       },
       {
         name: "전환율(CVR)",
         type: "column",
         data: data.map((d) => d.conversion),
       },
       {
         name: "노출수",
         type: "line",
         data: data.map((d) => d.impressions),
       },
-    ];
+      ],
+      [data],
+    );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/dashboard/charts/PerformanceEfficiencyChart.tsx` around lines
21 - 39, The series array in PerformanceEfficiencyChart is recreated on every
render; wrap its creation in useMemo to memoize it (e.g., replace the standalone
series declaration with const series = useMemo(() => [ ...same objects... ],
[data]) ) so the CTR/CVR/impressions mappings are only recomputed when data
changes; ensure you reference the same property names (clicks, impressions,
conversion) inside the memo and import/use React.useMemo if not already
imported.

10-47: 접근성(a11y) 개선을 위해 차트에 대체 텍스트를 고려해 주세요.

시각적 차트는 스크린 리더 사용자에게 정보를 전달하지 못합니다. 차트를 감싸는 영역에 aria-label이나 시각적으로 숨겨진 설명 텍스트를 추가하면 접근성이 향상됩니다.

♻️ 제안 예시
     return (
+      <div aria-label="플랫폼별 클릭률, 전환율, 노출수 비교 차트" role="img">
       <Suspense fallback={<div className="h-40" />}>
         <Chart options={options} series={series} height={150} />
       </Suspense>
+      </div>
     );

코딩 가이드라인에서 "시맨틱 HTML, ARIA 속성 사용 확인"을 명시하고 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/dashboard/charts/PerformanceEfficiencyChart.tsx` around lines
10 - 47, The PerformanceEfficiencyChart component lacks accessible text for
screen readers; wrap the Chart (inside the Suspense) with a semantic container
or pass accessibility props that provide an accessible name/description (e.g.,
add an aria-label or role="img" plus aria-label/aria-describedby on the Chart
wrapper or the Chart element itself) and/or include a visually-hidden
descriptive <span> that summarizes the chart series (CTR, CVR, impressions) so
screen readers can convey the chart content; update PerformanceEfficiencyChart
to render that accessible label/hidden description alongside the existing Chart
render.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/dashboard/charts/PerformanceEfficiencyChart.tsx`:
- Around line 41-45: The Chart component is missing a global chart type so the
per-series type fields are ignored; fix by specifying a chart type either on the
component or in the config: add a type prop to the Chart component (e.g., Chart
type="line" options={options} series={series} ...) in
PerformanceEfficiencyChart.tsx (preferred), or set options.chart.type = "line"
inside performanceEfficiencyChart.config.ts so the mixed series types
(series[].type = "column" / "line") are honored; update whichever file you
change to ensure the global chart type is present while keeping each series'
type intact.

---

Nitpick comments:
In `@src/components/dashboard/charts/PerformanceEfficiencyChart.tsx`:
- Around line 41-44: Replace the empty Suspense fallback with a visible loading
indicator by reusing the existing PerformanceEfficiencyChartSkeleton (or a
spinner) so users see feedback while the Chart (used with props options and
series) loads; update the Suspense wrapper around Chart in the
PerformanceEfficiencyChart component to render
<PerformanceEfficiencyChartSkeleton /> (or a centered spinner) as the fallback
instead of the empty div.
- Around line 21-39: The series array in PerformanceEfficiencyChart is recreated
on every render; wrap its creation in useMemo to memoize it (e.g., replace the
standalone series declaration with const series = useMemo(() => [ ...same
objects... ], [data]) ) so the CTR/CVR/impressions mappings are only recomputed
when data changes; ensure you reference the same property names (clicks,
impressions, conversion) inside the memo and import/use React.useMemo if not
already imported.
- Around line 10-47: The PerformanceEfficiencyChart component lacks accessible
text for screen readers; wrap the Chart (inside the Suspense) with a semantic
container or pass accessibility props that provide an accessible
name/description (e.g., add an aria-label or role="img" plus
aria-label/aria-describedby on the Chart wrapper or the Chart element itself)
and/or include a visually-hidden descriptive <span> that summarizes the chart
series (CTR, CVR, impressions) so screen readers can convey the chart content;
update PerformanceEfficiencyChart to render that accessible label/hidden
description alongside the existing Chart render.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 749e3be1-eb6e-4547-b509-64cf0fbb7af1

📥 Commits

Reviewing files that changed from the base of the PR and between d665192 and 5b3d8a5.

📒 Files selected for processing (6)
  • src/components/dashboard/charts/AdStatusChart.tsx
  • src/components/dashboard/charts/PerformanceEfficiencyChart.tsx
  • src/components/dashboard/platform/PlatformDetailCard.tsx
  • src/components/dashboard/platform/TopPerformanceList.tsx
  • src/pages/dashboard/platform/PlatformDashboard.tsx
  • src/pages/dashboard/platform/platformDashboard.mock.ts
✅ Files skipped from review due to trivial changes (1)
  • src/pages/dashboard/platform/platformDashboard.mock.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/components/dashboard/charts/AdStatusChart.tsx
  • src/components/dashboard/platform/PlatformDetailCard.tsx
  • src/components/dashboard/platform/TopPerformanceList.tsx
  • src/pages/dashboard/platform/PlatformDashboard.tsx

Comment thread src/components/dashboard/charts/PerformanceEfficiencyChart.tsx
@jjjsun

jjjsun commented Apr 5, 2026

Copy link
Copy Markdown
Collaborator

P3: 지금 차트의 색이 파랑/초록/회색으로 사용되고 있는데, 색이 조금 애매하다는 생각이 듭니다..!
그래서 차트 색상을 변경하는건 어떨까 제안드려요.
방안 2가지 정도로 생각했는데,

  1. 플랫폼 브랜드 컬러사용 ->
image google은 #f9ab00 image Naver는 #03c75a image meta는 #1877f2

각각의 브랜드 컬러 사용해서, 브랜드 이미지가 떠오를수있게 표현하는것도 좋을것같아요.
저희 서비스가 3개 플랫폼만으로 진행되기때문에 브랜드 컬러를 이부분만 사용하는것도 좋을것같아요

  1. 저희 서비스 브랜드 컬러사용
    저희 브랜드 chart 기준설정해놓은 컬러 사용해서 깔끔한 이미지를 줄수 있을것같아요.

@jjjsun

jjjsun commented Apr 5, 2026

Copy link
Copy Markdown
Collaborator

P3: 지금 차트의 색이 파랑/초록/회색으로 사용되고 있는데, 색이 조금 애매하다는 생각이 듭니다..! 그래서 차트 색상을 변경하는건 어떨까 제안드려요. 방안 2가지 정도로 생각했는데,

  1. 플랫폼 브랜드 컬러사용 ->

image google은 #f9ab00 image Naver는 #03c75a image meta는 #1877f2
각각의 브랜드 컬러 사용해서, 브랜드 이미지가 떠오를수있게 표현하는것도 좋을것같아요. 저희 서비스가 3개 플랫폼만으로 진행되기때문에 브랜드 컬러를 이부분만 사용하는것도 좋을것같아요

  1. 저희 서비스 브랜드 컬러사용
    저희 브랜드 chart 기준설정해놓은 컬러 사용해서 깔끔한 이미지를 줄수 있을것같아요.

google은 여러가지 컬러를 쓰고있어서, 하나의 브랜드 컬러를 찾기 어려워서 중간지점으로 임의로 설정해두었습니다!

@Seojegyeong Seojegyeong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P4: 확인했습니다! 고생하셨습니다:)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/pages/dashboard/platform/PlatformDashboard.tsx (2)

35-41: ⚠️ Potential issue | 🟠 Major

플랫폼 선택 상태가 상세 카드 데이터에 반영되지 않습니다.

Line 35에서 isAllView를 계산하지만, Line 199에서 항상 performanceEfficiencyMock 전체를 렌더링하고 있어 드롭다운 선택이 실제 결과에 영향을 주지 않습니다.

수정 예시
+  const visiblePerformanceData = isAllView
+    ? performanceEfficiencyMock
+    : performanceEfficiencyMock.filter(
+        (platform) => platform.provider === selectedPlatform,
+      );
...
-          {isLoading
-            ? Array.from({ length: 3 }).map((_, i) => (
-                <PlatformDetailCardSkeleton key={i} />
-              ))
-            : performanceEfficiencyMock.map((platform) => (
-                <PlatformDetailCard key={platform.provider} data={platform} />
-              ))}
+          {isLoading
+            ? Array.from({ length: 3 }).map((_, i) => (
+                <PlatformDetailCardSkeleton key={i} />
+              ))
+            : visiblePerformanceData.map((platform) => (
+                <PlatformDetailCard key={platform.provider} data={platform} />
+              ))}

As per coding guidelines, 1. 상태 관리: 서버 상태(React Query)와 전역 상태(Zustand)의 분리 여부 확인. useMutation, useQuery의 올바른 사용 확인.

Also applies to: 195-201

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/dashboard/platform/PlatformDashboard.tsx` around lines 35 - 41, The
selected platform dropdown isn't affecting the detailed cards because you
compute isAllView from selectedPlatform but still render
performanceEfficiencyMock unconditionally; update the render logic that uses
performanceEfficiencyMock (where the detailed cards are built) to use a derived
displayedData variable: if isAllView is true use performanceEfficiencyMock,
otherwise filter performanceEfficiencyMock by matching the selectedPlatform
value (compare against the item.platform or equivalent field), then map over
displayedData for the cards; ensure you reference selectedPlatform and isAllView
(and platformItems only for selection) so the UI updates when selectedPlatform
changes.

189-191: ⚠️ Potential issue | 🟠 Major

로딩 종료 후 “실시간 트래픽 변화” 카드가 빈 화면으로 남습니다.

Line 190에서 isLoading이 false이면 null을 반환해서 카드가 비어 보입니다. 실제 콘텐츠 또는 최소 empty state를 렌더링해 주세요.

수정 예시
         <Card title="실시간 트래픽 변화" className="min-h-125">
-          {isLoading ? <TrafficChartSkeleton /> : null}
+          {isLoading ? (
+            <TrafficChartSkeleton />
+          ) : (
+            <div className="flex h-full items-center justify-center text-text-sub">
+              실시간 트래픽 데이터를 준비 중입니다.
+            </div>
+          )}
         </Card>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/dashboard/platform/PlatformDashboard.tsx` around lines 189 - 191,
The "실시간 트래픽 변화" Card is left blank because PlatformDashboard currently renders
<TrafficChartSkeleton /> only when isLoading is true and returns null otherwise;
update the Card rendering in PlatformDashboard so that when isLoading is false
it renders the actual traffic content (e.g., <TrafficChart /> or the existing
chart component) or at minimum an empty/placeholder state component instead of
null; locate the Card with title "실시간 트래픽 변화" and replace the conditional that
returns null with the real chart component or a minimal EmptyState component so
the card shows meaningful content after loading.
🧹 Nitpick comments (1)
src/components/dashboard/charts/performanceEfficiencyChart.config.ts (1)

70-73: seriesIndex 매직 넘버(0/1) 의존은 시리즈 순서 변경 시 단위 표기를 깨뜨릴 수 있어요.

지금은 인덱스로 % 여부를 판단해서, 시리즈 배열 순서가 바뀌면 툴팁 단위가 조용히 잘못 표시됩니다. 시리즈 이름 기준 분기로 바꾸면 안전합니다.

♻️ 제안 리팩터링
   tooltip: {
@@
     y: {
-      formatter: (val, { seriesIndex }) => {
-        if (seriesIndex === 0 || seriesIndex === 1) {
+      formatter: (val, { seriesIndex, w }) => {
+        const seriesName = w.config.series?.[seriesIndex]?.name;
+        if (seriesName === "클릭률" || seriesName === "전환율") {
           return `${val.toFixed(2)}%`;
         }
         return val.toLocaleString();
       },
     },
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/dashboard/charts/performanceEfficiencyChart.config.ts` around
lines 70 - 73, The formatter function currently uses magic numbers (seriesIndex
=== 0 || seriesIndex === 1) to decide whether to append '%' which breaks if
series order changes; update the formatter in
performanceEfficiencyChart.config.ts to determine percent units by series name
instead: inside the formatter (params: { seriesIndex, val, ... }), look up the
series name (e.g., from params.seriesName or from the chart's series array using
seriesIndex) and compare against a small, explicit set of percent-series
identifiers (e.g., ['efficiency', 'utilization'] or the actual series.name
values used elsewhere) and append '%' only when the name matches; keep a
sensible fallback for unknown names.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/common/chart/ChartLegend.tsx`:
- Around line 6-7: IChartLegendItem currently allows both colorClass and color
to be undefined which permits items with only label; change the type so at least
one of color or colorClass is required (e.g., replace the optional pair with a
union/utility type that enforces RequiredOne<{ color?: string; colorClass?:
string }, 'color'|'colorClass'> or a two-variant union) and update any usages of
IChartLegendItem (e.g., in ChartLegend rendering/props) to satisfy the new
contract; keep the existing label property as required and ensure components
that build legend items supply either color or colorClass.

In `@src/components/dashboard/charts/performanceEfficiencyChart.config.ts`:
- Line 45: Calls to toLocaleString in this file (notably inside the formatter
function and the other number-formatting helpers) do not specify a locale;
update each toLocaleString(...) invocation to pass "ko-KR" (e.g.,
toLocaleString("ko-KR")) so numbers consistently use Korean formatting rules,
ensuring you change every occurrence including the one used in formatter: (val)
=> ... and the other numeric format helpers in
performanceEfficiencyChart.config.ts.

---

Duplicate comments:
In `@src/pages/dashboard/platform/PlatformDashboard.tsx`:
- Around line 35-41: The selected platform dropdown isn't affecting the detailed
cards because you compute isAllView from selectedPlatform but still render
performanceEfficiencyMock unconditionally; update the render logic that uses
performanceEfficiencyMock (where the detailed cards are built) to use a derived
displayedData variable: if isAllView is true use performanceEfficiencyMock,
otherwise filter performanceEfficiencyMock by matching the selectedPlatform
value (compare against the item.platform or equivalent field), then map over
displayedData for the cards; ensure you reference selectedPlatform and isAllView
(and platformItems only for selection) so the UI updates when selectedPlatform
changes.
- Around line 189-191: The "실시간 트래픽 변화" Card is left blank because
PlatformDashboard currently renders <TrafficChartSkeleton /> only when isLoading
is true and returns null otherwise; update the Card rendering in
PlatformDashboard so that when isLoading is false it renders the actual traffic
content (e.g., <TrafficChart /> or the existing chart component) or at minimum
an empty/placeholder state component instead of null; locate the Card with title
"실시간 트래픽 변화" and replace the conditional that returns null with the real chart
component or a minimal EmptyState component so the card shows meaningful content
after loading.

---

Nitpick comments:
In `@src/components/dashboard/charts/performanceEfficiencyChart.config.ts`:
- Around line 70-73: The formatter function currently uses magic numbers
(seriesIndex === 0 || seriesIndex === 1) to decide whether to append '%' which
breaks if series order changes; update the formatter in
performanceEfficiencyChart.config.ts to determine percent units by series name
instead: inside the formatter (params: { seriesIndex, val, ... }), look up the
series name (e.g., from params.seriesName or from the chart's series array using
seriesIndex) and compare against a small, explicit set of percent-series
identifiers (e.g., ['efficiency', 'utilization'] or the actual series.name
values used elsewhere) and append '%' only when the name matches; keep a
sensible fallback for unknown names.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 88da64bc-8e60-4630-922a-c442b1a4cef1

📥 Commits

Reviewing files that changed from the base of the PR and between 87e3b59 and 9c07eba.

📒 Files selected for processing (4)
  • src/components/common/chart/ChartLegend.tsx
  • src/components/dashboard/charts/AdStatusChart.tsx
  • src/components/dashboard/charts/performanceEfficiencyChart.config.ts
  • src/pages/dashboard/platform/PlatformDashboard.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/dashboard/charts/AdStatusChart.tsx

Comment thread src/components/common/chart/ChartLegend.tsx
@jjjsun

jjjsun commented Apr 6, 2026

Copy link
Copy Markdown
Collaborator

P4: 변경사항 확인했습니다! google 색상이 제가 임의로 정한거라 혹시 더 좋은 색상 아이디어있으시면 추후에 디자인마크업 작업 진행해주셔도 좋을것같아요! 고생하셨어요!

@YermIm
YermIm merged commit de38b5c into develop Apr 6, 2026
3 checks passed
@YermIm
YermIm deleted the feature/#145 branch April 6, 2026 08:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 기능 개발 🎨 Html&css 마크업 & 스타일링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ [Feature] 플랫폼 대시보드 기본 레이아웃 및 상단/하단 핵심 지표 섹션 구현

3 participants