[agent-pipeline] pipe-20260311052455-y968 round-5
This commit is contained in:
parent
f071777131
commit
9125d04345
|
|
@ -1,70 +1,80 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { ComponentData } from "@/types/screen";
|
||||
import { ConfigPanelBuilder } from "@/lib/registry/components/common/ConfigPanelBuilder";
|
||||
import { ConfigSectionDefinition } from "@/lib/registry/components/common/ConfigPanelTypes";
|
||||
|
||||
interface AlertConfigPanelProps {
|
||||
component: ComponentData;
|
||||
onUpdateProperty: (path: string, value: any) => void;
|
||||
config?: Record<string, any>;
|
||||
onChange?: (key: string, value: any) => void;
|
||||
component?: any;
|
||||
onUpdateProperty?: (path: string, value: any) => void;
|
||||
}
|
||||
|
||||
export const AlertConfigPanel: React.FC<AlertConfigPanelProps> = ({ component, onUpdateProperty }) => {
|
||||
const config = component.componentConfig || {};
|
||||
const sections: ConfigSectionDefinition[] = [
|
||||
{
|
||||
id: "content",
|
||||
title: "콘텐츠",
|
||||
fields: [
|
||||
{
|
||||
key: "title",
|
||||
label: "제목",
|
||||
type: "text",
|
||||
placeholder: "알림 제목을 입력하세요",
|
||||
},
|
||||
{
|
||||
key: "message",
|
||||
label: "메시지",
|
||||
type: "textarea",
|
||||
placeholder: "알림 메시지를 입력하세요",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "style",
|
||||
title: "스타일",
|
||||
fields: [
|
||||
{
|
||||
key: "type",
|
||||
label: "알림 타입",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "정보 (Info)", value: "info" },
|
||||
{ label: "경고 (Warning)", value: "warning" },
|
||||
{ label: "성공 (Success)", value: "success" },
|
||||
{ label: "오류 (Error)", value: "error" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "showIcon",
|
||||
label: "아이콘 표시",
|
||||
type: "switch",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const AlertConfigPanel: React.FC<AlertConfigPanelProps> = ({
|
||||
config: directConfig,
|
||||
onChange: directOnChange,
|
||||
component,
|
||||
onUpdateProperty,
|
||||
}) => {
|
||||
const config = directConfig || component?.componentConfig || {};
|
||||
|
||||
const handleChange = (key: string, value: any) => {
|
||||
if (directOnChange) {
|
||||
directOnChange(key, value);
|
||||
} else if (onUpdateProperty) {
|
||||
onUpdateProperty(`componentConfig.${key}`, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label htmlFor="alert-title">제목</Label>
|
||||
<Input
|
||||
id="alert-title"
|
||||
value={config.title || "알림 제목"}
|
||||
onChange={(e) => onUpdateProperty("componentConfig.title", e.target.value)}
|
||||
placeholder="알림 제목을 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="alert-message">메시지</Label>
|
||||
<Textarea
|
||||
id="alert-message"
|
||||
value={config.message || "알림 메시지입니다."}
|
||||
onChange={(e) => onUpdateProperty("componentConfig.message", e.target.value)}
|
||||
placeholder="알림 메시지를 입력하세요"
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="alert-type">알림 타입</Label>
|
||||
<Select
|
||||
value={config.type || "info"}
|
||||
onValueChange={(value) => onUpdateProperty("componentConfig.type", value)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="알림 타입 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="info">정보 (Info)</SelectItem>
|
||||
<SelectItem value="warning">경고 (Warning)</SelectItem>
|
||||
<SelectItem value="success">성공 (Success)</SelectItem>
|
||||
<SelectItem value="error">오류 (Error)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="show-icon"
|
||||
checked={config.showIcon ?? true}
|
||||
onCheckedChange={(checked) => onUpdateProperty("componentConfig.showIcon", checked)}
|
||||
/>
|
||||
<Label htmlFor="show-icon">아이콘 표시</Label>
|
||||
</div>
|
||||
</div>
|
||||
<ConfigPanelBuilder
|
||||
config={config}
|
||||
onChange={handleChange}
|
||||
sections={sections}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,65 +1,79 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { ComponentData } from "@/types/screen";
|
||||
import { ConfigPanelBuilder } from "@/lib/registry/components/common/ConfigPanelBuilder";
|
||||
import { ConfigSectionDefinition } from "@/lib/registry/components/common/ConfigPanelTypes";
|
||||
|
||||
interface BadgeConfigPanelProps {
|
||||
component: ComponentData;
|
||||
onUpdateProperty: (path: string, value: any) => void;
|
||||
config?: Record<string, any>;
|
||||
onChange?: (key: string, value: any) => void;
|
||||
component?: any;
|
||||
onUpdateProperty?: (path: string, value: any) => void;
|
||||
}
|
||||
|
||||
export const BadgeConfigPanel: React.FC<BadgeConfigPanelProps> = ({ component, onUpdateProperty }) => {
|
||||
const config = component.componentConfig || {};
|
||||
const sections: ConfigSectionDefinition[] = [
|
||||
{
|
||||
id: "content",
|
||||
title: "콘텐츠",
|
||||
fields: [
|
||||
{
|
||||
key: "text",
|
||||
label: "뱃지 텍스트",
|
||||
type: "text",
|
||||
placeholder: "뱃지 텍스트를 입력하세요",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "style",
|
||||
title: "스타일",
|
||||
fields: [
|
||||
{
|
||||
key: "variant",
|
||||
label: "뱃지 스타일",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "기본 (Default)", value: "default" },
|
||||
{ label: "보조 (Secondary)", value: "secondary" },
|
||||
{ label: "위험 (Destructive)", value: "destructive" },
|
||||
{ label: "외곽선 (Outline)", value: "outline" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "size",
|
||||
label: "뱃지 크기",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "작음 (Small)", value: "small" },
|
||||
{ label: "기본 (Default)", value: "default" },
|
||||
{ label: "큼 (Large)", value: "large" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const BadgeConfigPanel: React.FC<BadgeConfigPanelProps> = ({
|
||||
config: directConfig,
|
||||
onChange: directOnChange,
|
||||
component,
|
||||
onUpdateProperty,
|
||||
}) => {
|
||||
const config = directConfig || component?.componentConfig || {};
|
||||
|
||||
const handleChange = (key: string, value: any) => {
|
||||
if (directOnChange) {
|
||||
directOnChange(key, value);
|
||||
} else if (onUpdateProperty) {
|
||||
onUpdateProperty(`componentConfig.${key}`, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label htmlFor="badge-text">뱃지 텍스트</Label>
|
||||
<Input
|
||||
id="badge-text"
|
||||
value={config.text || "상태"}
|
||||
onChange={(e) => onUpdateProperty("componentConfig.text", e.target.value)}
|
||||
placeholder="뱃지 텍스트를 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="badge-variant">뱃지 스타일</Label>
|
||||
<Select
|
||||
value={config.variant || "default"}
|
||||
onValueChange={(value) => onUpdateProperty("componentConfig.variant", value)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="뱃지 스타일 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="default">기본 (Default)</SelectItem>
|
||||
<SelectItem value="secondary">보조 (Secondary)</SelectItem>
|
||||
<SelectItem value="destructive">위험 (Destructive)</SelectItem>
|
||||
<SelectItem value="outline">외곽선 (Outline)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="badge-size">뱃지 크기</Label>
|
||||
<Select
|
||||
value={config.size || "default"}
|
||||
onValueChange={(value) => onUpdateProperty("componentConfig.size", value)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="뱃지 크기 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="small">작음 (Small)</SelectItem>
|
||||
<SelectItem value="default">기본 (Default)</SelectItem>
|
||||
<SelectItem value="large">큼 (Large)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<ConfigPanelBuilder
|
||||
config={config}
|
||||
onChange={handleChange}
|
||||
sections={sections}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,119 +1,108 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { ComponentData } from "@/types/screen";
|
||||
import { ColorPickerWithTransparent } from "../common/ColorPickerWithTransparent";
|
||||
import { ConfigPanelBuilder } from "@/lib/registry/components/common/ConfigPanelBuilder";
|
||||
import { ConfigSectionDefinition } from "@/lib/registry/components/common/ConfigPanelTypes";
|
||||
|
||||
interface CardConfigPanelProps {
|
||||
component: ComponentData;
|
||||
onUpdateProperty: (path: string, value: any) => void;
|
||||
config?: Record<string, any>;
|
||||
onChange?: (key: string, value: any) => void;
|
||||
component?: any;
|
||||
onUpdateProperty?: (path: string, value: any) => void;
|
||||
}
|
||||
|
||||
export const CardConfigPanel: React.FC<CardConfigPanelProps> = ({ component, onUpdateProperty }) => {
|
||||
const config = component.componentConfig || {};
|
||||
const sections: ConfigSectionDefinition[] = [
|
||||
{
|
||||
id: "content",
|
||||
title: "콘텐츠",
|
||||
fields: [
|
||||
{
|
||||
key: "title",
|
||||
label: "카드 제목",
|
||||
type: "text",
|
||||
placeholder: "카드 제목을 입력하세요",
|
||||
},
|
||||
{
|
||||
key: "content",
|
||||
label: "카드 내용",
|
||||
type: "textarea",
|
||||
placeholder: "카드 내용을 입력하세요",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "style",
|
||||
title: "스타일",
|
||||
fields: [
|
||||
{
|
||||
key: "variant",
|
||||
label: "카드 스타일",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "기본 (Default)", value: "default" },
|
||||
{ label: "테두리 (Outlined)", value: "outlined" },
|
||||
{ label: "그림자 (Elevated)", value: "elevated" },
|
||||
{ label: "채움 (Filled)", value: "filled" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "padding",
|
||||
label: "패딩",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "없음 (None)", value: "none" },
|
||||
{ label: "작게 (Small)", value: "small" },
|
||||
{ label: "기본 (Default)", value: "default" },
|
||||
{ label: "크게 (Large)", value: "large" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "backgroundColor",
|
||||
label: "배경색",
|
||||
type: "color",
|
||||
},
|
||||
{
|
||||
key: "borderRadius",
|
||||
label: "테두리 반경",
|
||||
type: "text",
|
||||
placeholder: "8px",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "display",
|
||||
title: "표시 옵션",
|
||||
fields: [
|
||||
{
|
||||
key: "showHeader",
|
||||
label: "헤더 표시",
|
||||
type: "switch",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const handleConfigChange = (key: string, value: any) => {
|
||||
onUpdateProperty(`componentConfig.${key}`, value);
|
||||
export const CardConfigPanel: React.FC<CardConfigPanelProps> = ({
|
||||
config: directConfig,
|
||||
onChange: directOnChange,
|
||||
component,
|
||||
onUpdateProperty,
|
||||
}) => {
|
||||
const config = directConfig || component?.componentConfig || {};
|
||||
|
||||
const handleChange = (key: string, value: any) => {
|
||||
if (directOnChange) {
|
||||
directOnChange(key, value);
|
||||
} else if (onUpdateProperty) {
|
||||
onUpdateProperty(`componentConfig.${key}`, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">카드 설정</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* 카드 제목 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="card-title">카드 제목</Label>
|
||||
<Input
|
||||
id="card-title"
|
||||
placeholder="카드 제목을 입력하세요"
|
||||
value={config.title || "카드 제목"}
|
||||
onChange={(e) => handleConfigChange("title", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 카드 내용 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="card-content">카드 내용</Label>
|
||||
<Textarea
|
||||
id="card-content"
|
||||
placeholder="카드 내용을 입력하세요"
|
||||
value={config.content || "카드 내용 영역"}
|
||||
onChange={(e) => handleConfigChange("content", e.target.value)}
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 카드 스타일 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="card-variant">카드 스타일</Label>
|
||||
<Select value={config.variant || "default"} onValueChange={(value) => handleConfigChange("variant", value)}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="카드 스타일 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="default">기본 (Default)</SelectItem>
|
||||
<SelectItem value="outlined">테두리 (Outlined)</SelectItem>
|
||||
<SelectItem value="elevated">그림자 (Elevated)</SelectItem>
|
||||
<SelectItem value="filled">채움 (Filled)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 헤더 표시 여부 */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="show-header"
|
||||
checked={config.showHeader !== false}
|
||||
onCheckedChange={(checked) => handleConfigChange("showHeader", checked)}
|
||||
/>
|
||||
<Label htmlFor="show-header">헤더 표시</Label>
|
||||
</div>
|
||||
|
||||
{/* 패딩 설정 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="card-padding">패딩</Label>
|
||||
<Select value={config.padding || "default"} onValueChange={(value) => handleConfigChange("padding", value)}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="패딩 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음 (None)</SelectItem>
|
||||
<SelectItem value="small">작게 (Small)</SelectItem>
|
||||
<SelectItem value="default">기본 (Default)</SelectItem>
|
||||
<SelectItem value="large">크게 (Large)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 배경색 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="background-color">배경색</Label>
|
||||
<ColorPickerWithTransparent
|
||||
id="background-color"
|
||||
value={config.backgroundColor}
|
||||
onChange={(value) => handleConfigChange("backgroundColor", value)}
|
||||
defaultColor="#ffffff"
|
||||
placeholder="#ffffff"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 테두리 반경 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="border-radius">테두리 반경</Label>
|
||||
<Input
|
||||
id="border-radius"
|
||||
placeholder="8px"
|
||||
value={config.borderRadius || "8px"}
|
||||
onChange={(e) => handleConfigChange("borderRadius", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<ConfigPanelBuilder
|
||||
config={config}
|
||||
onChange={handleChange}
|
||||
sections={sections}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,150 +1,131 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { ComponentData } from "@/types/screen";
|
||||
import { ColorPickerWithTransparent } from "../common/ColorPickerWithTransparent";
|
||||
import { ConfigPanelBuilder } from "@/lib/registry/components/common/ConfigPanelBuilder";
|
||||
import { ConfigSectionDefinition } from "@/lib/registry/components/common/ConfigPanelTypes";
|
||||
|
||||
interface DashboardConfigPanelProps {
|
||||
component: ComponentData;
|
||||
onUpdateProperty: (path: string, value: any) => void;
|
||||
config?: Record<string, any>;
|
||||
onChange?: (key: string, value: any) => void;
|
||||
component?: any;
|
||||
onUpdateProperty?: (path: string, value: any) => void;
|
||||
}
|
||||
|
||||
export const DashboardConfigPanel: React.FC<DashboardConfigPanelProps> = ({ component, onUpdateProperty }) => {
|
||||
const config = component.componentConfig || {};
|
||||
const sections: ConfigSectionDefinition[] = [
|
||||
{
|
||||
id: "content",
|
||||
title: "콘텐츠",
|
||||
fields: [
|
||||
{
|
||||
key: "title",
|
||||
label: "그리드 제목",
|
||||
type: "text",
|
||||
placeholder: "그리드 제목을 입력하세요",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "grid",
|
||||
title: "그리드 설정",
|
||||
fields: [
|
||||
{
|
||||
key: "rows",
|
||||
label: "행 개수",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "1행", value: "1" },
|
||||
{ label: "2행", value: "2" },
|
||||
{ label: "3행", value: "3" },
|
||||
{ label: "4행", value: "4" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "columns",
|
||||
label: "열 개수",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "1열", value: "1" },
|
||||
{ label: "2열", value: "2" },
|
||||
{ label: "3열", value: "3" },
|
||||
{ label: "4열", value: "4" },
|
||||
{ label: "6열", value: "6" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "gap",
|
||||
label: "그리드 간격",
|
||||
type: "select",
|
||||
options: [
|
||||
{ label: "없음 (0px)", value: "none" },
|
||||
{ label: "작게 (8px)", value: "small" },
|
||||
{ label: "보통 (16px)", value: "medium" },
|
||||
{ label: "크게 (24px)", value: "large" },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "itemHeight",
|
||||
label: "아이템 높이",
|
||||
type: "text",
|
||||
placeholder: "120px",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "style",
|
||||
title: "스타일",
|
||||
fields: [
|
||||
{
|
||||
key: "backgroundColor",
|
||||
label: "배경색",
|
||||
type: "color",
|
||||
},
|
||||
{
|
||||
key: "borderRadius",
|
||||
label: "테두리 반경",
|
||||
type: "text",
|
||||
placeholder: "8px",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "display",
|
||||
title: "표시 옵션",
|
||||
fields: [
|
||||
{
|
||||
key: "responsive",
|
||||
label: "반응형 레이아웃",
|
||||
type: "switch",
|
||||
},
|
||||
{
|
||||
key: "showBorders",
|
||||
label: "그리드 테두리 표시",
|
||||
type: "switch",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const handleConfigChange = (key: string, value: any) => {
|
||||
onUpdateProperty(`componentConfig.${key}`, value);
|
||||
export const DashboardConfigPanel: React.FC<DashboardConfigPanelProps> = ({
|
||||
config: directConfig,
|
||||
onChange: directOnChange,
|
||||
component,
|
||||
onUpdateProperty,
|
||||
}) => {
|
||||
const config = directConfig || component?.componentConfig || {};
|
||||
|
||||
const handleChange = (key: string, value: any) => {
|
||||
if (directOnChange) {
|
||||
directOnChange(key, value);
|
||||
} else if (onUpdateProperty) {
|
||||
onUpdateProperty(`componentConfig.${key}`, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-sm font-medium">대시보드 그리드 설정</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* 그리드 제목 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="grid-title">그리드 제목</Label>
|
||||
<Input
|
||||
id="grid-title"
|
||||
placeholder="그리드 제목을 입력하세요"
|
||||
value={config.title || "대시보드 그리드"}
|
||||
onChange={(e) => handleConfigChange("title", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 행 개수 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="grid-rows">행 개수</Label>
|
||||
<Select
|
||||
value={String(config.rows || 2)}
|
||||
onValueChange={(value) => handleConfigChange("rows", parseInt(value))}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="행 개수 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">1행</SelectItem>
|
||||
<SelectItem value="2">2행</SelectItem>
|
||||
<SelectItem value="3">3행</SelectItem>
|
||||
<SelectItem value="4">4행</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 열 개수 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="grid-columns">열 개수</Label>
|
||||
<Select
|
||||
value={String(config.columns || 3)}
|
||||
onValueChange={(value) => handleConfigChange("columns", parseInt(value))}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="열 개수 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">1열</SelectItem>
|
||||
<SelectItem value="2">2열</SelectItem>
|
||||
<SelectItem value="3">3열</SelectItem>
|
||||
<SelectItem value="4">4열</SelectItem>
|
||||
<SelectItem value="6">6열</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 간격 설정 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="grid-gap">그리드 간격</Label>
|
||||
<Select value={config.gap || "medium"} onValueChange={(value) => handleConfigChange("gap", value)}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="간격 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음 (0px)</SelectItem>
|
||||
<SelectItem value="small">작게 (8px)</SelectItem>
|
||||
<SelectItem value="medium">보통 (16px)</SelectItem>
|
||||
<SelectItem value="large">크게 (24px)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 그리드 아이템 높이 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="item-height">아이템 높이</Label>
|
||||
<Input
|
||||
id="item-height"
|
||||
placeholder="120px"
|
||||
value={config.itemHeight || "120px"}
|
||||
onChange={(e) => handleConfigChange("itemHeight", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 반응형 설정 */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="responsive"
|
||||
checked={config.responsive !== false}
|
||||
onCheckedChange={(checked) => handleConfigChange("responsive", checked)}
|
||||
/>
|
||||
<Label htmlFor="responsive">반응형 레이아웃</Label>
|
||||
</div>
|
||||
|
||||
{/* 테두리 표시 */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="show-borders"
|
||||
checked={config.showBorders !== false}
|
||||
onCheckedChange={(checked) => handleConfigChange("showBorders", checked)}
|
||||
/>
|
||||
<Label htmlFor="show-borders">그리드 테두리 표시</Label>
|
||||
</div>
|
||||
|
||||
{/* 배경색 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="background-color">배경색</Label>
|
||||
<ColorPickerWithTransparent
|
||||
id="background-color"
|
||||
value={config.backgroundColor}
|
||||
onChange={(value) => handleConfigChange("backgroundColor", value)}
|
||||
defaultColor="#f8f9fa"
|
||||
placeholder="#f8f9fa"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 테두리 반경 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="border-radius">테두리 반경</Label>
|
||||
<Input
|
||||
id="border-radius"
|
||||
placeholder="8px"
|
||||
value={config.borderRadius || "8px"}
|
||||
onChange={(e) => handleConfigChange("borderRadius", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<ConfigPanelBuilder
|
||||
config={config}
|
||||
onChange={handleChange}
|
||||
sections={sections}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,84 +1,93 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { ComponentData } from "@/types/screen";
|
||||
import { ColorPickerWithTransparent } from "../common/ColorPickerWithTransparent";
|
||||
import { ConfigPanelBuilder } from "@/lib/registry/components/common/ConfigPanelBuilder";
|
||||
import { ConfigSectionDefinition } from "@/lib/registry/components/common/ConfigPanelTypes";
|
||||
|
||||
interface ProgressBarConfigPanelProps {
|
||||
component: ComponentData;
|
||||
onUpdateProperty: (path: string, value: any) => void;
|
||||
config?: Record<string, any>;
|
||||
onChange?: (key: string, value: any) => void;
|
||||
component?: any;
|
||||
onUpdateProperty?: (path: string, value: any) => void;
|
||||
}
|
||||
|
||||
export const ProgressBarConfigPanel: React.FC<ProgressBarConfigPanelProps> = ({ component, onUpdateProperty }) => {
|
||||
const config = component.componentConfig || {};
|
||||
const sections: ConfigSectionDefinition[] = [
|
||||
{
|
||||
id: "content",
|
||||
title: "콘텐츠",
|
||||
fields: [
|
||||
{
|
||||
key: "label",
|
||||
label: "라벨",
|
||||
type: "text",
|
||||
placeholder: "진행률 라벨을 입력하세요",
|
||||
},
|
||||
{
|
||||
key: "value",
|
||||
label: "현재 값",
|
||||
type: "number",
|
||||
min: 0,
|
||||
placeholder: "현재 값",
|
||||
},
|
||||
{
|
||||
key: "max",
|
||||
label: "최대 값",
|
||||
type: "number",
|
||||
min: 1,
|
||||
placeholder: "최대 값",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "style",
|
||||
title: "스타일",
|
||||
fields: [
|
||||
{
|
||||
key: "color",
|
||||
label: "진행률 색상",
|
||||
type: "color",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "display",
|
||||
title: "표시 옵션",
|
||||
fields: [
|
||||
{
|
||||
key: "showPercentage",
|
||||
label: "퍼센트 표시",
|
||||
type: "switch",
|
||||
},
|
||||
{
|
||||
key: "showValue",
|
||||
label: "값 표시",
|
||||
type: "switch",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const ProgressBarConfigPanel: React.FC<ProgressBarConfigPanelProps> = ({
|
||||
config: directConfig,
|
||||
onChange: directOnChange,
|
||||
component,
|
||||
onUpdateProperty,
|
||||
}) => {
|
||||
const config = directConfig || component?.componentConfig || {};
|
||||
|
||||
const handleChange = (key: string, value: any) => {
|
||||
if (directOnChange) {
|
||||
directOnChange(key, value);
|
||||
} else if (onUpdateProperty) {
|
||||
onUpdateProperty(`componentConfig.${key}`, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label htmlFor="progress-label">라벨</Label>
|
||||
<Input
|
||||
id="progress-label"
|
||||
value={config.label || "진행률"}
|
||||
onChange={(e) => onUpdateProperty("componentConfig.label", e.target.value)}
|
||||
placeholder="진행률 라벨을 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="progress-value">현재 값</Label>
|
||||
<Input
|
||||
id="progress-value"
|
||||
type="number"
|
||||
value={config.value || 65}
|
||||
onChange={(e) => onUpdateProperty("componentConfig.value", parseInt(e.target.value) || 0)}
|
||||
placeholder="현재 값"
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="progress-max">최대 값</Label>
|
||||
<Input
|
||||
id="progress-max"
|
||||
type="number"
|
||||
value={config.max || 100}
|
||||
onChange={(e) => onUpdateProperty("componentConfig.max", parseInt(e.target.value) || 100)}
|
||||
placeholder="최대 값"
|
||||
min="1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="progress-color">진행률 색상</Label>
|
||||
<ColorPickerWithTransparent
|
||||
id="progress-color"
|
||||
value={config.color}
|
||||
onChange={(value) => onUpdateProperty("componentConfig.color", value)}
|
||||
defaultColor="#3b82f6"
|
||||
placeholder="#3b82f6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="show-percentage"
|
||||
checked={config.showPercentage ?? true}
|
||||
onCheckedChange={(checked) => onUpdateProperty("componentConfig.showPercentage", checked)}
|
||||
/>
|
||||
<Label htmlFor="show-percentage">퍼센트 표시</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="show-value"
|
||||
checked={config.showValue ?? true}
|
||||
onCheckedChange={(checked) => onUpdateProperty("componentConfig.showValue", checked)}
|
||||
/>
|
||||
<Label htmlFor="show-value">값 표시</Label>
|
||||
</div>
|
||||
</div>
|
||||
<ConfigPanelBuilder
|
||||
config={config}
|
||||
onChange={handleChange}
|
||||
sections={sections}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue