refactor(frontend): 탭 단위 패키지 구조 전환 (tabs/)
- 11개 탭 디렉토리 생성: tabs/{prediction,hns,rescue,weather,incidents,aerial,board,reports,assets,scat,admin}/
- 51개 컴포넌트를 역할 기반(views/, analysis/, layout/) → 탭 기반(tabs/) 구조로 이동
- weather 탭에 전용 hooks/, services/ 포함
- incidents 탭에 전용 services/ 포함
- 공통 지도 컴포넌트(MapView, BacktrackReplay)를 common/components/map/으로 이동
- 각 탭에 index.ts 생성하여 View 컴포넌트 re-export
- App.tsx import를 @tabs/ alias 사용으로 변경
- 전체 import 경로 수정 (탭 내부 상대경로, 외부 @common/ alias)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
부모
a61864646f
커밋
f099ff29b1
@ -6,17 +6,17 @@ import { LoginPage } from '@common/components/auth/LoginPage'
|
||||
import { registerMainTabSwitcher } from '@common/hooks/useSubMenu'
|
||||
import { useAuthStore } from '@common/store/authStore'
|
||||
import { useMenuStore } from '@common/store/menuStore'
|
||||
import { OilSpillView } from './components/views/OilSpillView'
|
||||
import { ReportsView } from './components/views/ReportsView'
|
||||
import { HNSView } from './components/views/HNSView'
|
||||
import { AerialView } from './components/views/AerialView'
|
||||
import { AssetsView } from './components/views/AssetsView'
|
||||
import { BoardView } from './components/views/BoardView'
|
||||
import { WeatherView } from './components/views/WeatherView'
|
||||
import { IncidentsView } from './components/views/IncidentsView'
|
||||
import { AdminView } from './components/views/AdminView'
|
||||
import { PreScatView } from './components/views/PreScatView'
|
||||
import { RescueView } from './components/views/RescueView'
|
||||
import { OilSpillView } from '@tabs/prediction'
|
||||
import { ReportsView } from '@tabs/reports'
|
||||
import { HNSView } from '@tabs/hns'
|
||||
import { AerialView } from '@tabs/aerial'
|
||||
import { AssetsView } from '@tabs/assets'
|
||||
import { BoardView } from '@tabs/board'
|
||||
import { WeatherView } from '@tabs/weather'
|
||||
import { IncidentsView } from '@tabs/incidents'
|
||||
import { AdminView } from '@tabs/admin'
|
||||
import { PreScatView } from '@tabs/scat'
|
||||
import { RescueView } from '@tabs/rescue'
|
||||
|
||||
const GOOGLE_CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID || ''
|
||||
|
||||
|
||||
@ -2,9 +2,9 @@ import { useState, useMemo, useEffect } from 'react'
|
||||
import { MapContainer, TileLayer, Marker, Popup, useMap, useMapEvents, CircleMarker, Circle, Polyline } from 'react-leaflet'
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import L from 'leaflet'
|
||||
import { layerDatabase } from '../../data/layerDatabase'
|
||||
import { layerDatabase } from '../../../data/layerDatabase'
|
||||
import { decimalToDMS } from '@common/utils/coordinates'
|
||||
import type { PredictionModel } from '../views/OilSpillView'
|
||||
import type { PredictionModel } from '@tabs/prediction/components/OilSpillView'
|
||||
import type { BoomLine, BoomLineCoord } from '@common/types/boomLine'
|
||||
import type { ReplayShip, CollisionEvent } from '@common/types/backtrack'
|
||||
import { BacktrackReplayOverlay } from './BacktrackReplayOverlay'
|
||||
1
frontend/src/tabs/admin/index.ts
Normal file
1
frontend/src/tabs/admin/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { AdminView } from './components/AdminView'
|
||||
@ -1,6 +1,6 @@
|
||||
import { useState, useRef, useEffect } from 'react'
|
||||
import { useSubMenu } from '@common/hooks/useSubMenu'
|
||||
import { AerialTheoryView } from '../analysis/AerialTheoryView'
|
||||
import { AerialTheoryView } from './AerialTheoryView'
|
||||
|
||||
type AerialTab = 'media' | 'analysis' | 'realtime' | 'sensor'
|
||||
|
||||
1
frontend/src/tabs/aerial/index.ts
Normal file
1
frontend/src/tabs/aerial/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { AerialView } from './components/AerialView'
|
||||
1
frontend/src/tabs/assets/index.ts
Normal file
1
frontend/src/tabs/assets/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { AssetsView } from './components/AssetsView'
|
||||
@ -1,7 +1,7 @@
|
||||
import { useState } from 'react'
|
||||
import { useSubMenu } from '@common/hooks/useSubMenu'
|
||||
import { BoardWriteForm } from '../board/BoardWriteForm'
|
||||
import { BoardDetailView } from '../board/BoardDetailView'
|
||||
import { BoardWriteForm } from './BoardWriteForm'
|
||||
import { BoardDetailView } from './BoardDetailView'
|
||||
|
||||
interface BoardPost {
|
||||
id: number
|
||||
1
frontend/src/tabs/board/index.ts
Normal file
1
frontend/src/tabs/board/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { BoardView } from './components/BoardView'
|
||||
@ -1,6 +1,6 @@
|
||||
import React, { useState, useRef, useMemo } from 'react'
|
||||
import { sanitizeHtml } from '@common/utils/sanitize'
|
||||
import { HNS_SEARCH_DB, type HNSSearchSubstance } from '../../data/hnsSubstanceSearchData'
|
||||
import { HNS_SEARCH_DB, type HNSSearchSubstance } from '../../../data/hnsSubstanceSearchData'
|
||||
|
||||
/* ═══ HNS 물질 데이터베이스 ═══ */
|
||||
interface HNSSubstance {
|
||||
@ -1,12 +1,12 @@
|
||||
import { useState } from 'react'
|
||||
import { HNSLeftPanel } from '../layout/HNSLeftPanel'
|
||||
import { HNSRightPanel } from '../layout/HNSRightPanel'
|
||||
import { MapView } from '../map/MapView'
|
||||
import { HNSAnalysisListTable } from '../analysis/HNSAnalysisListTable'
|
||||
import { HNSTheoryView } from '../analysis/HNSTheoryView'
|
||||
import { HNSSubstanceView } from '../analysis/HNSSubstanceView'
|
||||
import { HNSScenarioView } from '../analysis/HNSScenarioView'
|
||||
import { HNSRecalcModal } from '../analysis/HNSRecalcModal'
|
||||
import { HNSLeftPanel } from './HNSLeftPanel'
|
||||
import { HNSRightPanel } from './HNSRightPanel'
|
||||
import { MapView } from '@common/components/map/MapView'
|
||||
import { HNSAnalysisListTable } from './HNSAnalysisListTable'
|
||||
import { HNSTheoryView } from './HNSTheoryView'
|
||||
import { HNSSubstanceView } from './HNSSubstanceView'
|
||||
import { HNSScenarioView } from './HNSScenarioView'
|
||||
import { HNSRecalcModal } from './HNSRecalcModal'
|
||||
import { useSubMenu, navigateToTab, setReportGenCategory } from '@common/hooks/useSubMenu'
|
||||
|
||||
/* ─── HNS 매뉴얼 뷰어 컴포넌트 ─── */
|
||||
1
frontend/src/tabs/hns/index.ts
Normal file
1
frontend/src/tabs/hns/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { HNSView } from './components/HNSView'
|
||||
@ -3,9 +3,9 @@ import { MapContainer, TileLayer, CircleMarker, Popup, Marker } from 'react-leaf
|
||||
import L from 'leaflet'
|
||||
import type { LatLngExpression } from 'leaflet'
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import { IncidentsLeftPanel, type Incident } from '../incidents/IncidentsLeftPanel'
|
||||
import { IncidentsRightPanel, type ViewMode, type AnalysisSection } from '../incidents/IncidentsRightPanel'
|
||||
import { mockVessels, VESSEL_LEGEND, type Vessel } from '../../data/vesselMockData'
|
||||
import { IncidentsLeftPanel, type Incident } from './IncidentsLeftPanel'
|
||||
import { IncidentsRightPanel, type ViewMode, type AnalysisSection } from './IncidentsRightPanel'
|
||||
import { mockVessels, VESSEL_LEGEND, type Vessel } from '../../../data/vesselMockData'
|
||||
|
||||
// Mock incident data (HTML 참고 6건)
|
||||
const mockIncidents: Incident[] = [
|
||||
1
frontend/src/tabs/incidents/index.ts
Normal file
1
frontend/src/tabs/incidents/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { IncidentsView } from './components/IncidentsView'
|
||||
@ -1,16 +1,16 @@
|
||||
import { useState, useMemo } from 'react'
|
||||
import { LayerTree } from '@common/components/layer/LayerTree'
|
||||
import { useLayerTree } from '@common/hooks/useLayers'
|
||||
import { layerData } from '../../data/layerData'
|
||||
import type { LayerNode } from '../../data/layerData'
|
||||
import type { Layer } from '../../data/layerDatabase'
|
||||
import { layerData } from '../../../data/layerData'
|
||||
import type { LayerNode } from '../../../data/layerData'
|
||||
import type { Layer } from '../../../data/layerDatabase'
|
||||
import { decimalToDMS } from '@common/utils/coordinates'
|
||||
import { ComboBox } from '@common/components/ui/ComboBox'
|
||||
import { ALL_MODELS } from '../views/OilSpillView'
|
||||
import type { PredictionModel } from '../views/OilSpillView'
|
||||
import { ALL_MODELS } from './OilSpillView'
|
||||
import type { PredictionModel } from './OilSpillView'
|
||||
import type { BoomLine, BoomLineCoord, AlgorithmSettings, ContainmentResult } from '@common/types/boomLine'
|
||||
import { generateAIBoomLines, runContainmentAnalysis, computePolylineLength, computeBearing } from '@common/utils/geo'
|
||||
import type { Analysis } from '../analysis/AnalysisListTable'
|
||||
import type { Analysis } from './AnalysisListTable'
|
||||
|
||||
interface LeftPanelProps {
|
||||
selectedAnalysis?: Analysis | null
|
||||
@ -1,18 +1,18 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { LeftPanel } from '../layout/LeftPanel'
|
||||
import { RightPanel } from '../layout/RightPanel'
|
||||
import { MapView } from '../map/MapView'
|
||||
import { AnalysisListTable, type Analysis } from '../analysis/AnalysisListTable'
|
||||
import { OilSpillTheoryView } from '../analysis/OilSpillTheoryView'
|
||||
import { BoomDeploymentTheoryView } from '../analysis/BoomDeploymentTheoryView'
|
||||
import { BacktrackModal } from '../analysis/BacktrackModal'
|
||||
import { RecalcModal } from '../analysis/RecalcModal'
|
||||
import { BacktrackReplayBar } from '../map/BacktrackReplayBar'
|
||||
import { LeftPanel } from './LeftPanel'
|
||||
import { RightPanel } from './RightPanel'
|
||||
import { MapView } from '@common/components/map/MapView'
|
||||
import { AnalysisListTable, type Analysis } from './AnalysisListTable'
|
||||
import { OilSpillTheoryView } from './OilSpillTheoryView'
|
||||
import { BoomDeploymentTheoryView } from './BoomDeploymentTheoryView'
|
||||
import { BacktrackModal } from './BacktrackModal'
|
||||
import { RecalcModal } from './RecalcModal'
|
||||
import { BacktrackReplayBar } from '@common/components/map/BacktrackReplayBar'
|
||||
import { useSubMenu, navigateToTab, setReportGenCategory } from '@common/hooks/useSubMenu'
|
||||
import type { BoomLine, AlgorithmSettings, ContainmentResult, BoomLineCoord } from '@common/types/boomLine'
|
||||
import type { BacktrackPhase, BacktrackVessel } from '@common/types/backtrack'
|
||||
import { TOTAL_REPLAY_FRAMES } from '@common/types/backtrack'
|
||||
import { MOCK_CONDITIONS, MOCK_VESSELS, MOCK_REPLAY_SHIPS, MOCK_COLLISION } from '../../data/backtrackMockData'
|
||||
import { MOCK_CONDITIONS, MOCK_VESSELS, MOCK_REPLAY_SHIPS, MOCK_COLLISION } from '../../../data/backtrackMockData'
|
||||
|
||||
export type PredictionModel = 'KOSPS' | 'POSEIDON' | 'OpenDrift'
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
@ -1,5 +1,5 @@
|
||||
import { useState, useRef, useEffect } from 'react'
|
||||
import type { PredictionModel } from '../views/OilSpillView'
|
||||
import type { PredictionModel } from './OilSpillView'
|
||||
|
||||
interface RecalcModalProps {
|
||||
isOpen: boolean
|
||||
1
frontend/src/tabs/prediction/index.ts
Normal file
1
frontend/src/tabs/prediction/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { OilSpillView } from './components/OilSpillView'
|
||||
@ -8,7 +8,7 @@ import {
|
||||
type OilSpillReportData,
|
||||
type ReportType,
|
||||
type Jurisdiction,
|
||||
} from '../reports/OilSpillReportTemplate'
|
||||
} from './OilSpillReportTemplate'
|
||||
import { sanitizeHtml } from '@common/utils/sanitize'
|
||||
import { useSubMenu, consumeReportGenCategory } from '@common/hooks/useSubMenu'
|
||||
|
||||
1
frontend/src/tabs/reports/index.ts
Normal file
1
frontend/src/tabs/reports/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { ReportsView } from './components/ReportsView'
|
||||
@ -1,7 +1,7 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useSubMenu } from '@common/hooks/useSubMenu'
|
||||
import { RescueTheoryView } from '../analysis/RescueTheoryView'
|
||||
import { RescueScenarioView } from '../analysis/RescueScenarioView'
|
||||
import { RescueTheoryView } from './RescueTheoryView'
|
||||
import { RescueScenarioView } from './RescueScenarioView'
|
||||
|
||||
/* ─── Types ─── */
|
||||
type AccidentType = 'collision' | 'grounding' | 'turning' | 'capsizing' | 'sharpTurn' | 'flooding' | 'sinking'
|
||||
1
frontend/src/tabs/rescue/index.ts
Normal file
1
frontend/src/tabs/rescue/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { RescueView } from './components/RescueView'
|
||||
@ -1,7 +1,7 @@
|
||||
import { ImageOverlay, useMap } from 'react-leaflet'
|
||||
import { LatLngBounds } from 'leaflet'
|
||||
import { useEffect, useState } from 'react'
|
||||
import type { OceanForecastData } from '../../services/khoaApi'
|
||||
import type { OceanForecastData } from '../services/khoaApi'
|
||||
|
||||
interface OceanForecastOverlayProps {
|
||||
forecast: OceanForecastData | null
|
||||
@ -2,14 +2,14 @@ import { useState, useEffect } from 'react'
|
||||
import { MapContainer, TileLayer, useMapEvents } from 'react-leaflet'
|
||||
import type { LatLngExpression } from 'leaflet'
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import { WeatherRightPanel } from '../weather/WeatherRightPanel'
|
||||
import { WeatherMapOverlay } from '../weather/WeatherMapOverlay'
|
||||
import { OceanForecastOverlay } from '../weather/OceanForecastOverlay'
|
||||
import { OceanCurrentLayer } from '../weather/OceanCurrentLayer'
|
||||
import { WaterTemperatureLayer } from '../weather/WaterTemperatureLayer'
|
||||
import { WindParticleLayer } from '../weather/WindParticleLayer'
|
||||
import { useWeatherData } from '../../hooks/useWeatherData'
|
||||
import { useOceanForecast } from '../../hooks/useOceanForecast'
|
||||
import { WeatherRightPanel } from './WeatherRightPanel'
|
||||
import { WeatherMapOverlay } from './WeatherMapOverlay'
|
||||
import { OceanForecastOverlay } from './OceanForecastOverlay'
|
||||
import { OceanCurrentLayer } from './OceanCurrentLayer'
|
||||
import { WaterTemperatureLayer } from './WaterTemperatureLayer'
|
||||
import { WindParticleLayer } from './WindParticleLayer'
|
||||
import { useWeatherData } from '../hooks/useWeatherData'
|
||||
import { useOceanForecast } from '../hooks/useOceanForecast'
|
||||
|
||||
type TimeOffset = '0' | '3' | '6' | '9'
|
||||
|
||||
1
frontend/src/tabs/weather/index.ts
Normal file
1
frontend/src/tabs/weather/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { WeatherView } from './components/WeatherView'
|
||||
불러오는 중...
Reference in New Issue
Block a user