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";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* pop-dashboard 디자이너 미리보기 컴포넌트
|
|
|
|
|
*
|
|
|
|
|
* 실제 데이터 없이 더미 레이아웃으로 미리보기 표시
|
|
|
|
|
* 디자이너가 설정 변경 시 즉시 미리보기 확인 가능
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import React from "react";
|
|
|
|
|
import { BarChart3, PieChart, Gauge, LayoutList } from "lucide-react";
|
|
|
|
|
import type { PopDashboardConfig, DashboardSubType } from "../types";
|
2026-02-10 14:22:30 +09:00
|
|
|
import { migrateConfig } from "./PopDashboardComponent";
|
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 SUBTYPE_ICONS: Record<DashboardSubType, React.ReactNode> = {
|
|
|
|
|
"kpi-card": <BarChart3 className="h-4 w-4" />,
|
|
|
|
|
chart: <PieChart className="h-4 w-4" />,
|
|
|
|
|
gauge: <Gauge className="h-4 w-4" />,
|
|
|
|
|
"stat-card": <LayoutList className="h-4 w-4" />,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SUBTYPE_LABELS: Record<DashboardSubType, string> = {
|
|
|
|
|
"kpi-card": "KPI",
|
|
|
|
|
chart: "차트",
|
|
|
|
|
gauge: "게이지",
|
|
|
|
|
"stat-card": "통계",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ===== 모드 라벨 =====
|
|
|
|
|
|
|
|
|
|
const MODE_LABELS: Record<string, string> = {
|
|
|
|
|
arrows: "좌우 버튼",
|
|
|
|
|
"auto-slide": "자동 슬라이드",
|
|
|
|
|
scroll: "스크롤",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ===== 더미 아이템 프리뷰 =====
|
|
|
|
|
|
|
|
|
|
function DummyItemPreview({
|
|
|
|
|
subType,
|
|
|
|
|
label,
|
|
|
|
|
}: {
|
|
|
|
|
subType: DashboardSubType;
|
|
|
|
|
label: string;
|
|
|
|
|
}) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex h-full w-full flex-col items-center justify-center gap-1 rounded border border-dashed border-muted-foreground/30 bg-muted/20 p-2">
|
|
|
|
|
<span className="text-muted-foreground">
|
|
|
|
|
{SUBTYPE_ICONS[subType]}
|
|
|
|
|
</span>
|
|
|
|
|
<span className="truncate text-[10px] text-muted-foreground">
|
|
|
|
|
{label || SUBTYPE_LABELS[subType]}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===== 메인 미리보기 =====
|
|
|
|
|
|
|
|
|
|
export function PopDashboardPreviewComponent({
|
|
|
|
|
config,
|
|
|
|
|
}: {
|
|
|
|
|
config?: PopDashboardConfig;
|
|
|
|
|
}) {
|
2026-02-10 12:20:44 +09:00
|
|
|
// config가 빈 객체 {} 또는 items가 없는 경우 방어
|
|
|
|
|
if (!config || !Array.isArray(config.items) || !config.items.length) {
|
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
|
|
|
return (
|
|
|
|
|
<div className="flex h-full w-full flex-col items-center justify-center gap-1 overflow-hidden">
|
|
|
|
|
<BarChart3 className="h-6 w-6 text-muted-foreground/50" />
|
|
|
|
|
<span className="text-[10px] text-muted-foreground">대시보드</span>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const visibleItems = config.items.filter((i) => i.visible);
|
2026-02-10 14:22:30 +09:00
|
|
|
|
|
|
|
|
// 마이그레이션 적용
|
|
|
|
|
const migrated = migrateConfig(config as unknown as Record<string, unknown>);
|
|
|
|
|
const pages = migrated.pages ?? [];
|
|
|
|
|
const hasPages = pages.length > 0;
|
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
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex h-full w-full flex-col overflow-hidden p-1">
|
2026-02-10 14:22:30 +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
|
|
|
<div className="mb-1 flex items-center gap-1">
|
|
|
|
|
<span className="rounded bg-primary/10 px-1 py-0.5 text-[8px] font-medium text-primary">
|
2026-02-10 14:22:30 +09:00
|
|
|
{MODE_LABELS[migrated.displayMode] ?? migrated.displayMode}
|
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
|
|
|
</span>
|
2026-02-10 14:22:30 +09:00
|
|
|
{hasPages && (
|
|
|
|
|
<span className="rounded bg-muted px-1 py-0.5 text-[8px] font-medium text-muted-foreground">
|
|
|
|
|
{pages.length}페이지
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
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
|
|
|
<span className="text-[8px] text-muted-foreground">
|
|
|
|
|
{visibleItems.length}개
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-02-10 14:22:30 +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
|
|
|
<div className="min-h-0 flex-1">
|
2026-02-10 14:22:30 +09:00
|
|
|
{hasPages ? (
|
|
|
|
|
// 첫 번째 페이지 그리드 미리보기
|
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
|
|
|
<div
|
|
|
|
|
className="h-full w-full gap-1"
|
|
|
|
|
style={{
|
|
|
|
|
display: "grid",
|
2026-02-10 14:22:30 +09:00
|
|
|
gridTemplateColumns: `repeat(${pages[0].gridColumns}, 1fr)`,
|
|
|
|
|
gridTemplateRows: `repeat(${pages[0].gridRows}, 1fr)`,
|
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
|
|
|
}}
|
|
|
|
|
>
|
2026-02-10 14:22:30 +09:00
|
|
|
{pages[0].gridCells.length > 0
|
|
|
|
|
? pages[0].gridCells.map((cell) => {
|
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 item = visibleItems.find(
|
|
|
|
|
(i) => i.id === cell.itemId
|
|
|
|
|
);
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
key={cell.id}
|
|
|
|
|
style={{
|
|
|
|
|
gridColumn: cell.gridColumn,
|
|
|
|
|
gridRow: cell.gridRow,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{item ? (
|
|
|
|
|
<DummyItemPreview
|
|
|
|
|
subType={item.subType}
|
|
|
|
|
label={item.label}
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<div className="h-full rounded border border-dashed border-muted-foreground/20" />
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})
|
2026-02-10 14:22:30 +09:00
|
|
|
: visibleItems.slice(0, 4).map((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
|
|
|
<DummyItemPreview
|
|
|
|
|
key={item.id}
|
|
|
|
|
subType={item.subType}
|
|
|
|
|
label={item.label}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
2026-02-10 14:22:30 +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
|
|
|
<div className="relative h-full">
|
|
|
|
|
{visibleItems[0] && (
|
|
|
|
|
<DummyItemPreview
|
|
|
|
|
subType={visibleItems[0].subType}
|
|
|
|
|
label={visibleItems[0].label}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
{visibleItems.length > 1 && (
|
|
|
|
|
<div className="absolute bottom-1 right-1 rounded-full bg-primary/80 px-1.5 py-0.5 text-[8px] font-medium text-primary-foreground">
|
|
|
|
|
+{visibleItems.length - 1}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|