Improve navigation handling in new map app

This commit is contained in:
Maciej Ziarkowski 2021-02-24 07:48:09 +00:00
parent 305f2f1671
commit 2afc7f8c8f
7 changed files with 39 additions and 36 deletions

View File

@ -129,7 +129,7 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition} = {
},
},
[Category.Sustainability]: {
mapStyle: 'sust_Dec',
mapStyle: 'sust_dec',
legend: {
title: 'Sustainability',
description: 'DEC Rating',

View File

@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from 'react';
import { Building } from '../models/building';
import { Building, BuildingAttributeVerificationCounts } from '../models/building';
import { apiGet } from '../apiHelpers';
export function useBuildingData(buildingId: number, preloadedData: Building): [Building, (updatedBuilding: Building) => void, () => void] {
@ -29,6 +29,13 @@ export function useBuildingData(buildingId: number, preloadedData: Building): [B
setIsOld(false);
}, [buildingId]);
const updateData = useCallback((building: Building) => {
if(building.verified == undefined) {
building.verified = {} as BuildingAttributeVerificationCounts;
}
setBuildingData(building);
}, []);
useEffect(() => {
return () => {
setIsOld(true);
@ -43,5 +50,5 @@ export function useBuildingData(buildingId: number, preloadedData: Building): [B
const reloadData = useCallback(() => setIsOld(true), []);
return [buildingData, setBuildingData, reloadData];
return [buildingData, updateData, reloadData];
}

View File

@ -1,7 +1,11 @@
import { usePrevious } from './use-previous';
import { useEffect, useState } from 'react';
export function useLastNotEmpty<T>(value: T): T {
const previousValue = usePrevious(value);
const [notEmpty, setNotEmpty] = useState(value);
useEffect(() => {
if(value != undefined) {
setNotEmpty(value);
}
}, [value]);
return value ?? previousValue;
return notEmpty;
}

View File

@ -1,10 +0,0 @@
import { useEffect, useRef } from 'react';
export function usePrevious<T>(value: T) {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
});
return ref.current;
}

View File

@ -46,30 +46,32 @@ function setOrToggle<T>(currentValue: T, newValue: T): T {
export const MapApp: React.FC<MapAppProps> = props => {
const [categoryUrlParam] = useUrlCategoryParam();
const [selectedBuildingId, setSelectedBuildingId] = useUrlBuildingParam();
const [mode] = useUrlModeParam();
const [currentCategory, setCategory] = useState<Category>();
useEffect(() => setCategory(unless(categoryUrlParam, 'categories')), [categoryUrlParam]);
const displayCategory = useLastNotEmpty(currentCategory) ?? defaultMapCategory;
const [selectedBuildingId, setSelectedBuildingId] = useUrlBuildingParam('view', displayCategory);
const [building, updateBuilding, reloadBuilding] = useBuildingData(selectedBuildingId, props.building);
const [buildingLike, updateBuildingLike] = useBuildingLikeData(selectedBuildingId, props.building_like);
const [userVerified, updateUserVerified, reloadUserVerified] = useUserVerifiedData(selectedBuildingId, props.user_verified);
const [revisionId, updateRevisionId] = useRevisionId(props.revisionId);
useEffect(() => {
updateRevisionId(building?.revision_id)
}, [building]);
const [mode] = useUrlModeParam();
const viewEditMode = unless(mode, 'multi-edit');
const [multiEditData, multiEditError] = useMultiEditData();
const selectBuilding = useCallback((selectedBuilding: Building) => {
updateBuilding(Object.assign({}, building, selectedBuilding));
setSelectedBuildingId(setOrToggle(selectedBuildingId, selectedBuilding?.building_id));
const currentId = selectedBuildingId;
updateBuilding(selectedBuilding);
setSelectedBuildingId(setOrToggle(currentId, selectedBuilding?.building_id));
}, [selectedBuildingId, setSelectedBuildingId, updateBuilding, building]);
const colourBuilding = useCallback(async (building: Building) => {

View File

@ -1,6 +1,7 @@
import { Category } from '../config/categories-config';
import { intParamTransform } from './url-param-transform';
import { useUrlParam } from './use-url-param';
export function useUrlBuildingParam() {
return useUrlParam('building', intParamTransform);
export function useUrlBuildingParam(defaultMode: 'view' | 'edit' | 'multi-edit', defaultCategory: Category | 'categories' = 'categories') {
return useUrlParam('building', intParamTransform, '/:mode/:category/:building?', {mode: defaultMode, category: defaultCategory});
}

View File

@ -5,7 +5,9 @@ import { UrlParamTransform } from './url-param-transform';
export function useUrlParam<T>(
param: string,
paramTransform: UrlParamTransform<T>
paramTransform: UrlParamTransform<T>,
pathPattern?: string,
defaultParams: { [key: string]: string} = {}
): [T, (newParam: T) => void] {
const match = useRouteMatch();
const history = useHistory();
@ -19,15 +21,12 @@ export function useUrlParam<T>(
}, [param, paramTransform, match.url]);
const setUrlParam = useCallback((value: T) => {
const stringValue = value == undefined ? '' : paramTransform.toParam(value);
const newPath = generatePath(match.path, {
...match.params,
...{
[param]: stringValue
}
});
const newParams = Object.assign({}, defaultParams, match.params);
newParams[param] = value == undefined ? undefined : paramTransform.toParam(value);
const newPath = generatePath(pathPattern ?? match.path, newParams);
history.push(newPath);
}, [param, paramTransform, match.url]);
}, [param, paramTransform, pathPattern, defaultParams, match.url]);
return [paramValue, setUrlParam];
}