ERP-node/frontend/components/admin/dashboard/DashboardTopMenu.tsx

233 lines
9.0 KiB
TypeScript
Raw Normal View History

2025-10-16 09:55:14 +09:00
"use client";
import React from "react";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
2025-10-16 16:51:24 +09:00
import { Save, Trash2, Palette } from "lucide-react";
2025-10-16 09:55:14 +09:00
import { ElementType, ElementSubtype } from "./types";
import { ResolutionSelector, Resolution } from "./ResolutionSelector";
import { Input } from "@/components/ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
interface DashboardTopMenuProps {
onSaveLayout: () => void;
onClearCanvas: () => void;
dashboardTitle?: string;
onAddElement?: (type: ElementType, subtype: ElementSubtype) => void;
resolution?: Resolution;
onResolutionChange?: (resolution: Resolution) => void;
currentScreenResolution?: Resolution;
backgroundColor?: string;
onBackgroundColorChange?: (color: string) => void;
}
/**
*
* - / ()
2025-10-16 16:51:24 +09:00
* - /
2025-10-16 09:55:14 +09:00
*/
export function DashboardTopMenu({
onSaveLayout,
onClearCanvas,
dashboardTitle,
onAddElement,
resolution = "fhd",
onResolutionChange,
currentScreenResolution,
backgroundColor = "#f9fafb",
onBackgroundColorChange,
}: DashboardTopMenuProps) {
const [chartValue, setChartValue] = React.useState<string>("");
const [widgetValue, setWidgetValue] = React.useState<string>("");
2025-10-16 09:55:14 +09:00
// 차트 선택 시 캔버스 중앙에 추가
const handleChartSelect = (value: string) => {
if (onAddElement) {
onAddElement("chart", value as ElementSubtype);
// 선택 후 즉시 리셋하여 같은 항목을 연속으로 선택 가능하게
setTimeout(() => setChartValue(""), 0);
2025-10-16 09:55:14 +09:00
}
};
// 위젯 선택 시 캔버스 중앙에 추가
const handleWidgetSelect = (value: string) => {
if (onAddElement) {
onAddElement("widget", value as ElementSubtype);
// 선택 후 즉시 리셋하여 같은 항목을 연속으로 선택 가능하게
setTimeout(() => setWidgetValue(""), 0);
2025-10-16 09:55:14 +09:00
}
};
return (
<div className="flex h-16 items-center justify-between border-b bg-white px-6 shadow-sm">
{/* 좌측: 대시보드 제목 */}
<div className="flex items-center gap-4">
{dashboardTitle && (
<div className="flex items-center gap-2">
<span className="text-lg font-semibold text-gray-900">{dashboardTitle}</span>
<span className="rounded bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700"> </span>
</div>
)}
</div>
{/* 중앙: 해상도 선택 & 요소 추가 */}
<div className="flex items-center gap-3">
{/* 해상도 선택 */}
{onResolutionChange && (
<ResolutionSelector
value={resolution}
onChange={onResolutionChange}
currentScreenResolution={currentScreenResolution}
/>
)}
<div className="h-6 w-px bg-gray-300" />
{/* 배경색 선택 */}
{onBackgroundColorChange && (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" size="sm" className="gap-2">
<Palette className="h-4 w-4" />
<div className="h-4 w-4 rounded border border-gray-300" style={{ backgroundColor }} />
</Button>
</PopoverTrigger>
<PopoverContent className="z-[99999] w-64">
<div className="space-y-3">
<div>
<label className="text-sm font-medium"> </label>
</div>
<div className="flex gap-2">
<Input
type="color"
value={backgroundColor}
onChange={(e) => onBackgroundColorChange(e.target.value)}
className="h-10 w-20 cursor-pointer"
/>
<Input
type="text"
value={backgroundColor}
onChange={(e) => onBackgroundColorChange(e.target.value)}
placeholder="#f9fafb"
className="flex-1"
/>
</div>
<div className="grid grid-cols-6 gap-2">
{[
"#ffffff",
"#f9fafb",
"#f3f4f6",
"#e5e7eb",
"#1f2937",
"#111827",
"#fef3c7",
"#fde68a",
"#dbeafe",
"#bfdbfe",
"#fecaca",
"#fca5a5",
].map((color) => (
<button
key={color}
className="h-8 w-8 rounded border-2 transition-transform hover:scale-110"
style={{
backgroundColor: color,
borderColor: backgroundColor === color ? "#3b82f6" : "#d1d5db",
}}
onClick={() => onBackgroundColorChange(color)}
/>
))}
</div>
</div>
</PopoverContent>
</Popover>
)}
<div className="h-6 w-px bg-gray-300" />
{/* 차트 선택 */}
<Select value={chartValue} onValueChange={handleChartSelect}>
2025-10-16 09:55:14 +09:00
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="차트 추가" />
</SelectTrigger>
<SelectContent className="z-[99999]">
<SelectGroup>
2025-10-23 17:23:30 +09:00
<SelectLabel> </SelectLabel>
2025-10-16 09:55:14 +09:00
<SelectItem value="bar"> </SelectItem>
<SelectItem value="horizontal-bar"> </SelectItem>
<SelectItem value="stacked-bar"> </SelectItem>
<SelectItem value="line"> </SelectItem>
<SelectItem value="area"> </SelectItem>
2025-10-23 17:23:30 +09:00
<SelectItem value="combo"> </SelectItem>
</SelectGroup>
<SelectGroup>
<SelectLabel> </SelectLabel>
2025-10-16 09:55:14 +09:00
<SelectItem value="pie"> </SelectItem>
<SelectItem value="donut"> </SelectItem>
</SelectGroup>
</SelectContent>
</Select>
{/* 위젯 선택 */}
<Select value={widgetValue} onValueChange={handleWidgetSelect}>
2025-10-16 09:55:14 +09:00
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="위젯 추가" />
</SelectTrigger>
<SelectContent className="z-[99999]">
<SelectGroup>
<SelectLabel> </SelectLabel>
<SelectItem value="map-summary-v2"></SelectItem>
{/* <SelectItem value="chart">차트</SelectItem> */}
<SelectItem value="list-v2"></SelectItem>
<SelectItem value="custom-metric-v2"> </SelectItem>
<SelectItem value="risk-alert-v2">/</SelectItem>
<SelectItem value="yard-management-3d"> 3D</SelectItem>
{/* <SelectItem value="transport-stats">커스텀 통계 카드</SelectItem> */}
{/* <SelectItem value="status-summary">커스텀 상태 카드</SelectItem> */}
2025-10-16 09:55:14 +09:00
</SelectGroup>
<SelectGroup>
<SelectLabel> </SelectLabel>
<SelectItem value="weather"></SelectItem>
2025-10-23 13:17:21 +09:00
{/* <SelectItem value="weather-map">날씨 지도</SelectItem> */}
2025-10-16 09:55:14 +09:00
<SelectItem value="exchange"></SelectItem>
<SelectItem value="calculator"></SelectItem>
<SelectItem value="calendar"></SelectItem>
<SelectItem value="clock"></SelectItem>
<SelectItem value="todo"> </SelectItem>
2025-10-20 17:42:35 +09:00
{/* <SelectItem value="booking-alert">예약 알림</SelectItem> */}
2025-10-16 09:55:14 +09:00
<SelectItem value="document"></SelectItem>
{/* <SelectItem value="risk-alert">리스크 알림</SelectItem> */}
2025-10-16 09:55:14 +09:00
</SelectGroup>
{/* 범용 위젯으로 대체 가능하여 주석처리 */}
{/* <SelectGroup>
2025-10-16 09:55:14 +09:00
<SelectLabel> </SelectLabel>
<SelectItem value="vehicle-status"> </SelectItem>
<SelectItem value="vehicle-list"> </SelectItem>
<SelectItem value="vehicle-map"> </SelectItem>
</SelectGroup> */}
2025-10-16 09:55:14 +09:00
</SelectContent>
</Select>
</div>
{/* 우측: 액션 버튼 */}
<div className="flex items-center gap-2">
<Button variant="outline" size="sm" onClick={onClearCanvas} className="gap-2 text-red-600 hover:text-red-700">
<Trash2 className="h-4 w-4" />
</Button>
<Button size="sm" onClick={onSaveLayout} className="gap-2">
<Save className="h-4 w-4" />
</Button>
</div>
</div>
);
}