feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 게이지 서브타입 컴포넌트
|
|
|
|
|
*
|
|
|
|
|
* SVG 기반 반원형 게이지 (외부 라이브러리 불필요)
|
|
|
|
|
* min/max/target/current 표시, 달성률 구간별 색상
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import React from "react";
|
2026-02-11 14:23:20 +09:00
|
|
|
import type { DashboardItem, FontSize } from "../../types";
|
|
|
|
|
import { TEXT_ALIGN_CLASSES } from "../../types";
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
import { abbreviateNumber } from "../utils/formula";
|
|
|
|
|
|
2026-02-11 14:23:20 +09:00
|
|
|
/** FontSize -> SVG 직접 fontSize(px) 매핑 */
|
|
|
|
|
const SVG_FONT_SIZE_MAP: Record<FontSize, number> = {
|
|
|
|
|
xs: 14,
|
|
|
|
|
sm: 18,
|
|
|
|
|
base: 24,
|
|
|
|
|
lg: 32,
|
|
|
|
|
xl: 48,
|
|
|
|
|
};
|
|
|
|
|
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
// ===== Props =====
|
|
|
|
|
|
|
|
|
|
export interface GaugeItemProps {
|
|
|
|
|
item: DashboardItem;
|
|
|
|
|
data: number | null;
|
|
|
|
|
/** 동적 목표값 (targetDataSource로 조회된 값) */
|
|
|
|
|
targetValue?: number | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===== 게이지 색상 판정 =====
|
|
|
|
|
|
|
|
|
|
function getGaugeColor(
|
|
|
|
|
percentage: number,
|
|
|
|
|
ranges?: { min: number; max: number; color: string }[]
|
|
|
|
|
): string {
|
|
|
|
|
if (ranges?.length) {
|
|
|
|
|
const match = ranges.find((r) => percentage >= r.min && percentage <= r.max);
|
|
|
|
|
if (match) return match.color;
|
|
|
|
|
}
|
|
|
|
|
// 기본 색상 (달성률 기준)
|
|
|
|
|
if (percentage >= 80) return "#10b981"; // emerald
|
|
|
|
|
if (percentage >= 50) return "#f59e0b"; // amber
|
|
|
|
|
return "#ef4444"; // rose
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===== 메인 컴포넌트 =====
|
|
|
|
|
|
|
|
|
|
export function GaugeItemComponent({
|
|
|
|
|
item,
|
|
|
|
|
data,
|
|
|
|
|
targetValue,
|
|
|
|
|
}: GaugeItemProps) {
|
2026-02-11 14:23:20 +09:00
|
|
|
const { visibility, gaugeConfig, itemStyle } = item;
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
const current = data ?? 0;
|
|
|
|
|
const min = gaugeConfig?.min ?? 0;
|
|
|
|
|
const max = gaugeConfig?.max ?? 100;
|
|
|
|
|
const target = targetValue ?? gaugeConfig?.target ?? max;
|
|
|
|
|
|
2026-02-11 14:23:20 +09:00
|
|
|
// 라벨 정렬만 사용자 설정
|
|
|
|
|
const labelAlignClass = TEXT_ALIGN_CLASSES[itemStyle?.labelAlign ?? "center"];
|
|
|
|
|
|
|
|
|
|
// SVG 내부 텍스트는 기본값 고정 (사용자 설정 연동 제거)
|
|
|
|
|
const svgValueFontSize = SVG_FONT_SIZE_MAP["base"]; // 24
|
|
|
|
|
const svgSubFontSize = SVG_FONT_SIZE_MAP["xs"]; // 14
|
|
|
|
|
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
// 달성률 계산 (0~100)
|
|
|
|
|
const range = max - min;
|
|
|
|
|
const percentage = range > 0 ? Math.min(100, Math.max(0, ((current - min) / range) * 100)) : 0;
|
|
|
|
|
const gaugeColor = getGaugeColor(percentage, gaugeConfig?.colorRanges);
|
|
|
|
|
|
|
|
|
|
// SVG 반원 게이지 수치
|
|
|
|
|
const cx = 100;
|
|
|
|
|
const cy = 90;
|
|
|
|
|
const radius = 70;
|
|
|
|
|
// 반원: 180도 -> percentage에 비례한 각도
|
|
|
|
|
const startAngle = Math.PI; // 180도 (왼쪽)
|
|
|
|
|
const endAngle = Math.PI - (percentage / 100) * Math.PI; // 0도 (오른쪽) 방향
|
|
|
|
|
|
|
|
|
|
const startX = cx + radius * Math.cos(startAngle);
|
|
|
|
|
const startY = cy - radius * Math.sin(startAngle);
|
|
|
|
|
const endX = cx + radius * Math.cos(endAngle);
|
|
|
|
|
const endY = cy - radius * Math.sin(endAngle);
|
|
|
|
|
const largeArcFlag = percentage > 50 ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
return (
|
2026-02-10 17:18:00 +09:00
|
|
|
<div className="@container flex h-full w-full flex-col items-center justify-center p-2">
|
2026-02-11 14:23:20 +09:00
|
|
|
{/* 라벨 - 사용자 정렬 적용 */}
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
{visibility.showLabel && (
|
2026-02-11 14:23:20 +09:00
|
|
|
<p className={`w-full shrink-0 truncate text-muted-foreground text-xs @[250px]:text-sm ${labelAlignClass}`}>
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
{item.label}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
|
2026-02-10 17:18:00 +09:00
|
|
|
{/* 게이지 SVG - 높이/너비 모두 반응형 */}
|
|
|
|
|
<div className="flex min-h-0 flex-1 items-center justify-center w-full">
|
|
|
|
|
<svg
|
|
|
|
|
viewBox="0 0 200 110"
|
|
|
|
|
className="h-full w-auto max-w-full"
|
|
|
|
|
preserveAspectRatio="xMidYMid meet"
|
|
|
|
|
>
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
{/* 배경 반원 (회색) */}
|
|
|
|
|
<path
|
|
|
|
|
d={`M ${cx - radius} ${cy} A ${radius} ${radius} 0 0 1 ${cx + radius} ${cy}`}
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="#e5e7eb"
|
|
|
|
|
strokeWidth="12"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{/* 값 반원 (색상) */}
|
|
|
|
|
{percentage > 0 && (
|
|
|
|
|
<path
|
|
|
|
|
d={`M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endX} ${endY}`}
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke={gaugeColor}
|
|
|
|
|
strokeWidth="12"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* 중앙 텍스트 */}
|
|
|
|
|
{visibility.showValue && (
|
|
|
|
|
<text
|
|
|
|
|
x={cx}
|
|
|
|
|
y={cy - 10}
|
|
|
|
|
textAnchor="middle"
|
2026-02-11 14:23:20 +09:00
|
|
|
className="fill-foreground font-bold"
|
|
|
|
|
fontSize={svgValueFontSize}
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
>
|
|
|
|
|
{abbreviateNumber(current)}
|
|
|
|
|
</text>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* 퍼센트 */}
|
|
|
|
|
<text
|
|
|
|
|
x={cx}
|
|
|
|
|
y={cy + 10}
|
|
|
|
|
textAnchor="middle"
|
2026-02-11 14:23:20 +09:00
|
|
|
className="fill-muted-foreground"
|
|
|
|
|
fontSize={svgSubFontSize}
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
>
|
|
|
|
|
{percentage.toFixed(1)}%
|
|
|
|
|
</text>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* 목표값 */}
|
|
|
|
|
{visibility.showTarget && (
|
2026-02-10 17:18:00 +09:00
|
|
|
<p className="shrink-0 text-xs text-muted-foreground">
|
feat(pop-dashboard): Phase 0 공통 타입 + Phase 1 대시보드 컴포넌트 구현
Phase 0: 공통 인프라 타입 정의
- ColumnBinding, JoinConfig, DataSourceConfig, PopActionConfig 등
- FilterOperator, AggregationType, SortConfig 타입
Phase 1: pop-dashboard 컴포넌트
- 4개 서브타입: KpiCard, ChartItem, GaugeItem, StatCard
- 4개 표시모드: ArrowsMode, AutoSlideMode, GridMode, ScrollMode
- 설정패널(PopDashboardConfig), 미리보기(PopDashboardPreview)
- 계산식 엔진(formula.ts), 데이터 조회(dataFetcher.ts)
- 팔레트/렌더러/타입 시스템 연동
fix(pop-text): DateTimeDisplay isRealtime 기본값 true로 수정
EOF
2026-02-10 11:04:18 +09:00
|
|
|
목표: {abbreviateNumber(target)}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|