3d508b6be9
Switch the 2D map sidebar from single-spacecraft selection to per-spacecraft visibility toggles, add a show-all action, and update map tab labels and styles for the all-spacecraft view.
118 lines
4.7 KiB
TypeScript
118 lines
4.7 KiB
TypeScript
import type { TguPlatformUi } from "../../model/timelineTypes";
|
||
import { filterPlatforms, platformLabel } from "../tgu-planning/tguTimelineMapper";
|
||
import { TGU_2D_MAP_LAYERS, type Tgu2DMapLayerKey, type Tgu2DMapLayersState } from "./model/mapLayerTypes";
|
||
import type { Tgu2DMapLayerAvailability } from "./Tgu2DMapLayers";
|
||
|
||
type Tgu2DMapSidebarProps = {
|
||
platforms: TguPlatformUi[];
|
||
selectedPlanId?: string;
|
||
hiddenIds: ReadonlySet<string>;
|
||
layers: Tgu2DMapLayersState;
|
||
search: string;
|
||
layerAvailability: Tgu2DMapLayerAvailability;
|
||
onSearchChange: (value: string) => void;
|
||
onToggleSpacecraft: (id: string) => void;
|
||
onShowAll: () => void;
|
||
onToggleLayer: (key: Tgu2DMapLayerKey) => void;
|
||
};
|
||
|
||
export function Tgu2DMapSidebar({
|
||
platforms,
|
||
selectedPlanId,
|
||
hiddenIds,
|
||
layers,
|
||
search,
|
||
layerAvailability,
|
||
onSearchChange,
|
||
onToggleSpacecraft,
|
||
onShowAll,
|
||
onToggleLayer
|
||
}: Tgu2DMapSidebarProps) {
|
||
const filteredPlatforms = filterPlatforms(platforms, search);
|
||
const hiddenCount = hiddenIds.size;
|
||
|
||
return (
|
||
<aside className="tgu-map-panel">
|
||
<div className="tgu-panel-heading">
|
||
<span>Карта 2D</span>
|
||
{hiddenCount > 0 && (
|
||
<button className="tgu-link-button" type="button" onClick={onShowAll}>
|
||
Показать все ({hiddenCount} скрыто)
|
||
</button>
|
||
)}
|
||
</div>
|
||
<div className="tgu-map-panel__section">
|
||
<div className="tgu-map-panel__label">Выбранный план</div>
|
||
<div className="tgu-map-panel__value mono">{selectedPlanId || "-"}</div>
|
||
</div>
|
||
<div className="tgu-map-panel__section">
|
||
<div className="tgu-map-panel__label">Слои</div>
|
||
<div className="tgu-map-layer-list">
|
||
{TGU_2D_MAP_LAYERS.map((layer) => (
|
||
<label className="tgu-map-layer" key={layer.key}>
|
||
<input type="checkbox" checked={layers[layer.key]} onChange={() => onToggleLayer(layer.key)} />
|
||
<span>
|
||
<span className="tgu-map-layer__title">{layer.label}</span>
|
||
<span className="tgu-map-layer__description">{layer.description}</span>
|
||
{layers[layer.key] && layerAvailability[layer.key] && (
|
||
<span className="tgu-map-layer__warning">{layerAvailability[layer.key]}</span>
|
||
)}
|
||
</span>
|
||
</label>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="tgu-map-panel__section">
|
||
<div className="tgu-map-panel__label">Космические аппараты</div>
|
||
<div className="tgu-search">
|
||
<input
|
||
type="search"
|
||
placeholder="Поиск name / NORAD / mission"
|
||
value={search}
|
||
onChange={(event) => onSearchChange(event.target.value)}
|
||
/>
|
||
</div>
|
||
<div className="tgu-map-spacecraft-list">
|
||
{filteredPlatforms.map((platform) => {
|
||
const visible = !hiddenIds.has(platform.spacecraftId);
|
||
return (
|
||
<label
|
||
className={`tgu-map-spacecraft ${visible ? "" : "is-hidden"}`}
|
||
key={platform.spacecraftId}
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
checked={visible}
|
||
onChange={() => onToggleSpacecraft(platform.spacecraftId)}
|
||
/>
|
||
<span>
|
||
<span className="tgu-map-spacecraft__name">{platformLabel(platform, platform.spacecraftId)}</span>
|
||
<span className="tgu-map-spacecraft__meta">
|
||
NORAD {platform.noradId || platform.spacecraftId}
|
||
{platform.mission ? ` · ${platform.mission}` : ""}
|
||
</span>
|
||
</span>
|
||
<span className="tgu-spacecraft__count">{platform.planCount}</span>
|
||
</label>
|
||
);
|
||
})}
|
||
{filteredPlatforms.length === 0 && <div className="tgu-empty tgu-empty--compact">Нет КА по текущему поиску.</div>}
|
||
</div>
|
||
</div>
|
||
<div className="tgu-map-panel__section">
|
||
<div className="tgu-map-panel__label">Статусы планов</div>
|
||
<div className="tgu-map-status-legend">
|
||
<span><i className="status-accepted" />ACCEPTED</span>
|
||
<span><i className="status-rejected" />REJECTED</span>
|
||
<span><i className="status-waiting" />WAITING_DECISION</span>
|
||
<span><i className="status-planned" />PLANNED</span>
|
||
<span><i className="status-issuing" />ISSUING</span>
|
||
<span><i className="status-expired" />EXPIRED</span>
|
||
<span><i className="status-superseded" />SUPERSEDED</span>
|
||
<span><i className="status-ambiguous" />START_AMBIGUOUS</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
);
|
||
}
|