diff --git a/frontend/src/components/korea/CorrelationPanel.tsx b/frontend/src/components/korea/CorrelationPanel.tsx index 413ac59..62b81ab 100644 --- a/frontend/src/components/korea/CorrelationPanel.tsx +++ b/frontend/src/components/korea/CorrelationPanel.tsx @@ -6,6 +6,8 @@ import type { UseGroupPolygonsResult } from '../../hooks/useGroupPolygons'; import { FONT_MONO } from '../../styles/fonts'; import { MODEL_ORDER, MODEL_COLORS, MODEL_DESC } from './fleetClusterConstants'; import { useGearReplayStore } from '../../stores/gearReplayStore'; +import { useTranslation } from 'react-i18next'; +import { useReplayCenterPanelLayout } from './useReplayCenterPanelLayout'; interface CorrelationPanelProps { selectedGearGroup: string; @@ -17,6 +19,8 @@ interface CorrelationPanelProps { enabledVessels: Set; correlationLoading: boolean; hoveredTarget: { mmsi: string; model: string } | null; + hasRightReviewPanel?: boolean; + reviewDriven?: boolean; onEnabledModelsChange: (updater: (prev: Set) => Set) => void; onEnabledVesselsChange: (updater: (prev: Set) => Set) => void; onHoveredTargetChange: (target: { mmsi: string; model: string } | null) => void; @@ -35,11 +39,19 @@ const CorrelationPanel = ({ enabledVessels, correlationLoading, hoveredTarget, + hasRightReviewPanel = false, + reviewDriven = false, onEnabledModelsChange, onEnabledVesselsChange, onHoveredTargetChange, }: CorrelationPanelProps) => { + const { t } = useTranslation(); const historyActive = useGearReplayStore(s => s.historyFrames.length > 0); + const layout = useReplayCenterPanelLayout({ + minWidth: 252, + maxWidth: 966, + hasRightReviewPanel, + }); // Local tooltip state const [hoveredModelTip, setHoveredModelTip] = useState(null); @@ -193,16 +205,30 @@ const CorrelationPanel = ({ key={`${modelName}-${c.targetMmsi}`} style={{ fontSize: 9, marginBottom: 1, display: 'flex', alignItems: 'center', gap: 3, - padding: '1px 2px', borderRadius: 2, cursor: 'pointer', + padding: '1px 2px', borderRadius: 2, cursor: reviewDriven ? 'default' : 'pointer', background: isHovered ? `${color}22` : 'transparent', - opacity: isEnabled ? 1 : 0.5, + opacity: reviewDriven ? 1 : isEnabled ? 1 : 0.5, }} - onClick={() => toggleVessel(c.targetMmsi)} - onMouseEnter={() => onHoveredTargetChange({ mmsi: c.targetMmsi, model: modelName })} - onMouseLeave={() => onHoveredTargetChange(null)} + onClick={reviewDriven ? undefined : () => toggleVessel(c.targetMmsi)} + onMouseEnter={reviewDriven ? undefined : () => onHoveredTargetChange({ mmsi: c.targetMmsi, model: modelName })} + onMouseLeave={reviewDriven ? undefined : () => onHoveredTargetChange(null)} > - + {reviewDriven ? ( + + ) : ( + + )} {isVessel ? '⛴' : '◆'} @@ -219,6 +245,15 @@ const CorrelationPanel = ({ ); }; + const visibleModelNames = useMemo(() => { + if (reviewDriven) { + return availableModels + .filter(model => (correlationByModel.get(model.name) ?? []).length > 0) + .map(model => model.name); + } + return availableModels.filter(model => enabledModels.has(model.name)).map(model => model.name); + }, [availableModels, correlationByModel, enabledModels, reviewDriven]); + // Member row renderer (identity model — no score, independent hover) const renderMemberRow = (m: { mmsi: string; name: string }, icon: string, iconColor: string, keyPrefix = 'id') => { const isHovered = hoveredTarget?.mmsi === m.mmsi && hoveredTarget?.model === 'identity'; @@ -251,10 +286,8 @@ const CorrelationPanel = ({
{selectedGearGroup} {memberCount}개
+
+ {reviewDriven + ? t('parentInference.reference.reviewDriven') + : t('parentInference.reference.shipOnly')} +
폴리곤 오버레이