Skip to content

Commit

Permalink
fix: lift some state from sidebar to page
Browse files Browse the repository at this point in the history
  • Loading branch information
zerj9 committed Sep 27, 2024
1 parent 988c488 commit b2acc92
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 268 deletions.
85 changes: 42 additions & 43 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,22 @@ import {
handleFileToggle as handleFileToggleUtil,
} from "../utils/fileHandler";

// Keys to change base layers
type BaseLayerKey = "Light" | "Dark" | "Road";
const layerButtonColors: Record<BaseLayerKey, string> = {
Light: "bg-yellow-400 hover:bg-yellow-500 focus:ring-yellow-300",
Dark: "bg-purple-700 hover:bg-purple-800 focus:ring-purple-600",
Road: "bg-green-600 hover:bg-green-700 focus:ring-green-500",
};

// Load Map
const Map = dynamic(() => import("../components/Map/Map"), {
loading: () => (
<div className="w-full h-full flex items-center justify-center">
<LoadingSpinner />
</div>
),
loading: () => <LoadingSpinner />,
ssr: false,
});

// Load Sidebar
const Sidebar = dynamic(() => import("../components/Sidebar/Sidebar"), {
ssr: false,
});

// Define Spinner
const LoadingSpinner = () => {
const [rotation, setRotation] = useState(0);

Expand All @@ -51,39 +48,40 @@ const LoadingSpinner = () => {
);
};

// ENTRY POINT FOR APP
function Home() {
// Define BASE_LAYERS inside the component
const BASE_LAYERS: Record<BaseLayerKey, string> = {
Light: `${typeof window !== "undefined" ? window.location.origin : ""}/OS_VTS_3857_Light.json`,
Dark: `${typeof window !== "undefined" ? window.location.origin : ""}/OS_VTS_3857_Dark.json`,
Road: `${typeof window !== "undefined" ? window.location.origin : ""}/OS_VTS_3857_Road.json`,
};

// Set up the states
const CORE_LAYERS = ["coreLayer1", "coreLayer2"];
const THEMATIC_LAYERS = ["thematicLayer1", "thematicLayer2"];
const USER_DEFINED_LAYERS = ["userLayer1", "userLayer2"];

// State
const [sidebarOpen, setSidebarOpen] = useState<boolean>(false);
const [activeLayers, setActiveLayers] = useState<string[]>(() =>
getLocalStorageItem("activeLayers", ["baseLayer1"]),
getLocalStorageItem("activeLayers", ["baseLayer1"])
);
const [uploadedFiles, setUploadedFiles] = useState<string[]>(() =>
getLocalStorageItem("uploadedFiles", []),
getLocalStorageItem("uploadedFiles", [])
);
const [activeFiles, setActiveFiles] = useState<string[]>(() =>
getLocalStorageItem("activeFiles", []),
getLocalStorageItem("activeFiles", [])
);
const [isDragging, setIsDragging] = useState<boolean>(false);
const [isModalOpen, setIsModalOpen] = useState(false);
const [currentUploadedFileName, setCurrentUploadedFileName] = useState("");
const [currentUploadedFileContent, setCurrentUploadedFileContent] =
useState("");
const [currentUploadedFileContent, setCurrentUploadedFileContent] = useState("");
const [uploadError, setUploadError] = useState<string | null>(null);
const [selectedBaseLayer, setSelectedBaseLayer] =
useState<BaseLayerKey>("Light");
const [selectedBaseLayer, setSelectedBaseLayer] = useState<BaseLayerKey>("Light");

const dragCounter = useRef(0);

// Call backs for interactive elements where props COULD change
const handleBaseLayerChange = useCallback((newBaseLayer: BaseLayerKey) => {
setSelectedBaseLayer(newBaseLayer);
// Callbacks
const handleBaseLayerChange = useCallback((newBaseLayer: string) => {
setSelectedBaseLayer(newBaseLayer as BaseLayerKey);
}, []);

const handleDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -131,19 +129,16 @@ function Home() {
handleFileUpload(files[0]);
}
},
[handleFileUpload],
[handleFileUpload]
);

const handleFileDelete = useCallback((fileName: string) => {
handleFileDeleteUtil(fileName, setUploadedFiles, setActiveFiles);
}, []);

const handleFileToggle = useCallback(
(fileName: string, isActive: boolean) => {
handleFileToggleUtil(fileName, isActive, setActiveFiles);
},
[],
);
const handleFileToggle = useCallback((fileName: string, isActive: boolean) => {
handleFileToggleUtil(fileName, isActive, setActiveFiles);
}, []);

const handleLayerToggle = useCallback((updatedLayers: string[]) => {
setActiveLayers(updatedLayers);
Expand All @@ -152,9 +147,7 @@ function Home() {

const handleLayerNameConfirm = useCallback(
async (layerName: string, isRemote: boolean) => {
console.log(
`handleLayerNameConfirm called with: ${layerName}, isRemote: ${isRemote}`,
);
console.log(`handleLayerNameConfirm called with: ${layerName}, isRemote: ${isRemote}`);
try {
const jsonData = JSON.parse(currentUploadedFileContent);
if (isRemote) {
Expand Down Expand Up @@ -203,7 +196,7 @@ function Home() {
setCurrentUploadedFileName("");
setCurrentUploadedFileContent("");
},
[currentUploadedFileContent],
[currentUploadedFileContent]
);

return (
Expand All @@ -216,7 +209,7 @@ function Home() {
>
<Sidebar
isOpen={sidebarOpen}
onClose={useCallback(() => setSidebarOpen(false), [])}
onClose={() => setSidebarOpen(false)}
onLayerToggle={handleLayerToggle}
onFileUpload={handleFileUpload}
onFileDelete={handleFileDelete}
Expand All @@ -225,28 +218,34 @@ function Home() {
uploadedFiles={uploadedFiles}
activeFiles={activeFiles}
uploadError={uploadError}
baseLayers={Object.keys(BASE_LAYERS) as BaseLayerKey[]}
coreLayers={["coreLayer1", "coreLayer2"]}
thematicLayers={["thematicLayer1", "thematicLayer2"]}
userDefinedLayers={["userLayer1", "userLayer2"]}
onBaseLayerChange={handleBaseLayerChange}
selectedBaseLayer={selectedBaseLayer}
layerGroups={[
{
title: "Base",
layers: Object.keys(BASE_LAYERS) as BaseLayerKey[],
onLayerSelect: handleBaseLayerChange,
buttonColors: layerButtonColors
},
{ title: "Core", layers: CORE_LAYERS },
{ title: "Thematic", layers: THEMATIC_LAYERS },
{ title: "User Defined", layers: USER_DEFINED_LAYERS },
]}
/>
<main className="flex-1 relative">
<button
className="absolute top-4 left-4 z-10 md:hidden text-gray-600 dark:text-gray-400 bg-white dark:bg-gray-800 p-2 rounded-md shadow-md"
onClick={useCallback(() => setSidebarOpen(true), [])}
onClick={() => setSidebarOpen(true)}
>
<Menu className="w-6 h-6" />
</button>
<Map
activeFiles={activeFiles}
baseLayer={BASE_LAYERS[selectedBaseLayer]}
/>{" "}
{/* Pass the selected base layer URL */}
/>
</main>
<FileUploadModal
isOpen={isModalOpen}
onClose={useCallback(() => setIsModalOpen(false), [])}
onClose={() => setIsModalOpen(false)}
onConfirm={handleLayerNameConfirm}
defaultLayerName={currentUploadedFileName || ""}
/>
Expand Down
101 changes: 81 additions & 20 deletions src/components/Map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
TokenData,
FeatureCollectionWithCRS,
INITIAL_VIEW_STATE,
handleError,
fetchToken,
getValidToken,
transformGeoJsonData,
Expand Down Expand Up @@ -77,6 +76,46 @@ const LayerStyleForm: React.FC<{
);
};

const addMvtLayer = (map: React.RefObject<maplibregl.Map>) => {
console.log("Adding MVT Layer");
console.log("Backend URL:", process.env.NEXT_PUBLIC_BACKEND_URL);
if (!map.current) {
console.log("Map not initialized, cannot add MVT layer");
return;
}
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL;

// Remove existing layer and source if they exist
if (map.current.getLayer('my-mvt-layer')) {
map.current.removeLayer('my-mvt-layer');
}
if (map.current.getSource('my-mvt-source')) {
map.current.removeSource('my-mvt-source');
}

// Add the vector tile source and layer
map.current.addSource('my-mvt-source', {
type: 'vector',
tiles: [`${backendUrl}/tiles/{z}/{y}/{x}`],
minzoom: 0,
maxzoom: 14,
});

map.current.addLayer({
id: 'my-mvt-layer',
type: 'circle',
source: 'my-mvt-source',
'source-layer': 'pois', // Replace with your actual source layer
paint: {
'circle-color': '#FF0000',
'circle-radius': 3,
},
});

console.log('MVT layer added');
};


// Initialize the map
const initMap = async (
mapContainer: React.RefObject<HTMLDivElement>,
Expand Down Expand Up @@ -121,14 +160,16 @@ const initMap = async (
},
});

map.current.on("load", () => setMapLoaded(true));
map.current.on("styledata", () =>
console.log("New style loaded:", baseLayer),
);
map.current.on("load", () => {
console.log("Running on load event")
setMapLoaded(true);
console.log("Calling addMvtLayer")
addMvtLayer(map);
});

map.current.on("error", (e) =>
handleError(setMapError, e.error, "Map error"),
);
map.current.on("error", (e) => {
console.error(setMapError, e.error, "Map error")
});

// Add click listener for layers to open the style form
map.current.on("click", (e) => {
Expand All @@ -140,8 +181,9 @@ const initMap = async (
}
}
});

} catch (error) {
handleError(setMapError, error as Error, "Error initializing map");
console.error('Error adding MVT layer:', error);
}
};

Expand All @@ -157,24 +199,43 @@ const Map: React.FC<MapProps> = ({ activeFiles, baseLayer }) => {

// Initialize map on component mount
useEffect(() => {
initMap(
mapContainer,
baseLayer,
setMapLoaded,
() =>
getValidToken(fetchToken, tokenDataRef, tokenPromiseRef, setMapError),
setMapError,
map,
tokenDataRef,
setSelectedLayer,
);
if (!map.current) {
console.log("Initializing map");
initMap(
mapContainer,
baseLayer,
setMapLoaded,
() =>
getValidToken(fetchToken, tokenDataRef, tokenPromiseRef, setMapError),
setMapError,
map,
tokenDataRef,
setSelectedLayer,
);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
return () => {
if (map.current) {
map.current.remove();
map.current = null;
}
};
}, []);

useEffect(() => {
if (map.current) {
console.log("Changing map style");
map.current.setStyle(baseLayer);

// Listen for the 'style.load' event and then add the MVT layer
map.current.once("styledata", () => {
console.log("Style loaded, adding MVT layer");
addMvtLayer(map);
});
}
}, [baseLayer]);

// Adds locally uploaded Geojsons to the map
Expand Down
Loading

0 comments on commit b2acc92

Please sign in to comment.