Implemented a Zustand-based project_id store, expanded project selection/switching to persist project_id,

and centralized backend requests via api/apiFetch (including data provider updates) to inject X-Project-ID.
This commit is contained in:
JIANG
2026-02-11 16:29:18 +08:00
parent a2e6c1f416
commit 9d06226cb4
25 changed files with 192 additions and 62 deletions
+19 -3
View File
@@ -3,6 +3,8 @@ import React, { createContext, 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;
@@ -17,6 +19,9 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
}) => {
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",
@@ -28,10 +33,12 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
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,
@@ -39,7 +46,13 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
}
}, []);
const applyConfig = async (ws: string, net: string, extent: number[]) => {
const applyConfig = async (
projectId: string,
ws: string,
net: string,
extent: number[],
) => {
const resolvedProjectId = projectId || net || ws;
setMapWorkspace(ws);
setNetworkName(net);
setMapExtent(extent);
@@ -47,6 +60,7 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
// 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);
@@ -55,7 +69,7 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
setIsConfigured(true);
try {
await fetch(`${config.BACKEND_URL}/openproject/?network=${net}`, {
await apiFetch(`${config.BACKEND_URL}/openproject/?network=${net}`, {
method: "POST",
});
} catch (error) {
@@ -68,7 +82,9 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
return (
<ProjectSelector
open={true}
onSelect={(ws, net, extent) => applyConfig(ws, net, extent)}
onSelect={(projectId, ws, net, extent) =>
applyConfig(projectId, ws, net, extent)
}
/>
);
}