From a61864646fa293667291599c7a2fcf62515920e4 Mon Sep 17 00:00:00 2001 From: htlee Date: Sat, 28 Feb 2026 14:00:50 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor(frontend):=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20common/=20=EB=B6=84=EB=A6=AC=20+=20OpenLay?= =?UTF-8?q?ers=20=EC=A0=9C=EA=B1=B0=20+=20path=20alias=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OpenLayers(ol) 패키지 제거 (미사용, import 0건) - common/ 디렉토리 생성: components, hooks, services, store, types, utils - 17개 공통 파일을 common/으로 이동 (git mv, blame 이력 보존) - MainTab 타입을 App.tsx에서 common/types/navigation.ts로 분리 - tsconfig path alias (@common/*, @tabs/*) + vite resolve.alias 설정 - 42개 import 경로를 @common/ alias 또는 상대경로로 수정 Co-Authored-By: Claude Opus 4.6 --- frontend/package-lock.json | 205 ------------------ frontend/package.json | 1 - frontend/src/App.tsx | 13 +- .../components/auth/LoginPage.tsx | 0 .../components/layer/LayerTree.tsx | 2 +- .../components/layout/MainLayout.tsx | 2 +- .../components/layout/SubMenuBar.tsx | 2 +- .../{ => common}/components/layout/TopBar.tsx | 2 +- .../{ => common}/components/ui/ComboBox.tsx | 0 frontend/src/{ => common}/hooks/useLayers.ts | 2 +- frontend/src/{ => common}/hooks/useSubMenu.ts | 2 +- frontend/src/{ => common}/services/api.ts | 0 frontend/src/{ => common}/services/authApi.ts | 0 frontend/src/{ => common}/store/authStore.ts | 0 frontend/src/{ => common}/store/menuStore.ts | 0 frontend/src/{ => common}/types/backtrack.ts | 0 frontend/src/{ => common}/types/boomLine.ts | 0 frontend/src/common/types/navigation.ts | 1 + .../src/{ => common}/utils/coordinates.ts | 0 frontend/src/{ => common}/utils/geo.ts | 0 frontend/src/{ => common}/utils/sanitize.ts | 0 .../components/analysis/AerialTheoryView.tsx | 2 +- .../components/analysis/BacktrackModal.tsx | 2 +- .../components/analysis/HNSSubstanceView.tsx | 2 +- .../src/components/analysis/HNSTheoryView.tsx | 2 +- .../analysis/OilSpillTheoryView.tsx | 2 +- .../components/analysis/RescueTheoryView.tsx | 2 +- .../src/components/board/BoardWriteForm.tsx | 2 +- .../src/components/layout/HNSLeftPanel.tsx | 2 +- frontend/src/components/layout/LeftPanel.tsx | 12 +- .../src/components/map/BacktrackReplayBar.tsx | 2 +- .../components/map/BacktrackReplayOverlay.tsx | 2 +- frontend/src/components/map/MapView.tsx | 6 +- frontend/src/components/views/AdminView.tsx | 6 +- frontend/src/components/views/AerialView.tsx | 2 +- frontend/src/components/views/BoardView.tsx | 2 +- frontend/src/components/views/HNSView.tsx | 2 +- .../src/components/views/OilSpillView.tsx | 8 +- frontend/src/components/views/ReportsView.tsx | 4 +- frontend/src/components/views/RescueView.tsx | 2 +- frontend/src/data/backtrackMockData.ts | 2 +- frontend/src/data/layerDatabase.ts | 2 +- frontend/tsconfig.app.json | 9 +- frontend/vite.config.ts | 7 + 44 files changed, 62 insertions(+), 254 deletions(-) rename frontend/src/{ => common}/components/auth/LoginPage.tsx (100%) rename frontend/src/{ => common}/components/layer/LayerTree.tsx (99%) rename frontend/src/{ => common}/components/layout/MainLayout.tsx (93%) rename frontend/src/{ => common}/components/layout/SubMenuBar.tsx (95%) rename frontend/src/{ => common}/components/layout/TopBar.tsx (99%) rename frontend/src/{ => common}/components/ui/ComboBox.tsx (100%) rename frontend/src/{ => common}/hooks/useLayers.ts (93%) rename frontend/src/{ => common}/hooks/useSubMenu.ts (98%) rename frontend/src/{ => common}/services/api.ts (100%) rename frontend/src/{ => common}/services/authApi.ts (100%) rename frontend/src/{ => common}/store/authStore.ts (100%) rename frontend/src/{ => common}/store/menuStore.ts (100%) rename frontend/src/{ => common}/types/backtrack.ts (100%) rename frontend/src/{ => common}/types/boomLine.ts (100%) create mode 100644 frontend/src/common/types/navigation.ts rename frontend/src/{ => common}/utils/coordinates.ts (100%) rename frontend/src/{ => common}/utils/geo.ts (100%) rename frontend/src/{ => common}/utils/sanitize.ts (100%) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e5e0d34..bc22c88 100755 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,7 +19,6 @@ "emoji-mart": "^5.6.0", "leaflet": "^1.9.4", "lucide-react": "^0.564.0", - "ol": "^10.8.0", "react": "^19.2.0", "react-dom": "^19.2.0", "react-leaflet": "^5.0.0", @@ -1148,12 +1147,6 @@ "node": ">= 8" } }, - "node_modules/@petamoriken/float16": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.3.tgz", - "integrity": "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==", - "license": "MIT" - }, "node_modules/@react-leaflet/core": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz", @@ -1650,12 +1643,6 @@ "undici-types": "~7.16.0" } }, - "node_modules/@types/rbush": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-4.0.0.tgz", - "integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==", - "license": "MIT" - }, "node_modules/@types/react": { "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", @@ -1966,16 +1953,6 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/@zarrita/storage": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@zarrita/storage/-/storage-0.1.4.tgz", - "integrity": "sha512-qURfJAQcQGRfDQ4J9HaCjGaj3jlJKc66bnRk6G/IeLUsM7WKyG7Bzsuf1EZurSXyc0I4LVcu6HaeQQ4d3kZ16g==", - "license": "MIT", - "dependencies": { - "reference-spec-reader": "^0.2.0", - "unzipit": "1.4.3" - } - }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -2483,12 +2460,6 @@ "node": ">= 0.4" } }, - "node_modules/earcut": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", - "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", - "license": "ISC" - }, "node_modules/electron-to-chromium": { "version": "1.5.286", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", @@ -2897,12 +2868,6 @@ } } }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -3051,25 +3016,6 @@ "node": ">=6.9.0" } }, - "node_modules/geotiff": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-3.0.3.tgz", - "integrity": "sha512-yRoDQDYxWYiB421p0cbxJvdy79OlQW+rxDI9GDbIUeWCAh6YAZ0vlTKF448EAiEuuUpBsNaegd2flavF0p+kvw==", - "license": "MIT", - "dependencies": { - "@petamoriken/float16": "^3.4.7", - "lerc": "^3.0.0", - "pako": "^2.0.4", - "parse-headers": "^2.0.2", - "quick-lru": "^6.1.1", - "web-worker": "^1.5.0", - "xml-utils": "^1.10.2", - "zstddec": "^0.2.0" - }, - "engines": { - "node": ">=10.19" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -3410,12 +3356,6 @@ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", "license": "BSD-2-Clause" }, - "node_modules/lerc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz", - "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==", - "license": "Apache-2.0" - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3633,15 +3573,6 @@ "node": ">=0.10.0" } }, - "node_modules/numcodecs": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/numcodecs/-/numcodecs-0.3.2.tgz", - "integrity": "sha512-6YSPnmZgg0P87jnNhi3s+FVLOcIn3y+1CTIgUulA3IdASzK9fJM87sUFkpyA+be9GibGRaST2wCgkD+6U+fWKw==", - "license": "MIT", - "dependencies": { - "fflate": "^0.8.0" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3662,24 +3593,6 @@ "node": ">= 6" } }, - "node_modules/ol": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/ol/-/ol-10.8.0.tgz", - "integrity": "sha512-kLk7jIlJvKyhVMAjORTXKjzlM6YIByZ1H/d0DBx3oq8nSPCG6/gbLr5RxukzPgwbhnAqh+xHNCmrvmFKhVMvoQ==", - "license": "BSD-2-Clause", - "dependencies": { - "@types/rbush": "4.0.0", - "earcut": "^3.0.0", - "geotiff": "^3.0.2", - "pbf": "4.0.1", - "rbush": "^4.0.0", - "zarrita": "^0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/openlayers" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3730,12 +3643,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "license": "(MIT AND Zlib)" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3749,12 +3656,6 @@ "node": ">=6" } }, - "node_modules/parse-headers": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", - "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==", - "license": "MIT" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3782,18 +3683,6 @@ "dev": true, "license": "MIT" }, - "node_modules/pbf": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz", - "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", - "license": "BSD-3-Clause", - "dependencies": { - "resolve-protobuf-schema": "^2.1.0" - }, - "bin": { - "pbf": "bin/pbf" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -4007,12 +3896,6 @@ "node": ">= 0.8.0" } }, - "node_modules/protocol-buffers-schema": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", - "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", - "license": "MIT" - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -4050,33 +3933,6 @@ ], "license": "MIT" }, - "node_modules/quick-lru": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", - "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/quickselect": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", - "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", - "license": "ISC" - }, - "node_modules/rbush": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/rbush/-/rbush-4.0.1.tgz", - "integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==", - "license": "MIT", - "dependencies": { - "quickselect": "^3.0.0" - } - }, "node_modules/react": { "version": "19.2.4", "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", @@ -4158,12 +4014,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/reference-spec-reader": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reference-spec-reader/-/reference-spec-reader-0.2.0.tgz", - "integrity": "sha512-q0mfCi5yZSSHXpCyxjgQeaORq3tvDsxDyzaadA/5+AbAUwRyRuuTh0aRQuE/vAOt/qzzxidJ5iDeu1cLHaNBlQ==", - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", @@ -4195,15 +4045,6 @@ "node": ">=4" } }, - "node_modules/resolve-protobuf-schema": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", - "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", - "license": "MIT", - "dependencies": { - "protocol-buffers-schema": "^3.3.1" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -4598,18 +4439,6 @@ "dev": true, "license": "MIT" }, - "node_modules/unzipit": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unzipit/-/unzipit-1.4.3.tgz", - "integrity": "sha512-gsq2PdJIWWGhx5kcdWStvNWit9FVdTewm4SEG7gFskWs+XCVaULt9+BwuoBtJiRE8eo3L1IPAOrbByNLtLtIlg==", - "license": "MIT", - "dependencies": { - "uzip-module": "^1.0.2" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -4658,12 +4487,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uzip-module": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/uzip-module/-/uzip-module-1.0.3.tgz", - "integrity": "sha512-AMqwWZaknLM77G+VPYNZLEruMGWGzyigPK3/Whg99B3S6vGHuqsyl5ZrOv1UUF3paGK1U6PM0cnayioaryg/fA==", - "license": "MIT" - }, "node_modules/vite": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", @@ -4739,12 +4562,6 @@ } } }, - "node_modules/web-worker": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", - "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", - "license": "Apache-2.0" - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4792,12 +4609,6 @@ } } }, - "node_modules/xml-utils": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.2.tgz", - "integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==", - "license": "CC0-1.0" - }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", @@ -4826,16 +4637,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/zarrita": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/zarrita/-/zarrita-0.6.1.tgz", - "integrity": "sha512-YOMTW8FT55Rz+vadTIZeOFZ/F2h4svKizyldvPtMYSxPgSNcRkOzkxCsWpIWlWzB1I/LmISmi0bEekOhLlI+Zw==", - "license": "MIT", - "dependencies": { - "@zarrita/storage": "^0.1.4", - "numcodecs": "^0.3.2" - } - }, "node_modules/zod": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", @@ -4859,12 +4660,6 @@ "zod": "^3.25.0 || ^4.0.0" } }, - "node_modules/zstddec": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.2.0.tgz", - "integrity": "sha512-oyPnDa1X5c13+Y7mA/FDMNJrn4S8UNBe0KCqtDmor40Re7ALrPN6npFwyYVRRh+PqozZQdeg23QtbcamZnG5rA==", - "license": "MIT AND BSD-3-Clause" - }, "node_modules/zustand": { "version": "5.0.11", "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.11.tgz", diff --git a/frontend/package.json b/frontend/package.json index c659318..aa8625f 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,7 +21,6 @@ "emoji-mart": "^5.6.0", "leaflet": "^1.9.4", "lucide-react": "^0.564.0", - "ol": "^10.8.0", "react": "^19.2.0", "react-dom": "^19.2.0", "react-leaflet": "^5.0.0", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index de541a9..3805afc 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,10 +1,11 @@ import { useState, useEffect } from 'react' import { GoogleOAuthProvider } from '@react-oauth/google' -import { MainLayout } from './components/layout/MainLayout' -import { LoginPage } from './components/auth/LoginPage' -import { registerMainTabSwitcher } from './hooks/useSubMenu' -import { useAuthStore } from './store/authStore' -import { useMenuStore } from './store/menuStore' +import type { MainTab } from '@common/types/navigation' +import { MainLayout } from '@common/components/layout/MainLayout' +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' @@ -17,8 +18,6 @@ import { AdminView } from './components/views/AdminView' import { PreScatView } from './components/views/PreScatView' import { RescueView } from './components/views/RescueView' -export type MainTab = 'prediction' | 'hns' | 'rescue' | 'reports' | 'aerial' | 'assets' | 'scat' | 'incidents' | 'board' | 'weather' | 'admin' - const GOOGLE_CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID || '' function App() { diff --git a/frontend/src/components/auth/LoginPage.tsx b/frontend/src/common/components/auth/LoginPage.tsx similarity index 100% rename from frontend/src/components/auth/LoginPage.tsx rename to frontend/src/common/components/auth/LoginPage.tsx diff --git a/frontend/src/components/layer/LayerTree.tsx b/frontend/src/common/components/layer/LayerTree.tsx similarity index 99% rename from frontend/src/components/layer/LayerTree.tsx rename to frontend/src/common/components/layer/LayerTree.tsx index df2a736..d02db78 100755 --- a/frontend/src/components/layer/LayerTree.tsx +++ b/frontend/src/common/components/layer/LayerTree.tsx @@ -1,5 +1,5 @@ import { useState, useRef, useEffect } from 'react' -import type { Layer } from '../../data/layerDatabase' +import type { Layer } from '../../../data/layerDatabase' const PRESET_COLORS = [ '#ef4444','#f97316','#eab308','#22c55e','#06b6d4', diff --git a/frontend/src/components/layout/MainLayout.tsx b/frontend/src/common/components/layout/MainLayout.tsx similarity index 93% rename from frontend/src/components/layout/MainLayout.tsx rename to frontend/src/common/components/layout/MainLayout.tsx index 68f7c50..adddd5f 100755 --- a/frontend/src/components/layout/MainLayout.tsx +++ b/frontend/src/common/components/layout/MainLayout.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from 'react' -import type { MainTab } from '../../App' +import type { MainTab } from '../../types/navigation' import { TopBar } from './TopBar' import { SubMenuBar } from './SubMenuBar' diff --git a/frontend/src/components/layout/SubMenuBar.tsx b/frontend/src/common/components/layout/SubMenuBar.tsx similarity index 95% rename from frontend/src/components/layout/SubMenuBar.tsx rename to frontend/src/common/components/layout/SubMenuBar.tsx index 9abd458..98a39da 100755 --- a/frontend/src/components/layout/SubMenuBar.tsx +++ b/frontend/src/common/components/layout/SubMenuBar.tsx @@ -1,4 +1,4 @@ -import type { MainTab } from '../../App' +import type { MainTab } from '../../types/navigation' import { useSubMenu } from '../../hooks/useSubMenu' interface SubMenuBarProps { diff --git a/frontend/src/components/layout/TopBar.tsx b/frontend/src/common/components/layout/TopBar.tsx similarity index 99% rename from frontend/src/components/layout/TopBar.tsx rename to frontend/src/common/components/layout/TopBar.tsx index c5f4a8d..3133575 100755 --- a/frontend/src/components/layout/TopBar.tsx +++ b/frontend/src/common/components/layout/TopBar.tsx @@ -1,5 +1,5 @@ import { useState, useRef, useEffect, useMemo } from 'react' -import type { MainTab } from '../../App' +import type { MainTab } from '../../types/navigation' import { useAuthStore } from '../../store/authStore' import { useMenuStore } from '../../store/menuStore' diff --git a/frontend/src/components/ui/ComboBox.tsx b/frontend/src/common/components/ui/ComboBox.tsx similarity index 100% rename from frontend/src/components/ui/ComboBox.tsx rename to frontend/src/common/components/ui/ComboBox.tsx diff --git a/frontend/src/hooks/useLayers.ts b/frontend/src/common/hooks/useLayers.ts similarity index 93% rename from frontend/src/hooks/useLayers.ts rename to frontend/src/common/hooks/useLayers.ts index 6c0ceb7..ae7fdaf 100755 --- a/frontend/src/hooks/useLayers.ts +++ b/frontend/src/common/hooks/useLayers.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query' import { fetchAllLayers, fetchLayerTree, fetchWMSLayers } from '../services/api' -import type { Layer } from '../data/layerDatabase' +import type { Layer } from '../../data/layerDatabase' // 모든 레이어 조회 훅 export function useLayers() { diff --git a/frontend/src/hooks/useSubMenu.ts b/frontend/src/common/hooks/useSubMenu.ts similarity index 98% rename from frontend/src/hooks/useSubMenu.ts rename to frontend/src/common/hooks/useSubMenu.ts index ce3b04a..9dac4b4 100755 --- a/frontend/src/hooks/useSubMenu.ts +++ b/frontend/src/common/hooks/useSubMenu.ts @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react' -import type { MainTab } from '../App' +import type { MainTab } from '../types/navigation' interface SubMenuItem { id: string diff --git a/frontend/src/services/api.ts b/frontend/src/common/services/api.ts similarity index 100% rename from frontend/src/services/api.ts rename to frontend/src/common/services/api.ts diff --git a/frontend/src/services/authApi.ts b/frontend/src/common/services/authApi.ts similarity index 100% rename from frontend/src/services/authApi.ts rename to frontend/src/common/services/authApi.ts diff --git a/frontend/src/store/authStore.ts b/frontend/src/common/store/authStore.ts similarity index 100% rename from frontend/src/store/authStore.ts rename to frontend/src/common/store/authStore.ts diff --git a/frontend/src/store/menuStore.ts b/frontend/src/common/store/menuStore.ts similarity index 100% rename from frontend/src/store/menuStore.ts rename to frontend/src/common/store/menuStore.ts diff --git a/frontend/src/types/backtrack.ts b/frontend/src/common/types/backtrack.ts similarity index 100% rename from frontend/src/types/backtrack.ts rename to frontend/src/common/types/backtrack.ts diff --git a/frontend/src/types/boomLine.ts b/frontend/src/common/types/boomLine.ts similarity index 100% rename from frontend/src/types/boomLine.ts rename to frontend/src/common/types/boomLine.ts diff --git a/frontend/src/common/types/navigation.ts b/frontend/src/common/types/navigation.ts new file mode 100644 index 0000000..a3c3c57 --- /dev/null +++ b/frontend/src/common/types/navigation.ts @@ -0,0 +1 @@ +export type MainTab = 'prediction' | 'hns' | 'rescue' | 'reports' | 'aerial' | 'assets' | 'scat' | 'incidents' | 'board' | 'weather' | 'admin'; diff --git a/frontend/src/utils/coordinates.ts b/frontend/src/common/utils/coordinates.ts similarity index 100% rename from frontend/src/utils/coordinates.ts rename to frontend/src/common/utils/coordinates.ts diff --git a/frontend/src/utils/geo.ts b/frontend/src/common/utils/geo.ts similarity index 100% rename from frontend/src/utils/geo.ts rename to frontend/src/common/utils/geo.ts diff --git a/frontend/src/utils/sanitize.ts b/frontend/src/common/utils/sanitize.ts similarity index 100% rename from frontend/src/utils/sanitize.ts rename to frontend/src/common/utils/sanitize.ts diff --git a/frontend/src/components/analysis/AerialTheoryView.tsx b/frontend/src/components/analysis/AerialTheoryView.tsx index c61bdea..733724b 100755 --- a/frontend/src/components/analysis/AerialTheoryView.tsx +++ b/frontend/src/components/analysis/AerialTheoryView.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { sanitizeHtml } from '../../utils/sanitize' +import { sanitizeHtml } from '@common/utils/sanitize' const panels = [ { id: 0, icon: '🌐', label: '개요' }, diff --git a/frontend/src/components/analysis/BacktrackModal.tsx b/frontend/src/components/analysis/BacktrackModal.tsx index a646cf7..86bf5ab 100755 --- a/frontend/src/components/analysis/BacktrackModal.tsx +++ b/frontend/src/components/analysis/BacktrackModal.tsx @@ -1,5 +1,5 @@ import { useRef, useEffect } from 'react' -import type { BacktrackPhase, BacktrackVessel, BacktrackConditions } from '../../types/backtrack' +import type { BacktrackPhase, BacktrackVessel, BacktrackConditions } from '@common/types/backtrack' interface BacktrackModalProps { isOpen: boolean diff --git a/frontend/src/components/analysis/HNSSubstanceView.tsx b/frontend/src/components/analysis/HNSSubstanceView.tsx index 6f9f41f..1008239 100755 --- a/frontend/src/components/analysis/HNSSubstanceView.tsx +++ b/frontend/src/components/analysis/HNSSubstanceView.tsx @@ -1,5 +1,5 @@ import React, { useState, useRef, useMemo } from 'react' -import { sanitizeHtml } from '../../utils/sanitize' +import { sanitizeHtml } from '@common/utils/sanitize' import { HNS_SEARCH_DB, type HNSSearchSubstance } from '../../data/hnsSubstanceSearchData' /* ═══ HNS 물질 데이터베이스 ═══ */ diff --git a/frontend/src/components/analysis/HNSTheoryView.tsx b/frontend/src/components/analysis/HNSTheoryView.tsx index 013ce02..39c33bf 100755 --- a/frontend/src/components/analysis/HNSTheoryView.tsx +++ b/frontend/src/components/analysis/HNSTheoryView.tsx @@ -1,5 +1,5 @@ import { useState, useRef } from 'react' -import { sanitizeHtml } from '../../utils/sanitize' +import { sanitizeHtml } from '@common/utils/sanitize' const theoryTabs = [ { icon: '🔬', name: '시스템 개요' }, diff --git a/frontend/src/components/analysis/OilSpillTheoryView.tsx b/frontend/src/components/analysis/OilSpillTheoryView.tsx index 12ce2e0..76a1fa4 100755 --- a/frontend/src/components/analysis/OilSpillTheoryView.tsx +++ b/frontend/src/components/analysis/OilSpillTheoryView.tsx @@ -1,5 +1,5 @@ import { useState, useRef } from 'react' -import { sanitizeHtml } from '../../utils/sanitize' +import { sanitizeHtml } from '@common/utils/sanitize' const theoryTabs: { id: number; icon: string; name: string; nameColor?: string }[] = [ { id: 0, icon: '🌊', name: '시스템 개요' }, diff --git a/frontend/src/components/analysis/RescueTheoryView.tsx b/frontend/src/components/analysis/RescueTheoryView.tsx index fe1a3ed..722dbfd 100755 --- a/frontend/src/components/analysis/RescueTheoryView.tsx +++ b/frontend/src/components/analysis/RescueTheoryView.tsx @@ -1,4 +1,4 @@ -import { sanitizeHtml } from '../../utils/sanitize' +import { sanitizeHtml } from '@common/utils/sanitize' export function RescueTheoryView() { const contentHtml = ` diff --git a/frontend/src/components/board/BoardWriteForm.tsx b/frontend/src/components/board/BoardWriteForm.tsx index 8d077db..e5c0103 100755 --- a/frontend/src/components/board/BoardWriteForm.tsx +++ b/frontend/src/components/board/BoardWriteForm.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react' -import { sanitizeInput } from '../../utils/sanitize' +import { sanitizeInput } from '@common/utils/sanitize' interface BoardPost { id?: number diff --git a/frontend/src/components/layout/HNSLeftPanel.tsx b/frontend/src/components/layout/HNSLeftPanel.tsx index 6da3479..af529f1 100755 --- a/frontend/src/components/layout/HNSLeftPanel.tsx +++ b/frontend/src/components/layout/HNSLeftPanel.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { ComboBox } from '../ui/ComboBox' +import { ComboBox } from '@common/components/ui/ComboBox' interface HNSLeftPanelProps { activeSubTab: 'analysis' | 'list' diff --git a/frontend/src/components/layout/LeftPanel.tsx b/frontend/src/components/layout/LeftPanel.tsx index e9eb1c1..0122881 100755 --- a/frontend/src/components/layout/LeftPanel.tsx +++ b/frontend/src/components/layout/LeftPanel.tsx @@ -1,15 +1,15 @@ import { useState, useMemo } from 'react' -import { LayerTree } from '../layer/LayerTree' -import { useLayerTree } from '../../hooks/useLayers' +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 { decimalToDMS } from '../../utils/coordinates' -import { ComboBox } from '../ui/ComboBox' +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 type { BoomLine, BoomLineCoord, AlgorithmSettings, ContainmentResult } from '../../types/boomLine' -import { generateAIBoomLines, runContainmentAnalysis, computePolylineLength, computeBearing } from '../../utils/geo' +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' interface LeftPanelProps { diff --git a/frontend/src/components/map/BacktrackReplayBar.tsx b/frontend/src/components/map/BacktrackReplayBar.tsx index ec46ddd..fdab7fe 100755 --- a/frontend/src/components/map/BacktrackReplayBar.tsx +++ b/frontend/src/components/map/BacktrackReplayBar.tsx @@ -1,4 +1,4 @@ -import type { ReplayShip, CollisionEvent } from '../../types/backtrack' +import type { ReplayShip, CollisionEvent } from '@common/types/backtrack' interface BacktrackReplayBarProps { isPlaying: boolean diff --git a/frontend/src/components/map/BacktrackReplayOverlay.tsx b/frontend/src/components/map/BacktrackReplayOverlay.tsx index 503d088..c2a6c51 100755 --- a/frontend/src/components/map/BacktrackReplayOverlay.tsx +++ b/frontend/src/components/map/BacktrackReplayOverlay.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react' import { Polyline, CircleMarker, Circle, Marker, Popup } from 'react-leaflet' import L from 'leaflet' -import type { ReplayShip, CollisionEvent, ReplayPathPoint } from '../../types/backtrack' +import type { ReplayShip, CollisionEvent, ReplayPathPoint } from '@common/types/backtrack' interface BacktrackReplayOverlayProps { replayShips: ReplayShip[] diff --git a/frontend/src/components/map/MapView.tsx b/frontend/src/components/map/MapView.tsx index 0d81357..6fc8738 100755 --- a/frontend/src/components/map/MapView.tsx +++ b/frontend/src/components/map/MapView.tsx @@ -3,10 +3,10 @@ import { MapContainer, TileLayer, Marker, Popup, useMap, useMapEvents, CircleMar import 'leaflet/dist/leaflet.css' import L from 'leaflet' import { layerDatabase } from '../../data/layerDatabase' -import { decimalToDMS } from '../../utils/coordinates' +import { decimalToDMS } from '@common/utils/coordinates' import type { PredictionModel } from '../views/OilSpillView' -import type { BoomLine, BoomLineCoord } from '../../types/boomLine' -import type { ReplayShip, CollisionEvent } from '../../types/backtrack' +import type { BoomLine, BoomLineCoord } from '@common/types/boomLine' +import type { ReplayShip, CollisionEvent } from '@common/types/backtrack' import { BacktrackReplayOverlay } from './BacktrackReplayOverlay' // Fix Leaflet default icon issue diff --git a/frontend/src/components/views/AdminView.tsx b/frontend/src/components/views/AdminView.tsx index a0d7bc6..06b0f67 100755 --- a/frontend/src/components/views/AdminView.tsx +++ b/frontend/src/components/views/AdminView.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, useCallback, useRef } from 'react' -import { useSubMenu } from '../../hooks/useSubMenu' +import { useSubMenu } from '@common/hooks/useSubMenu' import data from '@emoji-mart/data' import EmojiPicker from '@emoji-mart/react' import { @@ -43,8 +43,8 @@ import { type RegistrationSettings, type OAuthSettings, type MenuConfigItem, -} from '../../services/authApi' -import { useMenuStore } from '../../store/menuStore' +} from '@common/services/authApi' +import { useMenuStore } from '@common/store/menuStore' const DEFAULT_ROLE_COLORS: Record = { ADMIN: 'var(--red)', diff --git a/frontend/src/components/views/AerialView.tsx b/frontend/src/components/views/AerialView.tsx index 249cb70..0ecfbaf 100755 --- a/frontend/src/components/views/AerialView.tsx +++ b/frontend/src/components/views/AerialView.tsx @@ -1,5 +1,5 @@ import { useState, useRef, useEffect } from 'react' -import { useSubMenu } from '../../hooks/useSubMenu' +import { useSubMenu } from '@common/hooks/useSubMenu' import { AerialTheoryView } from '../analysis/AerialTheoryView' type AerialTab = 'media' | 'analysis' | 'realtime' | 'sensor' diff --git a/frontend/src/components/views/BoardView.tsx b/frontend/src/components/views/BoardView.tsx index 9f29312..9258ffd 100755 --- a/frontend/src/components/views/BoardView.tsx +++ b/frontend/src/components/views/BoardView.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { useSubMenu } from '../../hooks/useSubMenu' +import { useSubMenu } from '@common/hooks/useSubMenu' import { BoardWriteForm } from '../board/BoardWriteForm' import { BoardDetailView } from '../board/BoardDetailView' diff --git a/frontend/src/components/views/HNSView.tsx b/frontend/src/components/views/HNSView.tsx index 8d77bb2..d13ab75 100755 --- a/frontend/src/components/views/HNSView.tsx +++ b/frontend/src/components/views/HNSView.tsx @@ -7,7 +7,7 @@ import { HNSTheoryView } from '../analysis/HNSTheoryView' import { HNSSubstanceView } from '../analysis/HNSSubstanceView' import { HNSScenarioView } from '../analysis/HNSScenarioView' import { HNSRecalcModal } from '../analysis/HNSRecalcModal' -import { useSubMenu, navigateToTab, setReportGenCategory } from '../../hooks/useSubMenu' +import { useSubMenu, navigateToTab, setReportGenCategory } from '@common/hooks/useSubMenu' /* ─── HNS 매뉴얼 뷰어 컴포넌트 ─── */ function HNSManualViewer() { diff --git a/frontend/src/components/views/OilSpillView.tsx b/frontend/src/components/views/OilSpillView.tsx index cea74a0..afb5a8d 100755 --- a/frontend/src/components/views/OilSpillView.tsx +++ b/frontend/src/components/views/OilSpillView.tsx @@ -8,10 +8,10 @@ import { BoomDeploymentTheoryView } from '../analysis/BoomDeploymentTheoryView' import { BacktrackModal } from '../analysis/BacktrackModal' import { RecalcModal } from '../analysis/RecalcModal' import { BacktrackReplayBar } from '../map/BacktrackReplayBar' -import { useSubMenu, navigateToTab, setReportGenCategory } from '../../hooks/useSubMenu' -import type { BoomLine, AlgorithmSettings, ContainmentResult, BoomLineCoord } from '../../types/boomLine' -import type { BacktrackPhase, BacktrackVessel } from '../../types/backtrack' -import { TOTAL_REPLAY_FRAMES } from '../../types/backtrack' +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' export type PredictionModel = 'KOSPS' | 'POSEIDON' | 'OpenDrift' diff --git a/frontend/src/components/views/ReportsView.tsx b/frontend/src/components/views/ReportsView.tsx index 7222f85..c6e6446 100755 --- a/frontend/src/components/views/ReportsView.tsx +++ b/frontend/src/components/views/ReportsView.tsx @@ -9,8 +9,8 @@ import { type ReportType, type Jurisdiction, } from '../reports/OilSpillReportTemplate' -import { sanitizeHtml } from '../../utils/sanitize' -import { useSubMenu, consumeReportGenCategory } from '../../hooks/useSubMenu' +import { sanitizeHtml } from '@common/utils/sanitize' +import { useSubMenu, consumeReportGenCategory } from '@common/hooks/useSubMenu' // ─── Report Export Helpers ────────────────────────────── function generateReportHTML( diff --git a/frontend/src/components/views/RescueView.tsx b/frontend/src/components/views/RescueView.tsx index a5142f0..764dfdf 100755 --- a/frontend/src/components/views/RescueView.tsx +++ b/frontend/src/components/views/RescueView.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react' -import { useSubMenu } from '../../hooks/useSubMenu' +import { useSubMenu } from '@common/hooks/useSubMenu' import { RescueTheoryView } from '../analysis/RescueTheoryView' import { RescueScenarioView } from '../analysis/RescueScenarioView' diff --git a/frontend/src/data/backtrackMockData.ts b/frontend/src/data/backtrackMockData.ts index b494e7e..668cd3f 100755 --- a/frontend/src/data/backtrackMockData.ts +++ b/frontend/src/data/backtrackMockData.ts @@ -1,4 +1,4 @@ -import type { BacktrackConditions, BacktrackVessel, ReplayShip, CollisionEvent } from '../types/backtrack' +import type { BacktrackConditions, BacktrackVessel, ReplayShip, CollisionEvent } from '@common/types/backtrack' export const MOCK_CONDITIONS: BacktrackConditions = { estimatedSpillTime: '02-10 06:30', diff --git a/frontend/src/data/layerDatabase.ts b/frontend/src/data/layerDatabase.ts index 503dbd1..848c0e5 100755 --- a/frontend/src/data/layerDatabase.ts +++ b/frontend/src/data/layerDatabase.ts @@ -1,5 +1,5 @@ // 레이어 데이터베이스 - API에서 가져옴 -import { fetchAllLayers } from '../services/api' +import { fetchAllLayers } from '@common/services/api' export interface Layer { id: string diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json index a9b5a59..016b36c 100755 --- a/frontend/tsconfig.app.json +++ b/frontend/tsconfig.app.json @@ -22,7 +22,14 @@ "noUnusedParameters": true, "erasableSyntaxOnly": true, "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true + "noUncheckedSideEffectImports": true, + + /* Path aliases */ + "baseUrl": ".", + "paths": { + "@common/*": ["src/common/*"], + "@tabs/*": ["src/tabs/*"] + } }, "include": ["src"] } diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 8b0f57b..ccf4196 100755 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,7 +1,14 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' +import path from 'path' // https://vite.dev/config/ export default defineConfig({ plugins: [react()], + resolve: { + alias: { + '@common': path.resolve(__dirname, 'src/common'), + '@tabs': path.resolve(__dirname, 'src/tabs'), + }, + }, }) -- 2.45.2 From f099ff29b124e6a9d85ba368a72a2f47bde3b716 Mon Sep 17 00:00:00 2001 From: htlee Date: Sat, 28 Feb 2026 14:08:34 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor(frontend):=20=ED=83=AD=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EC=A0=84=ED=99=98=20(tabs/)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- frontend/src/App.tsx | 22 +++++++++---------- .../components/map/BacktrackReplayBar.tsx | 0 .../components/map/BacktrackReplayOverlay.tsx | 0 .../{ => common}/components/map/MapView.tsx | 4 ++-- .../admin/components}/AdminView.tsx | 0 frontend/src/tabs/admin/index.ts | 1 + .../aerial/components}/AerialTheoryView.tsx | 0 .../aerial/components}/AerialView.tsx | 2 +- frontend/src/tabs/aerial/index.ts | 1 + .../assets/components}/AssetsView.tsx | 0 frontend/src/tabs/assets/index.ts | 1 + .../board/components}/BoardDetailView.tsx | 0 .../board/components}/BoardListTable.tsx | 0 .../board/components}/BoardView.tsx | 4 ++-- .../board/components}/BoardWriteForm.tsx | 0 frontend/src/tabs/board/index.ts | 1 + .../hns/components}/HNSAnalysisListTable.tsx | 0 .../hns/components}/HNSLeftPanel.tsx | 0 .../hns/components}/HNSRecalcModal.tsx | 0 .../hns/components}/HNSRightPanel.tsx | 0 .../hns/components}/HNSScenarioView.tsx | 0 .../hns/components}/HNSSubstanceView.tsx | 2 +- .../hns/components}/HNSTheoryView.tsx | 0 .../views => tabs/hns/components}/HNSView.tsx | 16 +++++++------- frontend/src/tabs/hns/index.ts | 1 + .../incidents/components}/IncidentTable.tsx | 0 .../components}/IncidentsLeftPanel.tsx | 0 .../components}/IncidentsRightPanel.tsx | 0 .../incidents/components}/IncidentsView.tsx | 6 ++--- .../incidents/components}/MediaModal.tsx | 0 frontend/src/tabs/incidents/index.ts | 1 + .../incidents}/services/vesselService.ts | 0 .../components}/AnalysisListTable.tsx | 0 .../prediction/components}/BacktrackModal.tsx | 0 .../components}/BoomDeploymentTheoryView.tsx | 0 .../prediction/components}/LeftPanel.tsx | 12 +++++----- .../components}/OilSpillTheoryView.tsx | 0 .../prediction/components}/OilSpillView.tsx | 20 ++++++++--------- .../prediction/components}/RecalcModal.tsx | 2 +- .../prediction/components}/RightPanel.tsx | 0 frontend/src/tabs/prediction/index.ts | 1 + .../components}/OilSpillReportTemplate.tsx | 0 .../reports/components}/ReportsView.tsx | 2 +- frontend/src/tabs/reports/index.ts | 1 + .../rescue/components}/RescueScenarioView.tsx | 0 .../rescue/components}/RescueTheoryView.tsx | 0 .../rescue/components}/RescueView.tsx | 4 ++-- frontend/src/tabs/rescue/index.ts | 1 + .../scat/components}/PreScatView.tsx | 0 .../weather/components}/OceanCurrentLayer.tsx | 0 .../components}/OceanForecastOverlay.tsx | 2 +- .../components}/WaterTemperatureLayer.tsx | 0 .../weather/components}/WeatherMapOverlay.tsx | 0 .../weather/components}/WeatherRightPanel.tsx | 0 .../weather/components}/WeatherView.tsx | 16 +++++++------- .../weather/components}/WindParticleLayer.tsx | 0 .../weather}/hooks/useOceanForecast.ts | 0 .../weather}/hooks/useWeatherData.ts | 0 frontend/src/tabs/weather/index.ts | 1 + .../{ => tabs/weather}/services/khoaApi.ts | 0 .../{ => tabs/weather}/services/weatherApi.ts | 0 .../weather}/services/weatherService.ts | 0 62 files changed, 67 insertions(+), 57 deletions(-) rename frontend/src/{ => common}/components/map/BacktrackReplayBar.tsx (100%) rename frontend/src/{ => common}/components/map/BacktrackReplayOverlay.tsx (100%) rename frontend/src/{ => common}/components/map/MapView.tsx (99%) rename frontend/src/{components/views => tabs/admin/components}/AdminView.tsx (100%) create mode 100644 frontend/src/tabs/admin/index.ts rename frontend/src/{components/analysis => tabs/aerial/components}/AerialTheoryView.tsx (100%) rename frontend/src/{components/views => tabs/aerial/components}/AerialView.tsx (99%) create mode 100644 frontend/src/tabs/aerial/index.ts rename frontend/src/{components/views => tabs/assets/components}/AssetsView.tsx (100%) create mode 100644 frontend/src/tabs/assets/index.ts rename frontend/src/{components/board => tabs/board/components}/BoardDetailView.tsx (100%) rename frontend/src/{components/board => tabs/board/components}/BoardListTable.tsx (100%) rename frontend/src/{components/views => tabs/board/components}/BoardView.tsx (99%) rename frontend/src/{components/board => tabs/board/components}/BoardWriteForm.tsx (100%) create mode 100644 frontend/src/tabs/board/index.ts rename frontend/src/{components/analysis => tabs/hns/components}/HNSAnalysisListTable.tsx (100%) rename frontend/src/{components/layout => tabs/hns/components}/HNSLeftPanel.tsx (100%) rename frontend/src/{components/analysis => tabs/hns/components}/HNSRecalcModal.tsx (100%) rename frontend/src/{components/layout => tabs/hns/components}/HNSRightPanel.tsx (100%) rename frontend/src/{components/analysis => tabs/hns/components}/HNSScenarioView.tsx (100%) rename frontend/src/{components/analysis => tabs/hns/components}/HNSSubstanceView.tsx (99%) rename frontend/src/{components/analysis => tabs/hns/components}/HNSTheoryView.tsx (100%) rename frontend/src/{components/views => tabs/hns/components}/HNSView.tsx (98%) create mode 100644 frontend/src/tabs/hns/index.ts rename frontend/src/{components/incidents => tabs/incidents/components}/IncidentTable.tsx (100%) rename frontend/src/{components/incidents => tabs/incidents/components}/IncidentsLeftPanel.tsx (100%) rename frontend/src/{components/incidents => tabs/incidents/components}/IncidentsRightPanel.tsx (100%) rename frontend/src/{components/views => tabs/incidents/components}/IncidentsView.tsx (99%) rename frontend/src/{components/incidents => tabs/incidents/components}/MediaModal.tsx (100%) create mode 100644 frontend/src/tabs/incidents/index.ts rename frontend/src/{ => tabs/incidents}/services/vesselService.ts (100%) rename frontend/src/{components/analysis => tabs/prediction/components}/AnalysisListTable.tsx (100%) rename frontend/src/{components/analysis => tabs/prediction/components}/BacktrackModal.tsx (100%) rename frontend/src/{components/analysis => tabs/prediction/components}/BoomDeploymentTheoryView.tsx (100%) rename frontend/src/{components/layout => tabs/prediction/components}/LeftPanel.tsx (99%) rename frontend/src/{components/analysis => tabs/prediction/components}/OilSpillTheoryView.tsx (100%) rename frontend/src/{components/views => tabs/prediction/components}/OilSpillView.tsx (97%) rename frontend/src/{components/analysis => tabs/prediction/components}/RecalcModal.tsx (99%) rename frontend/src/{components/layout => tabs/prediction/components}/RightPanel.tsx (100%) create mode 100644 frontend/src/tabs/prediction/index.ts rename frontend/src/{components/reports => tabs/reports/components}/OilSpillReportTemplate.tsx (100%) rename frontend/src/{components/views => tabs/reports/components}/ReportsView.tsx (99%) create mode 100644 frontend/src/tabs/reports/index.ts rename frontend/src/{components/analysis => tabs/rescue/components}/RescueScenarioView.tsx (100%) rename frontend/src/{components/analysis => tabs/rescue/components}/RescueTheoryView.tsx (100%) rename frontend/src/{components/views => tabs/rescue/components}/RescueView.tsx (99%) create mode 100644 frontend/src/tabs/rescue/index.ts rename frontend/src/{components/views => tabs/scat/components}/PreScatView.tsx (100%) rename frontend/src/{components/weather => tabs/weather/components}/OceanCurrentLayer.tsx (100%) rename frontend/src/{components/weather => tabs/weather/components}/OceanForecastOverlay.tsx (95%) rename frontend/src/{components/weather => tabs/weather/components}/WaterTemperatureLayer.tsx (100%) rename frontend/src/{components/weather => tabs/weather/components}/WeatherMapOverlay.tsx (100%) rename frontend/src/{components/weather => tabs/weather/components}/WeatherRightPanel.tsx (100%) rename frontend/src/{components/views => tabs/weather/components}/WeatherView.tsx (97%) rename frontend/src/{components/weather => tabs/weather/components}/WindParticleLayer.tsx (100%) rename frontend/src/{ => tabs/weather}/hooks/useOceanForecast.ts (100%) rename frontend/src/{ => tabs/weather}/hooks/useWeatherData.ts (100%) create mode 100644 frontend/src/tabs/weather/index.ts rename frontend/src/{ => tabs/weather}/services/khoaApi.ts (100%) rename frontend/src/{ => tabs/weather}/services/weatherApi.ts (100%) rename frontend/src/{ => tabs/weather}/services/weatherService.ts (100%) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3805afc..bc5b47b 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -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 || '' diff --git a/frontend/src/components/map/BacktrackReplayBar.tsx b/frontend/src/common/components/map/BacktrackReplayBar.tsx similarity index 100% rename from frontend/src/components/map/BacktrackReplayBar.tsx rename to frontend/src/common/components/map/BacktrackReplayBar.tsx diff --git a/frontend/src/components/map/BacktrackReplayOverlay.tsx b/frontend/src/common/components/map/BacktrackReplayOverlay.tsx similarity index 100% rename from frontend/src/components/map/BacktrackReplayOverlay.tsx rename to frontend/src/common/components/map/BacktrackReplayOverlay.tsx diff --git a/frontend/src/components/map/MapView.tsx b/frontend/src/common/components/map/MapView.tsx similarity index 99% rename from frontend/src/components/map/MapView.tsx rename to frontend/src/common/components/map/MapView.tsx index 6fc8738..47c075a 100755 --- a/frontend/src/components/map/MapView.tsx +++ b/frontend/src/common/components/map/MapView.tsx @@ -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' diff --git a/frontend/src/components/views/AdminView.tsx b/frontend/src/tabs/admin/components/AdminView.tsx similarity index 100% rename from frontend/src/components/views/AdminView.tsx rename to frontend/src/tabs/admin/components/AdminView.tsx diff --git a/frontend/src/tabs/admin/index.ts b/frontend/src/tabs/admin/index.ts new file mode 100644 index 0000000..a4a410b --- /dev/null +++ b/frontend/src/tabs/admin/index.ts @@ -0,0 +1 @@ +export { AdminView } from './components/AdminView' diff --git a/frontend/src/components/analysis/AerialTheoryView.tsx b/frontend/src/tabs/aerial/components/AerialTheoryView.tsx similarity index 100% rename from frontend/src/components/analysis/AerialTheoryView.tsx rename to frontend/src/tabs/aerial/components/AerialTheoryView.tsx diff --git a/frontend/src/components/views/AerialView.tsx b/frontend/src/tabs/aerial/components/AerialView.tsx similarity index 99% rename from frontend/src/components/views/AerialView.tsx rename to frontend/src/tabs/aerial/components/AerialView.tsx index 0ecfbaf..321850f 100755 --- a/frontend/src/components/views/AerialView.tsx +++ b/frontend/src/tabs/aerial/components/AerialView.tsx @@ -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' diff --git a/frontend/src/tabs/aerial/index.ts b/frontend/src/tabs/aerial/index.ts new file mode 100644 index 0000000..013f9e4 --- /dev/null +++ b/frontend/src/tabs/aerial/index.ts @@ -0,0 +1 @@ +export { AerialView } from './components/AerialView' diff --git a/frontend/src/components/views/AssetsView.tsx b/frontend/src/tabs/assets/components/AssetsView.tsx similarity index 100% rename from frontend/src/components/views/AssetsView.tsx rename to frontend/src/tabs/assets/components/AssetsView.tsx diff --git a/frontend/src/tabs/assets/index.ts b/frontend/src/tabs/assets/index.ts new file mode 100644 index 0000000..2b2f64f --- /dev/null +++ b/frontend/src/tabs/assets/index.ts @@ -0,0 +1 @@ +export { AssetsView } from './components/AssetsView' diff --git a/frontend/src/components/board/BoardDetailView.tsx b/frontend/src/tabs/board/components/BoardDetailView.tsx similarity index 100% rename from frontend/src/components/board/BoardDetailView.tsx rename to frontend/src/tabs/board/components/BoardDetailView.tsx diff --git a/frontend/src/components/board/BoardListTable.tsx b/frontend/src/tabs/board/components/BoardListTable.tsx similarity index 100% rename from frontend/src/components/board/BoardListTable.tsx rename to frontend/src/tabs/board/components/BoardListTable.tsx diff --git a/frontend/src/components/views/BoardView.tsx b/frontend/src/tabs/board/components/BoardView.tsx similarity index 99% rename from frontend/src/components/views/BoardView.tsx rename to frontend/src/tabs/board/components/BoardView.tsx index 9258ffd..d9a996e 100755 --- a/frontend/src/components/views/BoardView.tsx +++ b/frontend/src/tabs/board/components/BoardView.tsx @@ -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 diff --git a/frontend/src/components/board/BoardWriteForm.tsx b/frontend/src/tabs/board/components/BoardWriteForm.tsx similarity index 100% rename from frontend/src/components/board/BoardWriteForm.tsx rename to frontend/src/tabs/board/components/BoardWriteForm.tsx diff --git a/frontend/src/tabs/board/index.ts b/frontend/src/tabs/board/index.ts new file mode 100644 index 0000000..31edec6 --- /dev/null +++ b/frontend/src/tabs/board/index.ts @@ -0,0 +1 @@ +export { BoardView } from './components/BoardView' diff --git a/frontend/src/components/analysis/HNSAnalysisListTable.tsx b/frontend/src/tabs/hns/components/HNSAnalysisListTable.tsx similarity index 100% rename from frontend/src/components/analysis/HNSAnalysisListTable.tsx rename to frontend/src/tabs/hns/components/HNSAnalysisListTable.tsx diff --git a/frontend/src/components/layout/HNSLeftPanel.tsx b/frontend/src/tabs/hns/components/HNSLeftPanel.tsx similarity index 100% rename from frontend/src/components/layout/HNSLeftPanel.tsx rename to frontend/src/tabs/hns/components/HNSLeftPanel.tsx diff --git a/frontend/src/components/analysis/HNSRecalcModal.tsx b/frontend/src/tabs/hns/components/HNSRecalcModal.tsx similarity index 100% rename from frontend/src/components/analysis/HNSRecalcModal.tsx rename to frontend/src/tabs/hns/components/HNSRecalcModal.tsx diff --git a/frontend/src/components/layout/HNSRightPanel.tsx b/frontend/src/tabs/hns/components/HNSRightPanel.tsx similarity index 100% rename from frontend/src/components/layout/HNSRightPanel.tsx rename to frontend/src/tabs/hns/components/HNSRightPanel.tsx diff --git a/frontend/src/components/analysis/HNSScenarioView.tsx b/frontend/src/tabs/hns/components/HNSScenarioView.tsx similarity index 100% rename from frontend/src/components/analysis/HNSScenarioView.tsx rename to frontend/src/tabs/hns/components/HNSScenarioView.tsx diff --git a/frontend/src/components/analysis/HNSSubstanceView.tsx b/frontend/src/tabs/hns/components/HNSSubstanceView.tsx similarity index 99% rename from frontend/src/components/analysis/HNSSubstanceView.tsx rename to frontend/src/tabs/hns/components/HNSSubstanceView.tsx index 1008239..e314597 100755 --- a/frontend/src/components/analysis/HNSSubstanceView.tsx +++ b/frontend/src/tabs/hns/components/HNSSubstanceView.tsx @@ -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 { diff --git a/frontend/src/components/analysis/HNSTheoryView.tsx b/frontend/src/tabs/hns/components/HNSTheoryView.tsx similarity index 100% rename from frontend/src/components/analysis/HNSTheoryView.tsx rename to frontend/src/tabs/hns/components/HNSTheoryView.tsx diff --git a/frontend/src/components/views/HNSView.tsx b/frontend/src/tabs/hns/components/HNSView.tsx similarity index 98% rename from frontend/src/components/views/HNSView.tsx rename to frontend/src/tabs/hns/components/HNSView.tsx index d13ab75..572c28d 100755 --- a/frontend/src/components/views/HNSView.tsx +++ b/frontend/src/tabs/hns/components/HNSView.tsx @@ -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 매뉴얼 뷰어 컴포넌트 ─── */ diff --git a/frontend/src/tabs/hns/index.ts b/frontend/src/tabs/hns/index.ts new file mode 100644 index 0000000..a413011 --- /dev/null +++ b/frontend/src/tabs/hns/index.ts @@ -0,0 +1 @@ +export { HNSView } from './components/HNSView' diff --git a/frontend/src/components/incidents/IncidentTable.tsx b/frontend/src/tabs/incidents/components/IncidentTable.tsx similarity index 100% rename from frontend/src/components/incidents/IncidentTable.tsx rename to frontend/src/tabs/incidents/components/IncidentTable.tsx diff --git a/frontend/src/components/incidents/IncidentsLeftPanel.tsx b/frontend/src/tabs/incidents/components/IncidentsLeftPanel.tsx similarity index 100% rename from frontend/src/components/incidents/IncidentsLeftPanel.tsx rename to frontend/src/tabs/incidents/components/IncidentsLeftPanel.tsx diff --git a/frontend/src/components/incidents/IncidentsRightPanel.tsx b/frontend/src/tabs/incidents/components/IncidentsRightPanel.tsx similarity index 100% rename from frontend/src/components/incidents/IncidentsRightPanel.tsx rename to frontend/src/tabs/incidents/components/IncidentsRightPanel.tsx diff --git a/frontend/src/components/views/IncidentsView.tsx b/frontend/src/tabs/incidents/components/IncidentsView.tsx similarity index 99% rename from frontend/src/components/views/IncidentsView.tsx rename to frontend/src/tabs/incidents/components/IncidentsView.tsx index 71fbca4..9e3ab9f 100755 --- a/frontend/src/components/views/IncidentsView.tsx +++ b/frontend/src/tabs/incidents/components/IncidentsView.tsx @@ -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[] = [ diff --git a/frontend/src/components/incidents/MediaModal.tsx b/frontend/src/tabs/incidents/components/MediaModal.tsx similarity index 100% rename from frontend/src/components/incidents/MediaModal.tsx rename to frontend/src/tabs/incidents/components/MediaModal.tsx diff --git a/frontend/src/tabs/incidents/index.ts b/frontend/src/tabs/incidents/index.ts new file mode 100644 index 0000000..9a15c9b --- /dev/null +++ b/frontend/src/tabs/incidents/index.ts @@ -0,0 +1 @@ +export { IncidentsView } from './components/IncidentsView' diff --git a/frontend/src/services/vesselService.ts b/frontend/src/tabs/incidents/services/vesselService.ts similarity index 100% rename from frontend/src/services/vesselService.ts rename to frontend/src/tabs/incidents/services/vesselService.ts diff --git a/frontend/src/components/analysis/AnalysisListTable.tsx b/frontend/src/tabs/prediction/components/AnalysisListTable.tsx similarity index 100% rename from frontend/src/components/analysis/AnalysisListTable.tsx rename to frontend/src/tabs/prediction/components/AnalysisListTable.tsx diff --git a/frontend/src/components/analysis/BacktrackModal.tsx b/frontend/src/tabs/prediction/components/BacktrackModal.tsx similarity index 100% rename from frontend/src/components/analysis/BacktrackModal.tsx rename to frontend/src/tabs/prediction/components/BacktrackModal.tsx diff --git a/frontend/src/components/analysis/BoomDeploymentTheoryView.tsx b/frontend/src/tabs/prediction/components/BoomDeploymentTheoryView.tsx similarity index 100% rename from frontend/src/components/analysis/BoomDeploymentTheoryView.tsx rename to frontend/src/tabs/prediction/components/BoomDeploymentTheoryView.tsx diff --git a/frontend/src/components/layout/LeftPanel.tsx b/frontend/src/tabs/prediction/components/LeftPanel.tsx similarity index 99% rename from frontend/src/components/layout/LeftPanel.tsx rename to frontend/src/tabs/prediction/components/LeftPanel.tsx index 0122881..a3540a3 100755 --- a/frontend/src/components/layout/LeftPanel.tsx +++ b/frontend/src/tabs/prediction/components/LeftPanel.tsx @@ -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 diff --git a/frontend/src/components/analysis/OilSpillTheoryView.tsx b/frontend/src/tabs/prediction/components/OilSpillTheoryView.tsx similarity index 100% rename from frontend/src/components/analysis/OilSpillTheoryView.tsx rename to frontend/src/tabs/prediction/components/OilSpillTheoryView.tsx diff --git a/frontend/src/components/views/OilSpillView.tsx b/frontend/src/tabs/prediction/components/OilSpillView.tsx similarity index 97% rename from frontend/src/components/views/OilSpillView.tsx rename to frontend/src/tabs/prediction/components/OilSpillView.tsx index afb5a8d..b9f74ab 100755 --- a/frontend/src/components/views/OilSpillView.tsx +++ b/frontend/src/tabs/prediction/components/OilSpillView.tsx @@ -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 diff --git a/frontend/src/components/analysis/RecalcModal.tsx b/frontend/src/tabs/prediction/components/RecalcModal.tsx similarity index 99% rename from frontend/src/components/analysis/RecalcModal.tsx rename to frontend/src/tabs/prediction/components/RecalcModal.tsx index 664484e..6e033d4 100755 --- a/frontend/src/components/analysis/RecalcModal.tsx +++ b/frontend/src/tabs/prediction/components/RecalcModal.tsx @@ -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 diff --git a/frontend/src/components/layout/RightPanel.tsx b/frontend/src/tabs/prediction/components/RightPanel.tsx similarity index 100% rename from frontend/src/components/layout/RightPanel.tsx rename to frontend/src/tabs/prediction/components/RightPanel.tsx diff --git a/frontend/src/tabs/prediction/index.ts b/frontend/src/tabs/prediction/index.ts new file mode 100644 index 0000000..bba2193 --- /dev/null +++ b/frontend/src/tabs/prediction/index.ts @@ -0,0 +1 @@ +export { OilSpillView } from './components/OilSpillView' diff --git a/frontend/src/components/reports/OilSpillReportTemplate.tsx b/frontend/src/tabs/reports/components/OilSpillReportTemplate.tsx similarity index 100% rename from frontend/src/components/reports/OilSpillReportTemplate.tsx rename to frontend/src/tabs/reports/components/OilSpillReportTemplate.tsx diff --git a/frontend/src/components/views/ReportsView.tsx b/frontend/src/tabs/reports/components/ReportsView.tsx similarity index 99% rename from frontend/src/components/views/ReportsView.tsx rename to frontend/src/tabs/reports/components/ReportsView.tsx index c6e6446..3941bdd 100755 --- a/frontend/src/components/views/ReportsView.tsx +++ b/frontend/src/tabs/reports/components/ReportsView.tsx @@ -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' diff --git a/frontend/src/tabs/reports/index.ts b/frontend/src/tabs/reports/index.ts new file mode 100644 index 0000000..5ba33c4 --- /dev/null +++ b/frontend/src/tabs/reports/index.ts @@ -0,0 +1 @@ +export { ReportsView } from './components/ReportsView' diff --git a/frontend/src/components/analysis/RescueScenarioView.tsx b/frontend/src/tabs/rescue/components/RescueScenarioView.tsx similarity index 100% rename from frontend/src/components/analysis/RescueScenarioView.tsx rename to frontend/src/tabs/rescue/components/RescueScenarioView.tsx diff --git a/frontend/src/components/analysis/RescueTheoryView.tsx b/frontend/src/tabs/rescue/components/RescueTheoryView.tsx similarity index 100% rename from frontend/src/components/analysis/RescueTheoryView.tsx rename to frontend/src/tabs/rescue/components/RescueTheoryView.tsx diff --git a/frontend/src/components/views/RescueView.tsx b/frontend/src/tabs/rescue/components/RescueView.tsx similarity index 99% rename from frontend/src/components/views/RescueView.tsx rename to frontend/src/tabs/rescue/components/RescueView.tsx index 764dfdf..2f890f2 100755 --- a/frontend/src/components/views/RescueView.tsx +++ b/frontend/src/tabs/rescue/components/RescueView.tsx @@ -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' diff --git a/frontend/src/tabs/rescue/index.ts b/frontend/src/tabs/rescue/index.ts new file mode 100644 index 0000000..adfd9eb --- /dev/null +++ b/frontend/src/tabs/rescue/index.ts @@ -0,0 +1 @@ +export { RescueView } from './components/RescueView' diff --git a/frontend/src/components/views/PreScatView.tsx b/frontend/src/tabs/scat/components/PreScatView.tsx similarity index 100% rename from frontend/src/components/views/PreScatView.tsx rename to frontend/src/tabs/scat/components/PreScatView.tsx diff --git a/frontend/src/components/weather/OceanCurrentLayer.tsx b/frontend/src/tabs/weather/components/OceanCurrentLayer.tsx similarity index 100% rename from frontend/src/components/weather/OceanCurrentLayer.tsx rename to frontend/src/tabs/weather/components/OceanCurrentLayer.tsx diff --git a/frontend/src/components/weather/OceanForecastOverlay.tsx b/frontend/src/tabs/weather/components/OceanForecastOverlay.tsx similarity index 95% rename from frontend/src/components/weather/OceanForecastOverlay.tsx rename to frontend/src/tabs/weather/components/OceanForecastOverlay.tsx index e34b530..c4a7585 100755 --- a/frontend/src/components/weather/OceanForecastOverlay.tsx +++ b/frontend/src/tabs/weather/components/OceanForecastOverlay.tsx @@ -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 diff --git a/frontend/src/components/weather/WaterTemperatureLayer.tsx b/frontend/src/tabs/weather/components/WaterTemperatureLayer.tsx similarity index 100% rename from frontend/src/components/weather/WaterTemperatureLayer.tsx rename to frontend/src/tabs/weather/components/WaterTemperatureLayer.tsx diff --git a/frontend/src/components/weather/WeatherMapOverlay.tsx b/frontend/src/tabs/weather/components/WeatherMapOverlay.tsx similarity index 100% rename from frontend/src/components/weather/WeatherMapOverlay.tsx rename to frontend/src/tabs/weather/components/WeatherMapOverlay.tsx diff --git a/frontend/src/components/weather/WeatherRightPanel.tsx b/frontend/src/tabs/weather/components/WeatherRightPanel.tsx similarity index 100% rename from frontend/src/components/weather/WeatherRightPanel.tsx rename to frontend/src/tabs/weather/components/WeatherRightPanel.tsx diff --git a/frontend/src/components/views/WeatherView.tsx b/frontend/src/tabs/weather/components/WeatherView.tsx similarity index 97% rename from frontend/src/components/views/WeatherView.tsx rename to frontend/src/tabs/weather/components/WeatherView.tsx index 811f7b5..c9b8339 100755 --- a/frontend/src/components/views/WeatherView.tsx +++ b/frontend/src/tabs/weather/components/WeatherView.tsx @@ -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' diff --git a/frontend/src/components/weather/WindParticleLayer.tsx b/frontend/src/tabs/weather/components/WindParticleLayer.tsx similarity index 100% rename from frontend/src/components/weather/WindParticleLayer.tsx rename to frontend/src/tabs/weather/components/WindParticleLayer.tsx diff --git a/frontend/src/hooks/useOceanForecast.ts b/frontend/src/tabs/weather/hooks/useOceanForecast.ts similarity index 100% rename from frontend/src/hooks/useOceanForecast.ts rename to frontend/src/tabs/weather/hooks/useOceanForecast.ts diff --git a/frontend/src/hooks/useWeatherData.ts b/frontend/src/tabs/weather/hooks/useWeatherData.ts similarity index 100% rename from frontend/src/hooks/useWeatherData.ts rename to frontend/src/tabs/weather/hooks/useWeatherData.ts diff --git a/frontend/src/tabs/weather/index.ts b/frontend/src/tabs/weather/index.ts new file mode 100644 index 0000000..e4dd76d --- /dev/null +++ b/frontend/src/tabs/weather/index.ts @@ -0,0 +1 @@ +export { WeatherView } from './components/WeatherView' diff --git a/frontend/src/services/khoaApi.ts b/frontend/src/tabs/weather/services/khoaApi.ts similarity index 100% rename from frontend/src/services/khoaApi.ts rename to frontend/src/tabs/weather/services/khoaApi.ts diff --git a/frontend/src/services/weatherApi.ts b/frontend/src/tabs/weather/services/weatherApi.ts similarity index 100% rename from frontend/src/services/weatherApi.ts rename to frontend/src/tabs/weather/services/weatherApi.ts diff --git a/frontend/src/services/weatherService.ts b/frontend/src/tabs/weather/services/weatherService.ts similarity index 100% rename from frontend/src/services/weatherService.ts rename to frontend/src/tabs/weather/services/weatherService.ts -- 2.45.2