WhiteNightsAdminPanel/src/pages/route-preview/MapDataContext.tsx
2025-05-03 01:17:37 +03:00

187 lines
5.8 KiB
TypeScript

import { useCustom, useShow, useApiUrl } from "@refinedev/core";
import { useParams } from "react-router";
import { createContext, ReactNode, useContext, useEffect, useMemo, useState } from "react";
import { RouteData, SightData, StationData, StationPatchData } from "./types";
import { axiosInstance } from "../../providers/data";
const MapDataContext = createContext<{
originalRouteData?: RouteData,
originalStationData?: StationData[],
originalSightData?: SightData[],
routeData?: RouteData,
stationData?: StationData[],
sightData?: SightData[],
isRouteLoading: boolean,
isStationLoading: boolean,
isSightLoading: boolean,
setScaleRange: (min: number, max: number) => void,
setMapRotation: (rotation: number) => void,
setMapCenter: (x: number, y: number) => void,
setStationOffset: (stationId: number, x: number, y: number) => void,
saveChanges: () => void,
}>({
originalRouteData: undefined,
originalStationData: undefined,
originalSightData: undefined,
routeData: undefined,
stationData: undefined,
sightData: undefined,
isRouteLoading: true,
isStationLoading: true,
isSightLoading: true,
setScaleRange: () => {},
setMapRotation: () => {},
setMapCenter: () => {},
setStationOffset: () => {},
saveChanges: () => {},
});
export function MapDataProvider({ children }: Readonly<{ children: ReactNode }>) {
const { id: routeId } = useParams<{ id: string }>();
const apiUrl = useApiUrl();
const [originalRouteData, setOriginalRouteData] = useState<RouteData>();
const [originalStationData, setOriginalStationData] = useState<StationData[]>();
const [originalSightData, setOriginalSightData] = useState<SightData[]>();
const [routeData, setRouteData] = useState<RouteData>();
const [stationData, setStationData] = useState<StationData[]>();
const [sightData, setSightData] = useState<SightData[]>();
const [routeChanges, setRouteChanges] = useState<RouteData>({} as RouteData);
const [stationChanges, setStationChanges] = useState<StationPatchData[]>([]);
const [sightChanges, setSightChanges] = useState<SightData[]>([]);
const { data: routeQuery, isLoading: isRouteLoading } = useCustom({
url: `${apiUrl}/route/${routeId}`,
method: 'get',
});
const { data: stationQuery, isLoading: isStationLoading } = useCustom({
url: `${apiUrl}/route/${routeId}/station`,
method: 'get',
});
const { data: sightQuery, isLoading: isSightLoading } = useCustom({
url: `${apiUrl}/route/${routeId}/sight`,
method: 'get',
});
useEffect(() => {
// if not undefined, set original data
if(routeQuery?.data) setOriginalRouteData(routeQuery.data as RouteData);
if(stationQuery?.data) setOriginalStationData(stationQuery.data as StationData[]);
if(sightQuery?.data) setOriginalSightData(sightQuery.data as SightData[]);
console.log("queries", routeQuery, stationQuery, sightQuery);
}, [routeQuery, stationQuery, sightQuery]);
useEffect(() => {
// combine changes with original data
if(originalRouteData) setRouteData({...originalRouteData, ...routeChanges});
if(originalStationData) setStationData(originalStationData);
if(originalSightData) setSightData(originalSightData);
}, [
originalRouteData, originalStationData, originalSightData,
routeChanges, stationChanges, sightChanges
]);
useEffect(() => {
console.log("data", routeData, stationData, sightData);
}, [routeData, stationData, sightData]);
function setScaleRange(min: number, max: number) {
setRouteChanges((prev) => {
return {...prev, scale_min: min, scale_max: max};
});
}
function setMapRotation(rotation: number) {
setRouteChanges((prev) => {
return {...prev, rotate: rotation};
});
}
function setMapCenter(x: number, y: number) {
setRouteChanges((prev) => {
return {...prev, center_latitude: x, center_longitude: y}
});
}
async function saveChanges() {
console.log("saveChanges", routeData);
const response = await axiosInstance.patch(`/route/${routeId}`, routeData);
saveStationChanges();
}
async function saveStationChanges() {
console.log("saveStationChanges", stationChanges);
for(const station of stationChanges) {
const response = await axiosInstance.patch(`/route/${routeId}/station`, station);
console.log("response", response);
}
}
function setStationOffset(stationId: number, x: number, y: number) {
setStationChanges((prev) => {
let found = prev.find((station) => station.station_id === stationId);
if(found) {
found.offset_x = x;
found.offset_y = y;
return prev.map((station) => {
if(station.station_id === stationId) {
return found;
}
return station;
});
} else {
const foundStation = stationData?.find((station) => station.id === stationId);
if(foundStation) {
return [...prev, {
station_id: stationId,
offset_x: x, offset_y: y,
transfers: foundStation.transfers
}];
}
return prev;
}
});
}
useEffect(() => {
console.log("stationChanges", stationChanges);
}, [stationChanges]);
const value = useMemo(() => ({
originalRouteData: originalRouteData,
originalStationData: originalStationData,
originalSightData: originalSightData,
routeData: routeData,
stationData: stationData,
sightData: sightData,
isRouteLoading,
isStationLoading,
isSightLoading,
setScaleRange,
setMapRotation,
setMapCenter,
saveChanges,
setStationOffset,
}), [originalRouteData, originalStationData, originalSightData, routeData, stationData, sightData, isRouteLoading, isStationLoading, isSightLoading]);
return (
<MapDataContext.Provider value={value}>
{children}
</MapDataContext.Provider>
);
}
export const useMapData = () => {
const context = useContext(MapDataContext);
if (!context) {
throw new Error('useMapData must be used within a MapDataProvider');
}
return context;
};