diff --git a/frontend/src/components/korea/KoreaDashboard.tsx b/frontend/src/components/korea/KoreaDashboard.tsx index 84ec81b..a733c68 100644 --- a/frontend/src/components/korea/KoreaDashboard.tsx +++ b/frontend/src/components/korea/KoreaDashboard.tsx @@ -159,7 +159,6 @@ export const KoreaDashboard = ({ koreaData.visibleShips, currentTime, vesselAnalysis.analysisMap, - koreaLayers.cnFishing, ); const handleTabChange = useCallback((_tab: DashboardTab) => { @@ -198,8 +197,8 @@ export const KoreaDashboard = ({ onClick={() => koreaFiltersResult.setFilter('ferryWatch', !koreaFiltersResult.filters.ferryWatch)} title={t('filters.ferryWatch')}> ๐Ÿšข{t('filters.ferryWatch')} - + + - ); - })} - +
+ + + + + + + + + + + + {badgeShips.slice(0, 200).map(s => ( + setFlyToTarget({ lng: s.lng, lat: s.lat, zoom: 12 })} + > + + + + + + + ))} + +
MMSINameFlagTypeSpeed
{s.mmsi}{s.name || '-'}{s.flag || '??'}{s.mtCategory || '-'}{s.speed?.toFixed(1)}kn
+ {badgeShips.length > 200 &&
...์™ธ {badgeShips.length - 200}์ฒ™
} +
+ + )} + ); })()} diff --git a/frontend/src/hooks/useKoreaFilters.ts b/frontend/src/hooks/useKoreaFilters.ts index 5a7dcde..e5a679d 100644 --- a/frontend/src/hooks/useKoreaFilters.ts +++ b/frontend/src/hooks/useKoreaFilters.ts @@ -12,6 +12,7 @@ interface KoreaFilters { cableWatch: boolean; dokdoWatch: boolean; ferryWatch: boolean; + cnFishing: boolean; } interface DokdoAlert { @@ -28,6 +29,7 @@ interface UseKoreaFiltersResult { transshipSuspects: Set; cableWatchSuspects: Set; dokdoWatchSuspects: Set; + cnFishingSuspects: Set; dokdoAlerts: DokdoAlert[]; anyFilterOn: boolean; } @@ -43,7 +45,6 @@ export function useKoreaFilters( visibleShips: Ship[], currentTime: number, analysisMap?: Map, - cnFishingOn = false, ): UseKoreaFiltersResult { const [filters, setFilters] = useLocalStorage('koreaFilters', { illegalFishing: false, @@ -52,6 +53,7 @@ export function useKoreaFilters( cableWatch: false, dokdoWatch: false, ferryWatch: false, + cnFishing: false, }); const [dokdoAlerts, setDokdoAlerts] = useState([]); @@ -70,7 +72,7 @@ export function useKoreaFilters( filters.cableWatch || filters.dokdoWatch || filters.ferryWatch || - cnFishingOn; + filters.cnFishing; // ๋ถˆ๋ฒ•ํ™˜์  ์˜์‹ฌ ์„ ๋ฐ• ํƒ์ง€ (Python ๋ถ„์„ ๊ฒฐ๊ณผ ์†Œ๋น„) const transshipSuspects = useMemo(() => { @@ -250,6 +252,18 @@ export function useKoreaFilters( return result; }, [koreaShips, filters.dokdoWatch, currentTime]); + // ์ค‘๊ตญ์–ด์„  ์˜์‹ฌ ์„ ๋ฐ• Set + const cnFishingSuspects = useMemo(() => { + if (!filters.cnFishing) return new Set(); + const result = new Set(); + for (const s of koreaShips) { + const isCnFishing = s.flag === 'CN' && s.mtCategory === 'fishing'; + const isGearPattern = /^.+?_\d+_\d+_?$/.test(s.name || ''); + if (isCnFishing || isGearPattern) result.add(s.mmsi); + } + return result; + }, [filters.cnFishing, koreaShips]); + // ํ•„ํ„ฐ๋ง๋œ ์„ ๋ฐ• ๋ชฉ๋ก const filteredShips = useMemo(() => { if (!anyFilterOn) return visibleShips; @@ -272,14 +286,10 @@ export function useKoreaFilters( if (filters.cableWatch && cableWatchSet.has(s.mmsi)) return true; if (filters.dokdoWatch && dokdoWatchSet.has(s.mmsi)) return true; if (filters.ferryWatch && s.mtCategory === 'passenger') return true; - if (cnFishingOn) { - const isCnFishing = s.flag === 'CN' && s.mtCategory === 'fishing'; - const isGearPattern = /^.+?_\d+_\d+_?$/.test(s.name || ''); - if (isCnFishing || isGearPattern) return true; - } + if (filters.cnFishing && cnFishingSuspects.has(s.mmsi)) return true; return false; }); - }, [visibleShips, filters, anyFilterOn, transshipSuspects, darkVesselSet, cableWatchSet, dokdoWatchSet, analysisMap, cnFishingOn]); + }, [visibleShips, filters, anyFilterOn, transshipSuspects, darkVesselSet, cableWatchSet, dokdoWatchSet, analysisMap, cnFishingSuspects]); return { filters, @@ -288,6 +298,7 @@ export function useKoreaFilters( transshipSuspects, cableWatchSuspects: cableWatchSet, dokdoWatchSuspects: dokdoWatchSet, + cnFishingSuspects, dokdoAlerts, anyFilterOn, };