116 lines
3.6 KiB
TypeScript
116 lines
3.6 KiB
TypeScript
"use client";
|
|
import React, { createContext, useCallback, useContext, useEffect, useState } from "react";
|
|
import { useSession } from "next-auth/react";
|
|
import { config, NETWORK_NAME, setMapWorkspace, setNetworkName, setMapExtent } from "@/config/config";
|
|
import { ProjectSelector } from "@/components/project/ProjectSelector";
|
|
import { apiFetch } from "@/lib/apiFetch";
|
|
import { useProjectStore } from "@/store/projectStore";
|
|
|
|
interface ProjectContextType {
|
|
workspace: string;
|
|
networkName: string;
|
|
extent: number[];
|
|
}
|
|
|
|
const ProjectContext = createContext<ProjectContextType | undefined>(undefined);
|
|
|
|
export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
children,
|
|
}) => {
|
|
const { status } = useSession();
|
|
const [isConfigured, setIsConfigured] = useState(false);
|
|
const setCurrentProjectId = useProjectStore(
|
|
(state) => state.setCurrentProjectId,
|
|
);
|
|
const [currentProject, setCurrentProject] = useState({
|
|
workspace: config.MAP_WORKSPACE,
|
|
networkName: NETWORK_NAME || "tjwater",
|
|
extent: config.MAP_EXTENT,
|
|
});
|
|
|
|
const applyConfig = useCallback(async (
|
|
projectId: string,
|
|
ws: string,
|
|
net: string,
|
|
extent: number[],
|
|
) => {
|
|
const resolvedProjectId = projectId || net || ws;
|
|
setMapWorkspace(ws);
|
|
setNetworkName(net);
|
|
setMapExtent(extent);
|
|
localStorage.setItem("NEXT_PUBLIC_MAP_EXTENT", extent.join(","));
|
|
// Reset extent cache
|
|
localStorage.removeItem(`${ws}_map_view`);
|
|
setCurrentProject({ workspace: ws, networkName: net, extent: extent });
|
|
setCurrentProjectId(resolvedProjectId);
|
|
|
|
// Save to localStorage
|
|
localStorage.setItem("NEXT_PUBLIC_MAP_WORKSPACE", ws);
|
|
localStorage.setItem("NEXT_PUBLIC_NETWORK_NAME", net);
|
|
|
|
setIsConfigured(true);
|
|
|
|
try {
|
|
const response = await apiFetch(
|
|
`${config.BACKEND_URL}/openproject/?network=${net}`,
|
|
{
|
|
method: "POST",
|
|
},
|
|
);
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}`);
|
|
}
|
|
const data = await response.json();
|
|
const bbox = Array.isArray(data?.map_extent?.bbox)
|
|
? data.map_extent.bbox.map((value: number) => Number(value))
|
|
: null;
|
|
if (bbox && bbox.length === 4) {
|
|
setMapExtent(bbox);
|
|
localStorage.setItem("NEXT_PUBLIC_MAP_EXTENT", bbox.join(","));
|
|
localStorage.removeItem(`${ws}_map_view`);
|
|
setCurrentProject((prev) => ({ ...prev, extent: bbox }));
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to open project:", error);
|
|
}
|
|
}, [setCurrentProjectId]);
|
|
|
|
useEffect(() => {
|
|
// Check localStorage
|
|
const savedWorkspace = localStorage.getItem("NEXT_PUBLIC_MAP_WORKSPACE");
|
|
const savedNetwork = localStorage.getItem("NEXT_PUBLIC_NETWORK_NAME");
|
|
const savedExtent = localStorage.getItem("NEXT_PUBLIC_MAP_EXTENT");
|
|
const savedProjectId = localStorage.getItem("active_project");
|
|
|
|
// If we have saved config, use it.
|
|
if (savedWorkspace && savedNetwork) {
|
|
applyConfig(
|
|
savedProjectId || savedNetwork || savedWorkspace,
|
|
savedWorkspace,
|
|
savedNetwork,
|
|
savedExtent ? savedExtent.split(",").map(Number) : config.MAP_EXTENT,
|
|
);
|
|
}
|
|
}, [applyConfig]);
|
|
|
|
// Only show selector if authenticated and not configured
|
|
if (status === "authenticated" && !isConfigured) {
|
|
return (
|
|
<ProjectSelector
|
|
open={true}
|
|
onSelect={(projectId, ws, net, extent) =>
|
|
applyConfig(projectId, ws, net, extent)
|
|
}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ProjectContext.Provider value={currentProject}>
|
|
{children}
|
|
</ProjectContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useProject = () => useContext(ProjectContext);
|