feat: 레이아웃 UI 및 사이드바 개선

- Header, Sidebar, SideNav, ToolBar 컴포넌트 업데이트
- 사이드바 스타일 개선

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
HeungTak Lee 2026-02-05 06:36:27 +09:00
부모 c068f55077
커밋 61dc5a0e4d
5개의 변경된 파일57개의 추가작업 그리고 22개의 파일을 삭제

파일 보기

@ -21,15 +21,15 @@ export default function Header() {
<span className="blind">알람</span> <span className="blind">알람</span>
</Link> </Link>
</li> </li>
<li className="setWrap"> {/*<li className="setWrap">*/}
<Link to="/signal" className="set" title="설정"> {/* <Link to="/signal" className="set" title="설정">*/}
<span className="blind">설정</span> {/* <span className="blind">설정</span>*/}
</Link> {/* </Link>*/}
<div className="setMenu"> {/* <div className="setMenu">*/}
<Link to="/signal">신호설정</Link> {/* <Link to="/signal">신호설정</Link>*/}
<Link to="/signal/custom">맞춤설정</Link> {/* <Link to="/signal/custom">맞춤설정</Link>*/}
</div> {/* </div>*/}
</li> {/*</li>*/}
<li> <li>
<Link to="/mypage" className="user" title="마이페이지"> <Link to="/mypage" className="user" title="마이페이지">
<span className="blind">마이페이지</span> <span className="blind">마이페이지</span>

파일 보기

@ -9,9 +9,9 @@ const gnbList = [
{ key: 'gnb3', className: 'gnb3', label: '기상', path: 'weather' }, { key: 'gnb3', className: 'gnb3', label: '기상', path: 'weather' },
{ key: 'gnb4', className: 'gnb4', label: '분석', path: 'analysis' }, { key: 'gnb4', className: 'gnb4', label: '분석', path: 'analysis' },
{ key: 'gnb5', className: 'gnb5', label: '타임라인', path: 'timeline' }, { key: 'gnb5', className: 'gnb5', label: '타임라인', path: 'timeline' },
{ key: 'gnb6', className: 'gnb6', label: 'AI모드', path: 'ai' }, // { key: 'gnb6', className: 'gnb6', label: 'AI', path: 'ai' },
{ key: 'gnb7', className: 'gnb7', label: '리플레이', path: 'replay' }, { key: 'gnb7', className: 'gnb7', label: '리플레이', path: 'replay' },
{ key: 'gnb8', className: 'gnb8', label: '항적조회', path: 'tracking' }, // { key: 'gnb8', className: 'gnb8', label: '', path: 'tracking' },
]; ];
const sideList = [ const sideList = [

파일 보기

@ -9,10 +9,11 @@ import Panel3Component from '../../publish/pages/Panel3Component';
import Panel4Component from '../../publish/pages/Panel4Component'; import Panel4Component from '../../publish/pages/Panel4Component';
import Panel5Component from '../../publish/pages/Panel5Component'; import Panel5Component from '../../publish/pages/Panel5Component';
import Panel6Component from '../../publish/pages/Panel6Component'; import Panel6Component from '../../publish/pages/Panel6Component';
import Panel7Component from '../../publish/pages/Panel7Component';
import Panel8Component from '../../publish/pages/Panel8Component'; import Panel8Component from '../../publish/pages/Panel8Component';
// DisplayComponent // DisplayComponent
import DisplayComponent from '../../component/wrap/side/DisplayComponent'; import DisplayComponent from '../../component/wrap/side/DisplayComponent';
//
import ReplayPage from '../../pages/ReplayPage';
/** /**
* 사이드바 컴포넌트 * 사이드바 컴포넌트
@ -22,12 +23,18 @@ import DisplayComponent from '../../component/wrap/side/DisplayComponent';
export default function Sidebar() { export default function Sidebar() {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const [isPanelOpen, setIsPanelOpen] = useState(true); //
const initialActiveKey = (() => {
const path = location.pathname.split('/')[1];
return path ? pathToKey[path] : null;
})();
const [isPanelOpen, setIsPanelOpen] = useState(initialActiveKey !== null);
// URL // URL ( )
const getActiveKey = () => { const getActiveKey = () => {
const path = location.pathname.split('/')[1] || 'ship'; const path = location.pathname.split('/')[1];
return pathToKey[path] || 'gnb1'; if (!path) return null; //
return pathToKey[path] || null;
}; };
const activeKey = getActiveKey(); const activeKey = getActiveKey();
@ -64,14 +71,15 @@ export default function Sidebar() {
case 'gnb6': case 'gnb6':
return <Panel6Component {...panelProps} />; return <Panel6Component {...panelProps} />;
case 'gnb7': case 'gnb7':
return <Panel7Component {...panelProps} />; return <ReplayPage {...panelProps} />;
case 'gnb8': case 'gnb8':
return <Panel8Component {...panelProps} />; return <Panel8Component {...panelProps} />;
case 'filter': case 'filter':
return <DisplayComponent {...panelProps} initialTab="filter" />;
case 'layer': case 'layer':
return <DisplayComponent {...panelProps} />; return <DisplayComponent {...panelProps} initialTab="layer" />;
default: default:
return <Panel1Component {...panelProps} />; return null; //
} }
}; };

파일 보기

@ -2,6 +2,11 @@ import { useState, useCallback } from 'react';
import { useMapStore } from '../../stores/mapStore'; import { useMapStore } from '../../stores/mapStore';
import useShipStore from '../../stores/shipStore'; import useShipStore from '../../stores/shipStore';
import { downloadShipCsv } from '../../utils/csvDownload'; import { downloadShipCsv } from '../../utils/csvDownload';
import { showLiveShips } from '../../utils/liveControl';
import useReplayStore from '../../replay/stores/replayStore';
import useAnimationStore from '../../replay/stores/animationStore';
import { unregisterReplayLayers } from '../../replay/utils/replayLayerRegistry';
import { shipBatchRenderer } from '../../map/ShipBatchRenderer';
// //
const AREA_SHAPES = [ const AREA_SHAPES = [
@ -45,7 +50,27 @@ export default function ToolBar() {
{/* 툴바 */} {/* 툴바 */}
<div className="toolBar"> <div className="toolBar">
<ul className="toolItem space"> <ul className="toolItem space">
<li><button type="button" className="tool01">초기화</button></li> <li>
<button
type="button"
className="tool01"
onClick={() => {
//
useReplayStore.getState().reset();
useAnimationStore.getState().reset();
unregisterReplayLayers();
//
showLiveShips();
//
shipBatchRenderer.immediateRender();
//
}}
title="초기화"
>초기화</button>
</li>
<li> <li>
<button <button
type="button" type="button"

파일 보기

@ -372,7 +372,8 @@
padding: 3rem 2rem; padding: 3rem 2rem;
&.noLine { &.noLine {
overflow-y: visible; overflow-x: hidden;
overflow-y: auto;
border-top: 0; border-top: 0;
padding: 0 2rem; padding: 0 2rem;
} }
@ -389,7 +390,8 @@
.tabBtmCnt { .tabBtmCnt {
flex: 1 1 auto; flex: 1 1 auto;
min-height: 0 ; min-height: 0;
overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
padding-bottom: 2rem; padding-bottom: 2rem;
} }