Skip to content

Commit

Permalink
front: Atomic Update of Region State.
Browse files Browse the repository at this point in the history
This commit overhauls the handling of the region state across various
components, ensuring it's updated atomically. This change centralizes the state
management of the selected region into a single state object within the
RegionContext, replacing the previously separate state variables for
selectedRegionId, selectedRegionName, and selectedRegionHasSubregions.
Consequently, components like BreadcrumbNavigation, ListOfRegions, MainDisplay,
and RegionMap have been updated to accommodate this new state structure. By
consolidating the region state, we eliminate potential inconsistencies across
components and streamline the management of the region data.

Signed-off-by: Nikolay Martyanov <ohmspectator@gmail.com>
  • Loading branch information
OhmSpectator committed Nov 2, 2023
1 parent 208391b commit 96b0ac1
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 53 deletions.
32 changes: 21 additions & 11 deletions frontend/src/components/BreadcrumbNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,43 @@ import React, { useEffect, useState } from 'react';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import { Typography } from "@mui/material";
import { useRegion } from './RegionContext';
import { fetchAncestors } from '../api';
import {fetchAncestors, fetchRegion} from '../api';

const BreadcrumbNavigation = () => {
const { setSelectedRegionId, setSelectedRegionName, selectedRegionId, selectedRegionName } = useRegion();
const [breadcrumbItems, setBreadcrumbItems] = useState([{ id: null, name: 'World' }]);
const { selectedRegion, setSelectedRegion } = useRegion();
const [breadcrumbItems, setBreadcrumbItems] = useState([{ id: null, name: 'World', hasSubregions: true }]);

useEffect(() => {
const fetchAndSetAncestors = async () => {
if (selectedRegionId !== null && selectedRegionId !== 0) {
const ancestors = await fetchAncestors(selectedRegionId);
if (selectedRegion.id !== null && selectedRegion.id !== 0) {
const ancestors = await fetchAncestors(selectedRegion.id);
if (Array.isArray(ancestors)) {
const reversedAncestors = ancestors.reverse();
setBreadcrumbItems([{id: 0, name: 'World'}, ...reversedAncestors]);
setBreadcrumbItems([{id: 0, name: 'World', hasSubregions: true }, ...reversedAncestors]);
} else {
console.error('Ancestors is not an array:', ancestors);
}
} else {
setBreadcrumbItems([{ id: null, name: 'World' }]);
setBreadcrumbItems([{ id: null, name: 'World', hasSubregions: true }]);
}
};
fetchAndSetAncestors();
}, [selectedRegionId]);
}, [selectedRegion]);


const handleBreadcrumbClick = (regionId, index) => {
setSelectedRegionId(regionId);
setSelectedRegionName(breadcrumbItems[index].name);

let hasSubregions = false;
if (regionId === null || regionId === 0 ) {
hasSubregions = true;
} else {
hasSubregions = fetchRegion(regionId).then((region) => region.hasSubregions);
}
setSelectedRegion({
id: regionId,
name: breadcrumbItems[index].name,
hasSubregions: hasSubregions,
});
// Truncate the breadcrumbItems array up to the clicked index + 1
setBreadcrumbItems(prevItems => prevItems.slice(0, index + 1));
};
Expand All @@ -39,7 +49,7 @@ const BreadcrumbNavigation = () => {
<Typography
color="inherit"
key={index}
onClick={() => handleBreadcrumbClick(item.id, index)}
onClick={() => handleBreadcrumbClick(item.id, index, item.hasSubregions)}
style={{ cursor: 'pointer' }}
>
{item.name}
Expand Down
18 changes: 12 additions & 6 deletions frontend/src/components/ListOfRegions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useRegion } from './RegionContext';

