알아서 배치되는거 하기 전 세이브 디벨롭만 된 상태

This commit is contained in:
leeheejin
2025-10-16 16:34:59 +09:00
parent 6d51aced2c
commit 7097775343
4 changed files with 29 additions and 97 deletions

View File

@@ -25,6 +25,10 @@ export default function DashboardViewPage({ params }: DashboardViewPageProps) {
title: string;
description?: string;
elements: DashboardElement[];
settings?: {
backgroundColor?: string;
resolution?: string;
};
createdAt: string;
updatedAt: string;
} | null>(null);
@@ -156,7 +160,11 @@ export default function DashboardViewPage({ params }: DashboardViewPageProps) {
{/* 대시보드 뷰어 */}
<div className="h-[calc(100vh-120px)]">
<DashboardViewer elements={dashboard.elements} dashboardId={dashboard.id} />
<DashboardViewer
elements={dashboard.elements}
dashboardId={dashboard.id}
backgroundColor={dashboard.settings?.backgroundColor}
/>
</div>
</div>
);

View File

@@ -115,6 +115,7 @@ interface DashboardViewerProps {
elements: DashboardElement[];
dashboardId: string;
refreshInterval?: number; // 전체 대시보드 새로고침 간격 (ms)
backgroundColor?: string; // 배경색
}
/**
@@ -123,7 +124,7 @@ interface DashboardViewerProps {
* - 실시간 데이터 업데이트
* - 반응형 레이아웃
*/
export function DashboardViewer({ elements, dashboardId, refreshInterval }: DashboardViewerProps) {
export function DashboardViewer({ elements, dashboardId, refreshInterval, backgroundColor = "#f9fafb" }: DashboardViewerProps) {
const [elementData, setElementData] = useState<Record<string, QueryResult>>({});
const [loadingElements, setLoadingElements] = useState<Set<string>>(new Set());
const [lastRefresh, setLastRefresh] = useState<Date>(new Date());
@@ -230,7 +231,7 @@ export function DashboardViewer({ elements, dashboardId, refreshInterval }: Dash
}
return (
<div className="relative h-full w-full overflow-auto bg-gray-100">
<div className="relative h-full w-full overflow-auto" style={{ backgroundColor }}>
{/* 새로고침 상태 표시 */}
<div className="text-muted-foreground absolute top-4 right-4 z-10 rounded-lg bg-white px-3 py-2 text-xs shadow-sm">
: {lastRefresh.toLocaleTimeString()}

View File

@@ -135,7 +135,7 @@ export default function ExchangeWidget({
const hasError = error || !exchangeRate;
return (
<div className="h-full bg-gradient-to-br from-green-50 to-emerald-50 rounded-lg border p-4">
<div className="h-full bg-gradient-to-br from-green-50 to-emerald-50 rounded-lg border p-4 @container">
{/* 헤더 */}
<div className="flex items-center justify-between mb-3">
<div className="flex-1">
@@ -160,10 +160,10 @@ export default function ExchangeWidget({
</Button>
</div>
{/* 통화 선택 */}
<div className="flex items-center gap-2 mb-3">
{/* 통화 선택 - 반응형 (좁을 때 세로 배치) */}
<div className="flex @[300px]:flex-row flex-col items-center gap-2 mb-3">
<Select value={base} onValueChange={setBase}>
<SelectTrigger className="flex-1 bg-white h-8 text-xs">
<SelectTrigger className="w-full @[300px]:flex-1 bg-white h-8 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
@@ -179,13 +179,13 @@ export default function ExchangeWidget({
variant="ghost"
size="sm"
onClick={handleSwap}
className="h-8 w-8 p-0 rounded-full hover:bg-white"
className="h-8 w-8 p-0 rounded-full hover:bg-white @[300px]:rotate-0 rotate-90"
>
<ArrowRightLeft className="h-3 w-3" />
</Button>
<Select value={target} onValueChange={setTarget}>
<SelectTrigger className="flex-1 bg-white h-8 text-xs">
<SelectTrigger className="w-full @[300px]:flex-1 bg-white h-8 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>