refactor(frontend): detection 계열 PageContainer/PageHeader 적용

- DarkVesselDetection: icon=EyeOff color=red
- GearDetection: icon=Anchor color=orange
- ChinaFishing: PageContainer size=sm (tab 기반 멀티뷰 루트)

GearIdentification/RealVesselAnalysis/RealGearGroups는 ChinaFishing의 서브
컴포넌트라 독립 마이그레이션 불필요.
This commit is contained in:
htlee 2026-04-08 11:51:32 +09:00
부모 4ee8f05dfd
커밋 a1c521792d
3개의 변경된 파일21개의 추가작업 그리고 16개의 파일을 삭제

파일 보기

@ -1,6 +1,7 @@
import { useState, useEffect, useMemo, useCallback } from 'react';
import { Card, CardContent } from '@shared/components/ui/card';
import { Badge } from '@shared/components/ui/badge';
import { PageContainer } from '@shared/components/layout';
import {
Search, Ship, Clock, ChevronRight, ChevronLeft, Cloud,
Eye, AlertTriangle, Radio, RotateCcw,
@ -287,7 +288,7 @@ export function ChinaFishing() {
];
return (
<div className="space-y-3">
<PageContainer size="sm">
{/* ── 모드 탭 (AI 대시보드 / 환적 탐지) ── */}
<div className="flex items-center gap-1 bg-surface-raised rounded-lg p-1 border border-slate-700/30 w-fit">
{modeTabs.map((tab) => (
@ -677,6 +678,6 @@ export function ChinaFishing() {
</div>
</>}
</div>
</PageContainer>
);
}

파일 보기

@ -2,6 +2,7 @@ import { useEffect, useState, useMemo, useRef, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Card, CardContent } from '@shared/components/ui/card';
import { Badge } from '@shared/components/ui/badge';
import { PageContainer, PageHeader } from '@shared/components/layout';
import { DataTable, type DataColumn } from '@shared/components/common/DataTable';
import { EyeOff, AlertTriangle, Radio, Tag, Loader2 } from 'lucide-react';
import { BaseMap, STATIC_LAYERS, createMarkerLayer, createRadiusLayer, useMapLayers, type MapHandle } from '@lib/map';
@ -147,13 +148,13 @@ export function DarkVesselDetection() {
useMapLayers(mapRef, buildLayers, [DATA]);
return (
<div className="p-5 space-y-4">
<div className="flex items-center justify-between">
<div>
<h2 className="text-lg font-bold text-heading whitespace-nowrap flex items-center gap-2"><EyeOff className="w-5 h-5 text-red-400" />{t('darkVessel.title')}</h2>
<p className="text-[10px] text-hint mt-0.5">{t('darkVessel.desc')}</p>
</div>
</div>
<PageContainer>
<PageHeader
icon={EyeOff}
iconColor="text-red-400"
title={t('darkVessel.title')}
description={t('darkVessel.desc')}
/>
{!serviceAvailable && (
<div className="flex items-center gap-2 px-4 py-3 rounded-lg border border-yellow-500/30 bg-yellow-500/5 text-yellow-400 text-xs">
@ -216,6 +217,6 @@ export function DarkVesselDetection() {
</div>
</CardContent>
</Card>
</div>
</PageContainer>
);
}

파일 보기

@ -2,6 +2,7 @@ import { useEffect, useState, useMemo, useRef, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Card, CardContent } from '@shared/components/ui/card';
import { Badge } from '@shared/components/ui/badge';
import { PageContainer, PageHeader } from '@shared/components/layout';
import { DataTable, type DataColumn } from '@shared/components/common/DataTable';
import { Anchor, AlertTriangle, Loader2 } from 'lucide-react';
import { BaseMap, STATIC_LAYERS, createMarkerLayer, createRadiusLayer, useMapLayers, type MapHandle } from '@lib/map';
@ -131,11 +132,13 @@ export function GearDetection() {
useMapLayers(mapRef, buildLayers, [DATA]);
return (
<div className="p-5 space-y-4">
<div>
<h2 className="text-lg font-bold text-heading whitespace-nowrap flex items-center gap-2"><Anchor className="w-5 h-5 text-orange-400" />{t('gearDetection.title')}</h2>
<p className="text-[10px] text-hint mt-0.5">{t('gearDetection.desc')}</p>
</div>
<PageContainer>
<PageHeader
icon={Anchor}
iconColor="text-orange-400"
title={t('gearDetection.title')}
description={t('gearDetection.desc')}
/>
{!serviceAvailable && (
<div className="flex items-center gap-2 px-4 py-3 rounded-lg border border-yellow-500/30 bg-yellow-500/5 text-yellow-400 text-xs">
@ -193,6 +196,6 @@ export function GearDetection() {
</div>
</CardContent>
</Card>
</div>
</PageContainer>
);
}