177 lines
6.2 KiB
TypeScript
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-default 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-default cursor-pointer">
|
|
{expanded ? '▼' : '▶'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{expanded && (
|
|
<div className="px-4 pb-2">
|
|
{isLoading && effectiveLayers.length === 0 ? (
|
|
<p className="text-label-2 text-fg-default py-2">레이어 로딩 중...</p>
|
|
) : effectiveLayers.length === 0 ? (
|
|
<p className="text-label-2 text-fg-default 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;
|