187 lines
5.8 KiB
TypeScript
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;
|
|
}; |