[FE] 대시보드 편집창 - 매출분석 지표 카드 추가 (매출추이 카테고리 제외)#274
Conversation
There was a problem hiding this comment.
Pull request overview
대시보드 편집 모드에서 **매출분석 지표 카드(매출추이 카테고리 제외)**를 미리보기/렌더링할 수 있도록, 관련 UI 컴포넌트와 매출 도메인 타입/상수/유틸 및 차트 렌더링 로직을 확장한 PR입니다.
Changes:
- 매출 현황/유입 구조/패턴 카드 컨텐츠 컴포넌트 및 편집 화면용
EditCardContent추가 - 브리핑 메시지 토큰화(
createMessageToken) 및 비교/트렌드 계산 유틸 추가 - SVG 좌표 계산을 viewBox 기준으로 변경하고 Bar/Line 차트 기능(활성 인덱스 강조 등) 개선
Reviewed changes
Copilot reviewed 93 out of 94 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/utils/shared/period-select/createPeriodTypeProvider.tsx | Context 기본값을 undefined로 변경해 오용 방지 |
| frontend/src/utils/shared/nullable.ts | Nullable 유틸 타입 추가 |
| frontend/src/utils/shared/line-chart/getXCoordinate.ts | X좌표 계산 입력을 svgWidth로 변경 |
| frontend/src/utils/shared/index.ts | shared 유틸 export 정리(Nullable/assertNever 추가 등) |
| frontend/src/utils/shared/getCoordinate.ts | 좌표 계산 입력을 svgWidth로 변경 |
| frontend/src/utils/shared/assertNever.ts | exhaustive check용 assertNever 추가 |
| frontend/src/utils/sales/index.ts | 매출 대시보드 유틸 export 추가 |
| frontend/src/utils/sales/dashboard/index.ts | 메시지 토큰 유틸 barrel 추가 |
| frontend/src/utils/sales/dashboard/createMessageToken.ts | 브리핑 메시지 토큰 생성 유틸 추가 |
| frontend/src/utils/sales/dashboard-sales-pattern/index.ts | 매출 패턴 유틸 barrel 추가 |
| frontend/src/utils/sales/dashboard-sales-pattern/getSalesPatternPeaktimeMessage.ts | 피크타임 브리핑 메시지 유틸 추가 |
| frontend/src/utils/sales/dashboard-sales-pattern/getSalesPatternByDayMessage.ts | 요일별 브리핑 메시지 유틸 추가 |
| frontend/src/utils/sales/dashboard-sales-pattern/createPeakTimeSeries.ts | 피크타임 차트 시리즈 변환 유틸 추가 |
| frontend/src/utils/sales/dashboard-sales-income/index.ts | 매출 유입 구조 메시지 유틸 barrel 추가 |
| frontend/src/utils/sales/dashboard-sales-income/getSalesIncomeStructureComparisionMessage.ts | 유입 구조 비교 브리핑 메시지 생성 유틸 추가 |
| frontend/src/utils/sales/dashboard-current-sales/index.ts | 매출 현황 메시지 유틸 barrel 추가 |
| frontend/src/utils/sales/dashboard-current-sales/getSalesCurrentComparisonMessage.ts | 매출 현황 비교 브리핑 메시지 유틸 추가 |
| frontend/src/utils/dashboard/index.ts | 대시보드 유틸 export에 getMetricTrend 추가 |
| frontend/src/utils/dashboard/getMetricTrend.ts | 변동값 기반 트렌드 계산 유틸 추가 |
| frontend/src/types/shared/line-chart/lineChartDataType.ts | LineChart datum을 공통 ChartDatum으로 통일 |
| frontend/src/types/shared/line-chart/index.ts | LineChart 타입 export 정리 |
| frontend/src/types/shared/index.ts | shared 타입 export에 chart 공통 타입 추가 |
| frontend/src/types/shared/chart/index.ts | chart 공통 타입 barrel 추가 |
| frontend/src/types/shared/chart/chartDataType.ts | Bar/Line 공통 datum/series 타입 추가 |
| frontend/src/types/shared/bar-chart/barChartDataType.ts | BarChart datum을 ChartDatum으로 통일 |
| frontend/src/types/sales/index.ts | 매출 도메인 타입 export 대거 추가 |
| frontend/src/types/sales/dto/index.ts | 매출 DTO barrel 추가 |
| frontend/src/types/sales/dto/getSalesByDayDto.ts | 요일별 매출 DTO 추가 |
| frontend/src/types/sales/dto/getRealTimeSalesDto.ts | 실시간 매출 DTO 추가 |
| frontend/src/types/sales/dto/getPeakTimeDto.ts | 피크타임 DTO 추가 |
| frontend/src/types/sales/dto/getOrderCountDto.ts | 주문건수 DTO 추가 |
| frontend/src/types/sales/dto/getIncomStructureBySalesTypeDto.ts | 판매유형별 유입 구조 DTO 추가 |
| frontend/src/types/sales/dto/getIncomStructureByPaymentMethodDto.ts | 결제수단별 유입 구조 DTO 추가 |
| frontend/src/types/sales/dto/getIncomStructureByOrderMethodDto.ts | 주문수단별 유입 구조 DTO 추가 |
| frontend/src/types/sales/dto/getAveragePriceDto.ts | 평균가 DTO 추가 |
| frontend/src/types/sales/dashboard-sales-pattern/salesByDay.ts | 요일별 패턴 타입 추가 |
| frontend/src/types/sales/dashboard-sales-pattern/peakTime.ts | 피크타임 타입 추가 |
| frontend/src/types/sales/dashboard-sales-pattern/index.ts | 매출 패턴 타입 barrel 추가 |
| frontend/src/types/sales/dashboard-sales-income/salesIncomeStructureInsight.ts | 유입 구조 인사이트 타입 추가 |
| frontend/src/types/sales/dashboard-sales-income/index.ts | 유입 구조 타입 barrel 추가 |
| frontend/src/mocks/auth/authHandler.ts | refresh mock 동작 변경(현재 passthrough) |
| frontend/src/hooks/shared/line-chart/useLineChart.ts | viewBox 기반 좌표 계산으로 변경 |
| frontend/src/hooks/shared/bar-chart/useBarChart.ts | viewBox 기반 좌표 계산으로 변경 |
| frontend/src/constants/sales/salesUnit.ts | 매출 단위 상수 추가 |
| frontend/src/constants/sales/salesSource.ts | Sales source 타입가드 추가 및 색상 조정 |
| frontend/src/constants/sales/index.ts | sales 도메인 상수 export 확장 |
| frontend/src/constants/sales/dashboard/index.ts | dashboard 하위 상수 barrel 추가 |
| frontend/src/constants/sales/dashboard/briefingMessageHighlightColor.ts | 브리핑 하이라이트 컬러 클래스 상수 추가 |
| frontend/src/constants/sales/dashboard-sales-pattern/salesByDay.ts | 요일별 패턴 예시 데이터/차트 상수 추가 |
| frontend/src/constants/sales/dashboard-sales-pattern/peakTime.ts | 피크타임 예시 데이터 상수 추가 |
| frontend/src/constants/sales/dashboard-sales-pattern/index.ts | 매출 패턴 상수 barrel 추가 |
| frontend/src/constants/sales/dashboard-sales-income/salesType.ts | 판매유형별 예시 데이터/차트 타이틀 상수 추가 |
| frontend/src/constants/sales/dashboard-sales-income/paymentMethod.ts | 결제수단별 예시 데이터/차트 타이틀 상수 추가 |
| frontend/src/constants/sales/dashboard-sales-income/orderMethod.ts | 주문수단별 예시 데이터/차트 타이틀 상수 추가 |
| frontend/src/constants/sales/dashboard-sales-income/index.ts | 유입 구조 상수 barrel 추가 |
| frontend/src/constants/sales/dashboard-current-sales/realSales.ts | 실매출 카드 상수 추가 |
| frontend/src/constants/sales/dashboard-current-sales/orderCount.ts | 주문건수 카드 상수 추가 |
| frontend/src/constants/sales/dashboard-current-sales/index.ts | 매출 현황 상수 barrel 추가 |
| frontend/src/constants/sales/dashboard-current-sales/averagePrice.ts | 평균가 카드 상수 추가 |
| frontend/src/constants/dashboard/metricTrend.ts | METRIC_TREND 상수/타입 추가 |
| frontend/src/constants/dashboard/index.ts | dashboard constants export 정리 |
| frontend/src/constants/dashboard/dashboardMetric.ts | 섹션 키 오탈자 수정 및 타입 유틸 추가 |
| frontend/src/components/shared/line-chart/YGuideLine.tsx | 가이드라인 렌더링을 svgWidth 기반으로 변경 |
| frontend/src/components/shared/line-chart/XGuideLine.tsx | svgRect 의존 제거 및 경량화 |
| frontend/src/components/shared/line-chart/LineChart.tsx | viewBox 기반 hook 사용으로 변경 |
| frontend/src/components/shared/index.ts | shared export에 LineChart 추가 |
| frontend/src/components/shared/images/images.stories.tsx | trend 아이콘 이미지 목록 추가 |
| frontend/src/components/shared/edit-card-wrapper/TrashCanIconButton.tsx | shadcn Button으로 교체 |
| frontend/src/components/shared/edit-card-wrapper/PlusIconButton.tsx | shadcn Button으로 교체 |
| frontend/src/components/shared/edit-card-wrapper/EditCardWrapper.tsx | 높이 계산/innerClassName 추가 및 transformOrigin 변경 |
| frontend/src/components/shared/default-card-wrapper/DefaultCardWrapper.tsx | width/height props 제거 |
| frontend/src/components/shared/default-card-wrapper/DefaultCardWrapper.stories.tsx | story args를 className 기반으로 변경 |
| frontend/src/components/shared/bar-chart/BarSeries.tsx | 활성 막대 강조를 index 기반으로 변경 |
| frontend/src/components/shared/bar-chart/BarChart.tsx | activeDataIndex 지원 및 viewBox 기반 hook 사용 |
| frontend/src/components/shared/bar-chart/BarChart.stories.tsx | activeDataIndex 데모 및 리얼타임 예제 보강 |
| frontend/src/components/sales/sales-source/sales-source-chart/index.ts | legend export 추가 |
| frontend/src/components/sales/sales-source/index.ts | sales-source export 확장 |
| frontend/src/components/sales/index.ts | 대시보드 카드 컨텐츠 export 추가 |
| frontend/src/components/sales/dashboard-sales-pattern/index.ts | 패턴 컨텐츠 barrel 추가 |
| frontend/src/components/sales/dashboard-sales-pattern/SalesByDayContent.tsx | 요일별 패턴 카드 UI 추가(BarChart 연동) |
| frontend/src/components/sales/dashboard-sales-pattern/PeakTimeContent.tsx | 피크타임 카드 UI 추가(LineChart 연동) |
| frontend/src/components/sales/dashboard-sales-pattern/PeakTimeChartCaption.tsx | 피크타임 차트 캡션 컴포넌트 추가 |
| frontend/src/components/sales/dashboard-sales-income/index.ts | 유입 구조 컨텐츠 barrel 추가 |
| frontend/src/components/sales/dashboard-sales-income/SalesTypeContent.tsx | 판매유형별 유입 구조 카드 컨텐츠 추가 |
| frontend/src/components/sales/dashboard-sales-income/PaymentMethodContent.tsx | 결제수단별 유입 구조 카드 컨텐츠 추가 |
| frontend/src/components/sales/dashboard-sales-income/OrderMethodContent.tsx | 주문수단별 유입 구조 카드 컨텐츠 추가 |
| frontend/src/components/sales/dashboard-sales-income/DashboardSalesIncomeContent.tsx | 유입 구조 공통 레이아웃/compound 컴포넌트 추가 |
| frontend/src/components/sales/dashboard-current-sales/index.ts | 매출 현황 컨텐츠 barrel 추가 |
| frontend/src/components/sales/dashboard-current-sales/RealSalesContent.tsx | 실매출 카드 컨텐츠 추가 |
| frontend/src/components/sales/dashboard-current-sales/OrderCountContent.tsx | 주문건수 카드 컨텐츠 추가 |
| frontend/src/components/sales/dashboard-current-sales/CurrentSalesContent.tsx | 매출 현황 공통 compound 컴포넌트 추가 |
| frontend/src/components/sales/dashboard-current-sales/AveragePriceContent.tsx | 평균가 카드 컨텐츠 추가 |
| frontend/src/components/dashboard/dashboard-edit/EditCardContent.tsx | 편집 화면 카드별 미리보기 컨텐츠 스위처 추가 |
| frontend/src/components/dashboard/dashboard-edit/CardEditViewCard.tsx | 카드 미리보기를 EditCardContent로 대체 |
Comments suppressed due to low confidence (1)
frontend/src/mocks/auth/authHandler.ts:53
/auth/refreshMSW 핸들러에서HttpResponse.json(...)을 호출만 하고 반환하지 않아 응답이 무시됩니다. 현재는 항상passthrough()가 반환되어 실제 네트워크로 빠지는데, 의도한 동작이 ‘목 응답’이라면HttpResponse.json(...)을return하도록 수정하고passthrough()를 제거해 주세요. 반대로 ‘갱신 비활성화’가 목적이라면HttpResponse.json(...)호출을 제거해 dead code가 없도록 정리해 주세요.
frontend/src/utils/sales/dashboard-sales-income/getSalesIncomeStructureComparisonMessage.ts
Show resolved
Hide resolved
frontend/src/utils/sales/dashboard-sales-income/getSalesIncomeStructureComparisionMessage.ts
Outdated
Show resolved
Hide resolved
frontend/src/utils/sales/dashboard-sales-pattern/getSalesPatternPeaktimeMessage.ts
Outdated
Show resolved
Hide resolved
frontend/src/components/sales/dashboard-current-sales/OrderCountContent.tsx
Outdated
Show resolved
Hide resolved
frontend/src/components/sales/dashboard-sales-income/OrderMethodContent.tsx
Outdated
Show resolved
Hide resolved
| export type Nullable<T> = { | ||
| [P in keyof T]?: T[P]; | ||
| }; |
There was a problem hiding this comment.
Nullable<T>가 실제로는 모든 프로퍼티를 optional로 만드는 형태라 Partial<T>와 동일하며, 일반적으로 기대하는 T | null/null 허용과 의미가 다릅니다. 용도에 맞게 이름을 PartialProps/Optional 등으로 바꾸거나(또는 Partial<T>를 직접 사용) 진짜 nullable 의미가 필요하다면 T | null/프로퍼티 T[P] | null 형태로 정의를 조정해 주세요.
There was a problem hiding this comment.
아 Partial 있는데 ts 까막눈 이슈네요.. 삭제하겠습니다.
frontend/src/components/sales/dashboard-current-sales/RealSalesContent.tsx
Outdated
Show resolved
Hide resolved
frontend/src/components/sales/dashboard-sales-income/SalesTypeContent.tsx
Outdated
Show resolved
Hide resolved
frontend/src/components/sales/dashboard-sales-income/PaymentMethodContent.tsx
Outdated
Show resolved
Hide resolved
| @@ -0,0 +1,3 @@ | |||
| export const assertNever = (value: never, message?: string): never => { | |||
| @@ -0,0 +1,20 @@ | |||
| import { | |||
There was a problem hiding this comment.
[p5] 하이라이트를 마주하고 소리 지르는 영재님이 상상되네요 ... 객체로 처리하니 깔끔하고 좋습니다~
| }: GetSalesCurrentComparisonMessageArgs): MessageToken[] => { | ||
| const weekday = DAY_OF_WEEK_LIST[new Date().getDay()]; | ||
|
|
||
| const PERIOD_TEXT = { |
There was a problem hiding this comment.
[p3] getPeriodComparisonMessage.ts 파일에서 같은 일을 하고 있는데 파일 삭제하고, 이를 사용하고 있는 SalesComparison.tsx 컴포넌트를 작업하신 내용 바탕으로 리팩터링 부탁 드립니다!
There was a problem hiding this comment.
이거는 대시보드 SSE 작업하는데에서 반영하겠습니다 ! 이 브랜치에서 반영하면 지금 올린 PR들에도 다 반영되어야해서 ㅠㅠ
| @@ -0,0 +1,19 @@ | |||
| export type SalesIncomeStructureTopType = | |||
There was a problem hiding this comment.
[p2] salesSource.ts에 있는 const 객체에서 DeepValueOf 유틸 함수를 통해 이렇게 타입을 뽑아낼 수 있어요. 중복 정의되고 있는 것 같아서 말씀 드린 방식으로 바꿔주시면 감사하겠습니다!
There was a problem hiding this comment.
feature/#302-fe-dashbard-card-ui
이 브랜치에 반영해놓겠습니다 ~
| } from '../dashboard-sales-income'; | ||
|
|
||
| interface SalesTypeItem { | ||
| salesType: Extract<SalesIncomeStructureTopType, '홀' | '포장' | '배달'>; |
There was a problem hiding this comment.
[p3] salesType, payMethod, orderChannel 타입 따로 export 하면 SalesSourceType 대신 타입 내러잉 하는 데 재사용 될 수 있을 것 같아요. 그리고 Extract 대신 SALES_SOURCE.SALE_TYPE 상수에서 ValueOf로 뽑아낼 수도 있을 것 같습니다.
There was a problem hiding this comment.
feature/#302-fe-dashbard-card-ui 해당 브랜치에서 반영했습니다 ~
| } from '../dashboard-sales-income'; | ||
|
|
||
| interface OrderMethodItem { | ||
| orderChannel: Extract< |
There was a problem hiding this comment.
[p4] order method / order channel 명칭 통일해주면 좋을 것 같습니다!
There was a problem hiding this comment.
이건 백엔드 DTO명을 그대로 따라서..
orderChannel로 맞춰야겠네요 ..
| ...Object.values(SALES_SOURCE.PAYMENT_METHOD), | ||
| ]; | ||
|
|
||
| export const isSalesSourceType = (value: string): value is SalesSourceType => { |
There was a problem hiding this comment.
[p3] 여기도 마찬가지로 DeepValueOf 함수 사용해서 만든 타입과 비교하면 더 깔끔하게 할 수 있을 것 같네요.
There was a problem hiding this comment.
이부분은 value가 string 타입인데, 위에 있는 객체에 object.values로 접근하면 value에 타입 단언을 해줘야해서 저렇게 했습니다 !
| * 결과: 'SLS_01_01' | 'SLS_01_02' | 'SLS_01_03' | 'SLS_02_01' | 'SLS_02_02' | 'SLS_02_03' | 'SLS_03_01' | 'SLS_03_02' | 'SLS_03_03'; | ||
| * | ||
| */ | ||
| export type ExtractCardCodesFromSection<T> = T extends MetricSection |
| height: | ||
| Math.max(EDIT_CARD_WRAPPER.MIN_HEIGHT, computedCardHeight) * sizeY + | ||
| GRID_GAP * (sizeY - 1), // 최소 높이 147px, gap 20px | ||
| Math.max(EDIT_CARD_WRAPPER.MIN_HEIGHT, computedCardHeight) + GRID_GAP, // 최소 높이 147px, |
There was a problem hiding this comment.
[p2] 스크린샷 보니 미묘하게 아래에 마진이 남고 있어요. 높이에 GRID_GAP이 들어가지 않아도 될 것 같습니다!
There was a problem hiding this comment.
이거 대시보드 SSE 브랜치에서 (gap * sizeY - 1)로 변경했습니다 !
| METRIC_LABEL, | ||
| } = AVERAGE_PRICE; | ||
|
|
||
| type AveragePriceCardCodes = ExtractCardCodes< |
There was a problem hiding this comment.
[p5] 타입 내러잉 좋습니다! 상세분석 컴포넌트들도 리팩터링이 ,, 필요하겠군요
| )} | ||
| > | ||
| <div className="h-45 w-45"> | ||
| <DoughnutChart title={title} chartData={chartData} /> |
There was a problem hiding this comment.
[p3] 여기 도넛차트 애니메이션 끄는 게 나을 것 같은데 어떻게 생각하시나요?
There was a problem hiding this comment.
음.. 일단 기능적인 결함은 아니어서 이번주에 기능 개발끝나고 생각해보죠 !
lwjmcn
left a comment
There was a problem hiding this comment.
상수 양이 정말 어마어마어마어마 하네요...
1875 line changed가 이해가 됩니다
수많은 분기 처리 추상화도 하시고 예시 데이터도 뚝딱뚝딱 만드시느라 고생 정말 많으셨습니다!
mskwon02
left a comment
There was a problem hiding this comment.
[p5]메뉴분석 지표카드 만들 때 많이 참고했습니다! 감사합니다~~
#️⃣ 변경 사항
매출 분석 대시보드 UI 구현 및 관련 도메인 로직(DTO, 상수, 유틸리티)이 대거 추가되었습니다. 주요 변경 사항은 다음과 같습니다.
EditCardContent컴포넌트를 구현하고 예시 데이터를 연결했습니다.LineChart와BarChart의 유연성을 높이기 위해 강조 색상 지정 및 좌표 계산 로직을 개선하고, 카드 래퍼(EditCardWrapper)의 스타일과 인터페이스를 수정했습니다.sales도메인의 상수, 타입, 유틸리티 함수들을 현황(current-sales), 유입 구조(sales-income), 패턴(sales-pattern) 서브 도메인으로 분리하여 관리 효율성을 높였습니다.#️⃣ 작업 상세 내용
RealSalesContent,OrderCountContent,AveragePriceContent: 매출 현황 지표 카드 전용 컨텐츠.SalesTypeContent,OrderMethodContent,PaymentMethodContent: 도넛 차트 기반 매출 유입 구조 컨텐츠.PeakTimeContent,SalesByDayContent: 라인/바 차트 기반 매출 패턴 분석 컨텐츠.EditCardContent: 대시보드 편집 화면에서 카드별 예시 데이터를 렌더링하는 통합 컴포넌트.getSalesCurrentComparisonMessage: 지표 변동에 따른 동적 브리핑 메시지 생성.getMetricTrend: 데이터 비교를 통한 상승/하락/유지 경향성 판단 로직.createPeakTimeSeries: 피크타임 차트용 데이터 변환 유틸리티.BarChart: 특정 인덱스의 막대를 강조할 수 있는 기능 추가.LineChart:svg viewbox기반의 높이/너비 계산 방식으로 변경하여 렌더링 정확도 개선.EditCardWrapper: 카드 사이즈(sizeX) 및 추가/삭제 버튼(Shadcn UI 교체) 로직 수정.추가 설명
매출분석 공통
createMessageToken활용첨부한 사진처럼 텍스트의 일부가 강조되는 형식이 불규칙했습니다. 위와 같은 UI에 대응하기 위해
createMessageToken유틸 함수를 추가했습니다.createMessageToken은 문장을 토큰 배열로 분해해 하나의 문장에서 강조할 구간만 색상 스타일을 줄 수 있게 합니다.구조는 다음과 같습니다.
MessageToken[]{ text, isHighlight, highlightColor }핵심 포인트는 "문구 생성 로직은 유틸에서, 스타일 적용은 UI 컴포넌트에서 분리"하는 것입니다.
사용 방식
예시 코드
위와 같이 활용할 수 있습니다.
Compound 패턴 활용
CurrentSalesContent,DashboardMainContent라는 공통 컴포넌트 추가위와 같이 compound 패턴을 통해 비슷하지만 UI가 달라지는 부분에 대응하였습니다.
각 카테고리에서 활용하는 공통 컴포넌트는 아래와 같습니다.
CurrentSalesContentDashboardMainContent차트 관련 변경사항
대시보드 카드가
css transform: scale(...)환경에서 렌더링될 때, 화면 픽셀 기준(getBoundingClientRect) 좌표와 SVG 내부 좌표계가 어긋나서 차트가 viewbox의 크기보다 한참 작게 렌더링되는 문제가 있었습니다.때문에, getBoundingClientRect 기반에서 svg viewbox를 기준으로 좌표를 계산하도록 수정했습니다.
EditCardWrapper 변경사항
EditCardWrapper의 height가 비정상적으로 높게 계산되는 문제를 해결했습니다. 자식 컴포넌트의 높이가 최소 카드 높이 이상일 때도 sizeY를 곱하여, 자식 컴포넌트의 높이와 최소 카드 높이에 sizeY를 곱하지 않도록 하였습니다.
또한, EditCardWrapper의 자식 content를 감싸는 div를 커스텀할 수 있게
innerClassName도 추가했습니다.#️⃣ 관련 이슈
📸 스크린샷 (선택)
변경 전
변경 후
2026-02-15.8.32.15.mov
📎 참고할만한 자료 (선택)