관로 분석 - 분석 도구 메뉴 및 지도 컨트롤 UI 정리
This commit is contained in:
@@ -1,50 +1,101 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ChartColumnBig,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
History,
|
||||
PanelsTopLeft,
|
||||
PencilRuler,
|
||||
Search,
|
||||
Settings2,
|
||||
TriangleAlert,
|
||||
Waves,
|
||||
} from "lucide-react";
|
||||
import type { WindowPopupKey } from "@/features/windowPopup/model/popupDefinitions";
|
||||
|
||||
type Props = {
|
||||
onOpenPopup: (popupKey: WindowPopupKey) => void;
|
||||
onOpenInfoSearch: () => void;
|
||||
};
|
||||
|
||||
const ANALYSIS_POPUP_ITEMS: Array<{ key: WindowPopupKey; label: string }> = [
|
||||
{ key: "pipeAnalysisPopup", label: "관로분석" },
|
||||
{ key: "floodPredictionMapPopup", label: "침수예측지도" },
|
||||
{ key: "floodHistoryPopup", label: "침수발생이력" },
|
||||
{ key: "gisEditPopup", label: "GIS 편집" },
|
||||
{ key: "gisManagementPopup", label: "GIS 관리" },
|
||||
{ key: "flowRiskPopup", label: "통수 위험" },
|
||||
const ANALYSIS_POPUP_ITEMS: Array<{
|
||||
key: WindowPopupKey | "infoSearch";
|
||||
label: string;
|
||||
icon: typeof ChartColumnBig;
|
||||
}> = [
|
||||
{ key: "infoSearch", label: "정보검색", icon: Search },
|
||||
{ key: "pipeAnalysisPopup", label: "관로분석", icon: ChartColumnBig },
|
||||
{ key: "floodPredictionMapPopup", label: "침수예측지도", icon: Waves },
|
||||
{ key: "floodHistoryPopup", label: "침수발생이력", icon: History },
|
||||
{ key: "gisEditPopup", label: "GIS 편집", icon: PencilRuler },
|
||||
{ key: "gisManagementPopup", label: "GIS 관리", icon: Settings2 },
|
||||
{ key: "flowRiskPopup", label: "통수 위험", icon: TriangleAlert },
|
||||
];
|
||||
|
||||
export default function AnalysisPopupMenu({ onOpenPopup }: Props) {
|
||||
export default function AnalysisPopupMenu({ onOpenPopup, onOpenInfoSearch }: Props) {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [activeKey, setActiveKey] = useState<WindowPopupKey | "infoSearch" | null>(null);
|
||||
|
||||
return (
|
||||
<div className="absolute right-[0.35rem] top-[53%] z-[70]">
|
||||
<div className="absolute right-[0.55rem] top-[20px] z-[45]">
|
||||
<div className="relative">
|
||||
{isOpen ? (
|
||||
<div className="absolute right-[21px] top-1/2 flex w-[86px] -translate-y-1/2 flex-col gap-[3px]">
|
||||
{ANALYSIS_POPUP_ITEMS.map((item) => (
|
||||
<button
|
||||
key={item.key}
|
||||
type="button"
|
||||
className="min-h-[40px] rounded-md border border-primary bg-primary px-2 py-1 text-center text-[1rem] font-semibold leading-[1.2] text-white shadow transition hover:brightness-95"
|
||||
onClick={() => onOpenPopup(item.key)}
|
||||
>
|
||||
<span className="break-keep whitespace-normal">{item.label}</span>
|
||||
</button>
|
||||
))}
|
||||
<div className="absolute right-[28px] w-[132px] overflow-hidden rounded-[6px] border border-[#d8dee8] bg-[rgba(255,255,255,0.96)] shadow-[0_8px_18px_rgba(15,23,42,0.14)]">
|
||||
<div className="flex h-[36px] items-center gap-2 border-b border-[#e5eaf1] bg-[#f8fafc] px-[10px] text-[13px] font-bold text-[#1f2937]">
|
||||
<div className="flex items-center gap-2">
|
||||
<PanelsTopLeft className="h-4 w-4 text-[#1e88e5]" />
|
||||
<span>분석도구</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1 p-[6px]">
|
||||
{ANALYSIS_POPUP_ITEMS.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const isActive = activeKey === item.key;
|
||||
|
||||
return (
|
||||
<button
|
||||
key={item.key}
|
||||
type="button"
|
||||
className={`relative flex h-[34px] items-center gap-[7px] rounded-[5px] border px-[8px] pl-[10px] text-left text-[12px] font-semibold transition ${
|
||||
isActive
|
||||
? "border-[#b9dcff] bg-[#eaf4ff] font-bold text-[#0f5fa8] before:absolute before:left-0 before:top-[7px] before:bottom-[7px] before:w-[3px] before:rounded-r-[2px] before:bg-[#1e88e5]"
|
||||
: "border-transparent bg-white text-[#374151] hover:border-[#cfe5ff] hover:bg-[#eef6ff] hover:text-[#1e3a5f]"
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveKey(item.key);
|
||||
|
||||
if (item.key === "infoSearch") {
|
||||
onOpenInfoSearch();
|
||||
return;
|
||||
}
|
||||
|
||||
onOpenPopup(item.key);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
className={`h-[15px] w-[15px] shrink-0 ${
|
||||
isActive ? "text-[#1e88e5]" : "text-[#64748b]"
|
||||
}`}
|
||||
/>
|
||||
<span className="break-keep whitespace-normal">{item.label}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-[36px] w-[18px] items-center justify-center rounded-sm border border-[#2f5c9b] bg-white text-[0.9rem] font-bold text-[#2f5c9b] shadow transition hover:bg-slate-50"
|
||||
className="absolute right-0 top-0 flex h-[36px] w-[20px] items-center justify-center rounded-[4px] border border-[#d8dee8] bg-[rgba(255,255,255,0.96)] text-[#64748b] shadow-[0_8px_18px_rgba(15,23,42,0.14)] transition hover:bg-[#eaf4ff] hover:text-[#1e88e5]"
|
||||
onClick={() => setIsOpen((value) => !value)}
|
||||
title={isOpen ? "분석 메뉴 접기" : "분석 메뉴 펼치기"}
|
||||
aria-label={isOpen ? "분석 메뉴 접기" : "분석 메뉴 펼치기"}
|
||||
>
|
||||
{isOpen ? ">" : "<"}
|
||||
{isOpen ? <ChevronRight className="h-4 w-4" /> : <ChevronLeft className="h-4 w-4" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,6 +70,10 @@ function Gis({
|
||||
viewExtent,
|
||||
viewMinZoom,
|
||||
showZoomLevel = false,
|
||||
zoomGuide,
|
||||
showFloatingSearchButton = true,
|
||||
treeTogglePosition = "center",
|
||||
showZoomScaleInfo = false,
|
||||
}) {
|
||||
const mapRef = useRef();
|
||||
const [mapObject, setMapObject] = useState({});
|
||||
@@ -311,6 +315,7 @@ function Gis({
|
||||
onProgressChange={handleProgressChange}
|
||||
layerSettingView={LayerSettingView}
|
||||
inlineLayerSettingView={inlineLayerSettingView}
|
||||
toggleButtonPosition={treeTogglePosition}
|
||||
/>
|
||||
|
||||
{typeof WaterDepth === "function" && (
|
||||
@@ -345,13 +350,15 @@ function Gis({
|
||||
</div>
|
||||
)}
|
||||
<GisToolBar />
|
||||
{showZoomLevel && <GisZoomLevel />}
|
||||
{showZoomLevel && (
|
||||
<GisZoomLevel zoomGuide={zoomGuide} showZoomScaleInfo={showZoomScaleInfo} />
|
||||
)}
|
||||
<GisMapToggle />
|
||||
<GisSelect onFeatureSelect={handleFeatureSelect} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isSearch && (
|
||||
{isSearch && showFloatingSearchButton && (
|
||||
<div className="absolute right-8 top-[248px] z-20">
|
||||
<button
|
||||
onClick={() => setIsSearchModalOpen(true)}
|
||||
|
||||
@@ -46,6 +46,7 @@ export default React.memo(function GisTree({
|
||||
layerSettingView: LayerSettingView = null,
|
||||
layerIconVisible,
|
||||
inlineLayerSettingView,
|
||||
toggleButtonPosition = "center",
|
||||
}) {
|
||||
const { gisCore, treeData } = useGisContext();
|
||||
|
||||
@@ -510,6 +511,9 @@ export default React.memo(function GisTree({
|
||||
|
||||
if (!treeData || treeData.length === 0) return null;
|
||||
|
||||
const toggleButtonPositionClass =
|
||||
toggleButtonPosition === "top" ? "top-[5.5rem]" : "top-1/2 -translate-y-1/2";
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 사이드 패널 */}
|
||||
@@ -629,7 +633,7 @@ export default React.memo(function GisTree({
|
||||
)}
|
||||
<button
|
||||
onClick={() => setVisible(false)}
|
||||
className="absolute right-[-3px] top-1/2 z-50 -translate-y-1/2 transform rounded-l-none rounded-r border border-l border-gray-300 bg-white px-1 py-2 shadow-sm"
|
||||
className={`absolute right-[-3px] z-50 transform rounded-l-none rounded-r border border-l border-gray-300 bg-white px-1 py-2 shadow-sm ${toggleButtonPositionClass}`}
|
||||
>
|
||||
<ChevronLeft size={16} />
|
||||
</button>
|
||||
@@ -637,7 +641,7 @@ export default React.memo(function GisTree({
|
||||
{!visible && (
|
||||
<button
|
||||
onClick={() => setVisible(true)}
|
||||
className="absolute left-[-3px] top-1/2 z-50 -translate-y-1/2 transform rounded-r border border-r border-gray-300 bg-white px-1 py-2 shadow-sm"
|
||||
className={`absolute left-[-3px] z-50 transform rounded-r border border-r border-gray-300 bg-white px-1 py-2 shadow-sm ${toggleButtonPositionClass}`}
|
||||
>
|
||||
<ChevronRight size={16} />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user