wing-ops/frontend/src/tabs/prediction/components/InfoLayerSection.tsx
jeonghyo.k fbdf0e9122 refactor(prediction): layerColors 상태를 OilSpillView로 끌어올림
InfoLayerSection 내부 상태였던 layerColors를 OilSpillView에서
관리하도록 변경하여 MapView에 색상 정보를 전달할 수 있도록 함.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 22:31:08 +09:00

177 lines
6.2 KiB
TypeScript

import { LayerTree } from '@common/components/layer/LayerTree';
import { useLayerTree } from '@common/hooks/useLayers';
import type { Layer } from '@common/services/layerService';
interface InfoLayerSectionProps {
expanded: boolean;
onToggle: () => void;
enabledLayers: Set<string>;
onToggleLayer: (layerId: string, enabled: boolean) => void;
layerOpacity: number;
onLayerOpacityChange: (val: number) => void;
layerBrightness: number;
onLayerBrightnessChange: (val: number) => void;
layerColors: Record<string, string>;
onLayerColorChange: (layerId: string, color: string) => void;
}
const InfoLayerSection = ({
expanded,
onToggle,
enabledLayers,
onToggleLayer,
layerOpacity,
onLayerOpacityChange,
layerBrightness,
onLayerBrightnessChange,
layerColors,
onLayerColorChange,
}: InfoLayerSectionProps) => {
// API에서 레이어 트리 데이터 가져오기 (관리자 설정 USE_YN='Y' 레이어만 반환)
const { data: layerTree, isLoading } = useLayerTree();
// 관리자에서 사용여부가 ON인 레이어만 표시 (정적 폴백 없음)
const effectiveLayers: Layer[] = layerTree ?? [];
return (
<div className="border-b border-stroke">
<div className="flex items-center justify-between p-4 hover:bg-[rgba(255,255,255,0.02)]">
<h3
onClick={onToggle}
className="text-title-4 font-bold text-fg-sub font-korean cursor-pointer"
>
</h3>
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
<button
onClick={(e) => {
e.stopPropagation();
// Get all layer IDs from layerTree recursively
const getAllLayerIds = (layers: Layer[]): string[] => {
const ids: string[] = [];
layers?.forEach((layer) => {
ids.push(layer.id);
if (layer.children) {
ids.push(...getAllLayerIds(layer.children));
}
});
return ids;
};
const allIds = getAllLayerIds(effectiveLayers);
allIds.forEach((id) => onToggleLayer(id, true));
}}
style={{
padding: '4px 8px',
fontSize: 'var(--font-size-label-2)',
fontWeight: 500,
border: '1px solid var(--stroke-default)',
borderRadius: 'var(--radius-sm)',
background: 'transparent',
color: 'var(--fg-sub)',
cursor: 'pointer',
transition: '0.15s',
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = 'var(--bg-surface-hover)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = 'transparent';
}}
>
</button>
<button
onClick={(e) => {
e.stopPropagation();
// Get all layer IDs from layerTree recursively
const getAllLayerIds = (layers: Layer[]): string[] => {
const ids: string[] = [];
layers?.forEach((layer) => {
ids.push(layer.id);
if (layer.children) {
ids.push(...getAllLayerIds(layer.children));
}
});
return ids;
};
const allIds = getAllLayerIds(effectiveLayers);
allIds.forEach((id) => onToggleLayer(id, false));
}}
style={{
padding: '4px 8px',
fontSize: 'var(--font-size-label-2)',
fontWeight: 500,
border: '1px solid var(--stroke-default)',
borderRadius: 'var(--radius-sm)',
background: 'transparent',
color: 'var(--fg-sub)',
cursor: 'pointer',
transition: '0.15s',
}}
onMouseEnter={(e) => {
e.currentTarget.style.background = 'var(--bg-surface-hover)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = 'transparent';
}}
>
</button>
<span onClick={onToggle} className="text-label-2 text-fg-disabled cursor-pointer">
{expanded ? '▼' : '▶'}
</span>
</div>
</div>
{expanded && (
<div className="px-4 pb-2">
{isLoading && effectiveLayers.length === 0 ? (
<p className="text-label-2 text-fg-disabled py-2"> ...</p>
) : effectiveLayers.length === 0 ? (
<p className="text-label-2 text-fg-disabled py-2"> .</p>
) : (
<LayerTree
layers={effectiveLayers}
enabledLayers={enabledLayers}
onToggleLayer={onToggleLayer}
layerColors={layerColors}
onColorChange={onLayerColorChange}
/>
)}
{/* 레이어 스타일 조절 */}
<div className="lyr-style-box">
<div className="lyr-style-label"> </div>
<div className="lyr-style-row">
<span className="lyr-style-name"></span>
<input
type="range"
className="lyr-style-slider"
min={0}
max={100}
value={layerOpacity}
onChange={(e) => onLayerOpacityChange(Number(e.target.value))}
/>
<span className="lyr-style-val">{layerOpacity}%</span>
</div>
<div className="lyr-style-row">
<span className="lyr-style-name"></span>
<input
type="range"
className="lyr-style-slider"
min={0}
max={100}
value={layerBrightness}
onChange={(e) => onLayerBrightnessChange(Number(e.target.value))}
/>
<span className="lyr-style-val">{layerBrightness}%</span>
</div>
</div>
</div>
)}
</div>
);
};
export default InfoLayerSection;