WhiteNightsAdminPanel/src/preview/components/route-preview/mappers/mapRouteFromApi.ts

142 lines
3.7 KiB
TypeScript

import { MapData, StationOnMap } from "@mt/components";
import { TEMP_STATION_TYPE_MAP } from "@mt/common-types";
import {
Coordinates,
Route,
RouteStation,
Station,
Track,
TransferStation,
} from "@mt/common-types";
export function mapRouteFromApi(
routeData: Route,
stations: Station[]
): MapData {
const {
generalInfo,
attractionGroupings,
stations: routeStations,
} = routeData;
const { rotate, scale1, scale2, centerCoordinates, track } = generalInfo;
return {
mapRotateAngle: rotate,
fullMapScale: scale1,
zoomedMapScale: scale2,
centerOfMapPoint: centerCoordinates,
trackPoints: track,
stationsOnMap: mapStationsFromApi(routeStations, stations, track),
touristAttractionGroupsOnMap: attractionGroupings
.filter(({ coordinates }) => Boolean(coordinates))
.map(({ iconSize, coordinates, attractionIds }) => ({
iconSize,
pointOnMap: coordinates,
touristAttractionsOnMap: attractionIds.map((id) => ({
id,
pointOnMap: coordinates,
})),
})),
};
}
function mapStationsFromApi(
routeStations: RouteStation[],
stations: Station[],
track: Track
): MapData["stationsOnMap"] {
const stationsMap = new Map(stations.map((station) => [station.id, station]));
const unionStations: Array<Omit<RouteStation, "stationId"> & Station> =
routeStations.map(({ stationId, ...station }) => ({
...station,
...stationsMap.get(stationId),
}));
const mappedStations = unionStations.map((station) => {
const {
id,
name,
shortName,
coordinates,
textAlignment,
mapOffsets,
stationTypeId,
transferStations,
iconUrl,
} = station;
return {
id,
name,
shortName,
coordinates,
transferStationInfos: mapTransfersToMap(transferStations, stationsMap),
labelAlignment: textAlignment,
labelOffset: mapOffsets,
iconUrl,
stationTypeId,
};
});
const stationsOnMap = mappedStations.map((station) => {
const { coordinates } = station;
const trackIndex = track.findIndex(
(trackPoint) =>
coordinates.lat === trackPoint.lat && coordinates.lon === trackPoint.lon
);
return {
...station,
pointOnMap: {
...coordinates,
trackIndex,
},
};
}) as MapData["stationsOnMap"];
return sortStationsByTrackOrder(track, stationsOnMap);
}
function sortStationsByTrackOrder(
track: Track,
stations: StationOnMap[]
): StationOnMap[] {
// Create a map to store the index of each coordinate in the second array
const coordinateIndexMap = new Map<string, number>();
track.forEach((coordinate, index) => {
coordinateIndexMap.set(getCoordinateString(coordinate), index);
});
// Sort the first array based on the order of coordinates in the second array
return [...stations].sort((a, b) => {
const indexA =
coordinateIndexMap.get(getCoordinateString(a.coordinates)) || 0;
const indexB =
coordinateIndexMap.get(getCoordinateString(b.coordinates)) || 0;
return indexA - indexB;
});
}
// TODO: move to shared utils and refactor across the project
function getCoordinateString(coordinate: Coordinates): string {
return `${coordinate.lat}:${coordinate.lon}`;
}
function mapTransfersToMap(
transferStations: TransferStation[],
stationsMap: Map<string, Station>
) {
return transferStations
.filter(({ isShowOnMap }) => isShowOnMap)
.sort(({ ordinal: ordinalA }, { ordinal: ordinalB }) => ordinalA - ordinalB)
.map(({ stationId }) => {
const { stationTypeId, shortName } = stationsMap.get(stationId);
return {
type: TEMP_STATION_TYPE_MAP[stationTypeId].type,
name: shortName,
};
});
}