colouring-montreal/app/src/frontend/api-data/use-building-data.ts
2022-11-02 10:38:42 +01:00

70 lines
2.4 KiB
TypeScript

import { useCallback, useEffect, useState } from 'react';
import { Building, BuildingAttributeVerificationCounts } from '../models/building';
import { apiGet } from '../apiHelpers';
/**
*
* @param buildingId Requested building ID
* @param preloadedData Data preloaded through SSR, to return before the request is first sent
* @param includeUserAttributes Should the building-user attributes be included in the result? This requires login session cookies to be present
* @returns
*/
export function useBuildingData(buildingId: number, preloadedData: Building, includeUserAttributes: boolean = false): [Building, (updatedBuilding: Building) => void, () => void] {
const [buildingData, setBuildingData] = useState<Building>(preloadedData);
const [isOld, setIsOld] = useState<boolean>(preloadedData == undefined);
const fetchData = useCallback(async () => {
if(buildingId == undefined) {
setBuildingData(undefined);
setIsOld(false);
return;
}
try {
let [building, buildingUprns, planningData] = await Promise.all([
apiGet(`/api/buildings/${buildingId}.json${includeUserAttributes ? '?user_attributes=true' : ''}`),
apiGet(`/api/buildings/${buildingId}/uprns.json`),
apiGet(`/api/buildings/${buildingId}/planning_data.json`)
]);
building.uprns = buildingUprns.uprns;
building.planning_data = planningData.data;
building = Object.assign(building, {...building.user_attributes});
delete building.user_attributes;
setBuildingData(building);
} catch(error) {
console.error(error);
// TODO: add UI for API errors
}
setIsOld(false);
}, [buildingId]);
const updateData = useCallback((building: Building) => {
if(building == undefined) {
setBuildingData(building);
} else {
if(building.verified == undefined) {
building.verified = {} as BuildingAttributeVerificationCounts;
}
setBuildingData(building);
}
}, []);
useEffect(() => {
return () => {
setIsOld(true);
};
}, [buildingId]);
useEffect(() => {
if(isOld) {
fetchData();
}
}, [isOld]);
const reloadData = useCallback(() => setIsOld(true), []);
return [buildingData, updateData, reloadData];
}