const ListOfRegions = () => {

const { selectedRegionId, setSelectedRegionId, setSelectedRegionName, selectedRegionHasSubregions, setSelectedRegionHasSubregions } = useRegion();
const { selectedRegion, setSelectedRegion } = useRegion();
const [regions, setRegions] = useState([]);

const fetchRegions = async (regionId, hasSubregions) => {
Expand All @@ -27,13 +27,19 @@ const ListOfRegions = () => {
};

useEffect(() => {
fetchRegions(selectedRegionId, selectedRegionHasSubregions);
}, [selectedRegionId, setSelectedRegionHasSubregions]);
fetchRegions(selectedRegion.id, selectedRegion.hasSubregions);
}, [selectedRegion]);

const handleItemClick = (region) => {
setSelectedRegionId(region.id);
setSelectedRegionName(region.name);
setSelectedRegionHasSubregions(region.hasSubregions);
setSelectedRegion(
{
id: region.id,
name: region.name,
info: selectedRegion.info,
hasSubregions: region.hasSubregions,
}
);

};

return (
Expand Down
26 changes: 10 additions & 16 deletions frontend/src/components/MainDisplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,21 @@ import { fetchRegion } from '../api';
import RegionMap from "./RegionMap";

const MainDisplay = () => {
const { selectedRegionId, selectedRegionName, setSelectedRegionInfo } = useRegion();
const { selectedRegion, setSelectedRegion } = useRegion();

useEffect(() => {
const fetchSelectedRegionInfo = async () => {
try {
if (selectedRegionId !== null && selectedRegionId !== 0) {
const info = await fetchRegion(selectedRegionId);
setSelectedRegionInfo(info.regionName);
}
} catch (error) {
console.error(`Error fetching region info: ${error}`);
}
};

fetchSelectedRegionInfo();
}, [selectedRegionId]);
}, [selectedRegion]);

return (
<div>
{selectedRegionName && <h1>{selectedRegionName}</h1>}
{selectedRegionName && <RegionMap/>}
{selectedRegion.name ? (
<>
<h1>{selectedRegion.name}</h1>
<RegionMap/>
</>
) : (
<p>No region selected.</p>
)}
</div>
);
};
Expand Down
23 changes: 7 additions & 16 deletions frontend/src/components/RegionContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,15 @@ export const useRegion = () => {
};

export const RegionProvider = ({ children }) => {
const [selectedRegionId, setSelectedRegionId] = useState(null);
const [selectedRegionName, setSelectedRegionName] = useState(null);
const [selectedRegionInfo, setSelectedRegionInfo] = useState({});
const [selectedRegionHasSubregions, setSelectedRegionHasSubregions] = useState(false);
const [selectedRegion, setSelectedRegion] = useState({
id: null,
name: 'World',
info: {},
hasSubregions: false,
});

return (
<RegionContext.Provider
value={{
selectedRegionId,
setSelectedRegionId,
selectedRegionName,
setSelectedRegionName,
selectedRegionInfo,
setSelectedRegionInfo,
selectedRegionHasSubregions,
setSelectedRegionHasSubregions,
}}
>
<RegionContext.Provider value={{ selectedRegion, setSelectedRegion }}>
{children}
</RegionContext.Provider>
);
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/RegionMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {fetchRegionGeometry} from "../api";
const MapComponent = () => {
const mapContainer = useRef(null);
const map = useRef(null);
const { selectedRegionId, selectedRegionName } = useRegion();
const { selectedRegion } = useRegion();

const fetchSelectedRegionGeometry = async () => {
if (selectedRegionId !== null && selectedRegionId !== 0) {
const response = await fetchRegionGeometry(selectedRegionId);
if (selectedRegion.id !== null && selectedRegion.id !== 0) {
const response = await fetchRegionGeometry(selectedRegion.id);
if (response) {
return response.geometry;
} else {
Expand Down Expand Up @@ -72,7 +72,7 @@ const MapComponent = () => {
map.current = null;
}
};
}, [selectedRegionName]);
}, [selectedRegion]);

return <div ref={mapContainer} style={{ width: '100%', height: '400px' }} />;
};
Expand Down

0 comments on commit 96b0ac1

Please sign in to comment.