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(); const [originalStationData, setOriginalStationData] = useState(); const [originalSightData, setOriginalSightData] = useState(); const [routeData, setRouteData] = useState(); const [stationData, setStationData] = useState(); const [sightData, setSightData] = useState(); const [routeChanges, setRouteChanges] = useState({} as RouteData); const [stationChanges, setStationChanges] = useState([]); const [sightChanges, setSightChanges] = useState([]); 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 ( {children} ); } export const useMapData = () => { const context = useContext(MapDataContext); if (!context) { throw new Error('useMapData must be used within a MapDataProvider'); } return context; };