Files
TJWaterFrontend_Refine/src/contexts/ProjectContext.tsx
T

143 lines
4.5 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 {
// Open project backend (simulation model)
const openResponse = await apiFetch(
`${config.BACKEND_URL}/api/v1/openproject/?network=${net}`,
{
method: "POST",
},
);
if (!openResponse.ok) {
throw new Error(`Failed to open project: HTTP ${openResponse.status}`);
}
// Fetch project metadata
const infoResponse = await apiFetch(
`${config.BACKEND_URL}/api/v1/project_info/?network=${net}`,
);
if (!infoResponse.ok) {
console.warn(
`Failed to fetch project info: HTTP ${infoResponse.status}`,
);
} else {
const data = await infoResponse.json();
// Update workspace if different
if (data?.gs_workspace && data.gs_workspace !== ws) {
setMapWorkspace(data.gs_workspace);
localStorage.setItem(
"NEXT_PUBLIC_MAP_WORKSPACE",
data.gs_workspace,
);
setCurrentProject((prev) => ({
...prev,
workspace: data.gs_workspace,
}));
}
// Update extent if available
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 setup 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);