From 3e6396159e353a504f233b1f2a862d58c8fa87a4 Mon Sep 17 00:00:00 2001 From: John Eric Date: Fri, 30 Aug 2024 15:02:05 +0800 Subject: [PATCH] chore: code optimisations --- src/components/modal/congoptions.tsx | 41 +------ src/pages/admin.tsx | 137 +++++++++++------------ src/pages/slip.tsx | 56 ++++----- src/utils/helpers/checkcongexp.ts | 11 -- src/utils/helpers/checkmaxtries.ts | 11 -- src/utils/helpers/getcongoptions.ts | 22 +++- src/utils/helpers/getterritorydetails.ts | 48 +++----- 7 files changed, 138 insertions(+), 188 deletions(-) delete mode 100644 src/utils/helpers/checkcongexp.ts delete mode 100644 src/utils/helpers/checkmaxtries.ts diff --git a/src/components/modal/congoptions.tsx b/src/components/modal/congoptions.tsx index 16ee6834..3943e8b2 100644 --- a/src/components/modal/congoptions.tsx +++ b/src/components/modal/congoptions.tsx @@ -1,13 +1,6 @@ import NiceModal, { useModal, bootstrapDialog } from "@ebay/nice-modal-react"; import { useRollbar } from "@rollbar/react"; -import { - set, - ref, - get, - query, - orderByChild, - DataSnapshot -} from "firebase/database"; +import { set, ref } from "firebase/database"; import { useState, FormEvent, @@ -35,12 +28,12 @@ import { HHOptionProps, UpdateCongregationOptionsModalProps } from "../../utils/interface"; -import pollingQueryFunction from "../../utils/helpers/pollingquery"; import GenericInputField from "../form/input"; import ModalSubmitButton from "../form/submit"; import { confirmAlert } from "react-confirm-alert"; import { flushSync } from "react-dom"; import { usePostHog } from "posthog-js/react"; +import { getOptions } from "../../utils/helpers/getcongoptions"; const UpdateCongregationOptions = NiceModal.create( ({ currentCongregation }: UpdateCongregationOptionsModalProps) => { @@ -184,38 +177,16 @@ const UpdateCongregationOptions = NiceModal.create( ); useEffect(() => { - const getOptions = async () => { + const getHHOptions = async () => { try { - const optionsSnapshot = await pollingQueryFunction(() => - get( - query( - ref( - database, - `congregations/${currentCongregation}/options/list` - ), - orderByChild("sequence") - ) - ) - ); - const optionValues: Array = []; - optionsSnapshot.forEach((element: DataSnapshot) => { - const optionDetails = element.val(); - const optionCode = element.key as string; - const option = { - code: optionCode, - description: optionDetails.description, - isCountable: optionDetails.isCountable || false, - isDefault: optionDetails.isDefault || false, - sequence: optionDetails.sequence - }; - optionValues.push(option); - }); + const optionValues: Array = + await getOptions(currentCongregation); setOptions(optionValues); } catch (error) { errorHandler(error, rollbar); } }; - getOptions(); + getHHOptions(); }, [currentCongregation]); return ( diff --git a/src/pages/admin.tsx b/src/pages/admin.tsx index c2f0ea28..8aac3df3 100644 --- a/src/pages/admin.tsx +++ b/src/pages/admin.tsx @@ -67,10 +67,8 @@ import errorHandler from "../utils/helpers/errorhandler"; import ZeroPad from "../utils/helpers/zeropad"; import assignmentMessage from "../utils/helpers/assignmentmsg"; import getMaxUnitLength from "../utils/helpers/maxunitlength"; -import checkCongregationExpireHours from "../utils/helpers/checkcongexp"; import SetPollerInterval from "../utils/helpers/pollinginterval"; import pollingVoidFunction from "../utils/helpers/pollingvoid"; -import checkCongregationMaxTries from "../utils/helpers/checkmaxtries"; import TerritoryListing from "../components/navigation/territorylist"; import UserListing from "../components/navigation/userlist"; import NavBarBranding from "../components/navigation/branding"; @@ -101,13 +99,10 @@ import { } from "../utils/constants"; import ModalManager from "@ebay/nice-modal-react"; import SuspenseComponent from "../components/utils/suspense"; -import getOptions from "../utils/helpers/getcongoptions"; +import { processOptions } from "../utils/helpers/getcongoptions"; import GetDirection from "../utils/helpers/directiongenerator"; -import getOptionIsMultiSelect from "../utils/helpers/getoptionmultiselect"; -import getCongregationOrigin from "../utils/helpers/getcongorigin"; import useLocalStorage from "../utils/helpers/storage"; import CongListing from "../components/navigation/conglist"; -import getCongregationDetails from "../utils/helpers/getcongdetails"; import setLink from "../utils/helpers/setlink"; import getTerritoryData from "../utils/helpers/getterritorydetails"; import { usePostHog } from "posthog-js/react"; @@ -191,8 +186,6 @@ function Admin({ user }: adminProps) { const [sortedAddressList, setSortedAddressList] = useState>([]); const [selectedTerritoryCode, setSelectedTerritoryCode] = useState(); const [selectedTerritoryName, setSelectedTerritoryName] = useState(); - const [selectedTerritoryAggregates, setSelectedTerritoryAggregates] = - useState(0); const [addressData, setAddressData] = useState( new Map() ); @@ -286,17 +279,16 @@ function Admin({ user }: adminProps) { const processSelectedTerritory = async (selectedTerritoryCode: string) => { try { - const { territoryAddsResult, territoryNameResult, territoryAggregates } = - await getTerritoryData(code, selectedTerritoryCode); - setSelectedTerritoryCode(selectedTerritoryCode); - setSelectedTerritoryName(territoryNameResult.val()); - setSelectedTerritoryAggregates( - territoryAggregates.exists() ? territoryAggregates.val().value : 0 + const territoryAddsResult = await getTerritoryData( + code, + selectedTerritoryCode ); - + setSelectedTerritoryCode(selectedTerritoryCode); + setSelectedTerritoryName(territories.get(selectedTerritoryCode)?.name); refreshAddressState(); unsubscribers.current = [] as Array; + if (!territoryAddsResult) return; const detailsListing = getDetailsListing(territoryAddsResult); setSortedAddressList(detailsListing); @@ -716,15 +708,12 @@ function Admin({ user }: adminProps) { }; const processCongregationTerritories = ( - snapshot: DataSnapshot | undefined + // eslint-disable-next-line @typescript-eslint/no-explicit-any + congregationTerritories: any ) => { + const territoryList = new Map(); try { - if (!snapshot) return; - const data = snapshot.val(); - if (!data) return; - document.title = data["name"] as string; - const congregationTerritories = data["territories"]; - const territoryList = new Map(); + if (!congregationTerritories) return territoryList; for (const territory in congregationTerritories) { const name = congregationTerritories[territory]["name"]; const addresses = congregationTerritories[territory]["addresses"]; @@ -737,15 +726,10 @@ function Admin({ user }: adminProps) { aggregates: aggregates }); } - setTerritories(territoryList); - setName(data["name"] as string); - return territoryList; } catch (error) { console.error("Error processing congregation territories: ", error); } - }; - const getUserAccessLevel = async (congregationCode: string) => { - return congregationAccess.current[congregationCode]; + return territoryList; }; const handleTerritorySelect = useCallback( @@ -934,63 +918,65 @@ function Admin({ user }: adminProps) { if (!code) return; refreshAddressState(); - Promise.all([ - getUserAccessLevel(code), - checkCongregationExpireHours(code), - checkCongregationMaxTries(code), - getOptions(code), - getOptionIsMultiSelect(code), - getCongregationDetails(code), - getCongregationOrigin(code) - ]) - .then( - ([ - userAccessLevel, - expireHours, - maxTries, - options, - optionIsMultiselect, - congregationDetails, - origin - ]) => { - setUserAccessLevel(Number(userAccessLevel)); - setDefaultExpiryHours( - expireHours.exists() - ? expireHours.val() - : DEFAULT_SELF_DESTRUCT_HOURS + setUserAccessLevel(congregationAccess.current[code]); + const congregationUnsub = onValue( + child(ref(database), `congregations/${code}`), + (snapshot) => { + try { + if (!snapshot.exists()) { + setIsUnauthorised(true); + errorHandler( + `Unauthorised access by ${user.email}`, + rollbar, + false + ); + return; + } + const congregationDetails = snapshot.val(); + const congName = congregationDetails["name"] as string; + const expireHours = + congregationDetails["expireHours"] || DEFAULT_SELF_DESTRUCT_HOURS; + const maxTries = + congregationDetails["maxTries"] || DEFAULT_CONGREGATION_MAX_TRIES; + const options = processOptions( + congregationDetails["options"]["list"] ); + const optionIsMultiselect = + congregationDetails["options"]["isMultiselect"] || + DEFAULT_CONGREGATION_OPTION_IS_MULTIPLE; + const origin = + congregationDetails["origin"] || + DEFAULT_MAP_DIRECTION_CONGREGATION_LOCATION; + const congregationTerritories = processCongregationTerritories( + congregationDetails["territories"] + ); + + document.title = congName; + setName(congName); + setDefaultExpiryHours(expireHours); setOptions(options); setPolicy( new Policy( loginUserClaims.current, options, - maxTries.exists() - ? maxTries.val() - : DEFAULT_CONGREGATION_MAX_TRIES, - optionIsMultiselect.exists() - ? optionIsMultiselect.val() - : DEFAULT_CONGREGATION_OPTION_IS_MULTIPLE, - origin.exists() - ? origin.val() - : DEFAULT_MAP_DIRECTION_CONGREGATION_LOCATION + maxTries, + optionIsMultiselect, + origin ) ); - + setTerritories(congregationTerritories); posthog?.identify(code, { - name: congregationDetails.exists() - ? congregationDetails.val()["name"] - : "" + name: congName }); - processCongregationTerritories( - congregationDetails.exists() ? congregationDetails : undefined - ); + } catch (error) { + errorHandler(error, rollbar); + } finally { setIsLoading(false); } - ) - .catch((error) => { - // Handle the error here - console.error(error); - }); + } + ); + + return () => congregationUnsub(); }, [code]); if (isLoading) return ; @@ -1068,7 +1054,10 @@ function Admin({ user }: adminProps) { {selectedTerritoryCode ? ( <> {selectedTerritoryCode} diff --git a/src/pages/slip.tsx b/src/pages/slip.tsx index 2aa8ad1d..0d224f29 100644 --- a/src/pages/slip.tsx +++ b/src/pages/slip.tsx @@ -14,7 +14,6 @@ import { LinkSession, Policy } from "../utils/policies"; import ZeroPad from "../utils/helpers/zeropad"; import processAddressData from "../utils/helpers/processadddata"; import getMaxUnitLength from "../utils/helpers/maxunitlength"; -import getOptions from "../utils/helpers/getcongoptions"; import Legend from "../components/navigation/legend"; import Loader from "../components/statics/loader"; import { @@ -35,13 +34,13 @@ import InstructionImg from "../assets/instruction.svg?react"; import TimeImg from "../assets/time.svg?react"; import ModalManager from "@ebay/nice-modal-react"; import GetDirection from "../utils/helpers/directiongenerator"; -import getOptionIsMultiSelect from "../utils/helpers/getoptionmultiselect"; -import getCongregationOrigin from "../utils/helpers/getcongorigin"; import { useParams } from "react-router-dom"; import InvalidPage from "../components/statics/invalidpage"; import { useRollbar } from "@rollbar/react"; import SuspenseComponent from "../components/utils/suspense"; import { usePostHog } from "posthog-js/react"; +import { processOptions } from "../utils/helpers/getcongoptions"; +import getCongregationDetails from "../utils/helpers/getcongdetails"; const UpdateUnitStatus = lazy(() => import("../components/modal/updatestatus")); @@ -58,9 +57,6 @@ const Map = () => { const [isLinkExpired, setIsLinkExpired] = useState(true); const [tokenEndTime, setTokenEndTime] = useState(0); const [publisherName, setPublisherName] = useState(""); - const [congregationMaxTries, setCongregationMaxTries] = useState( - DEFAULT_CONGREGATION_MAX_TRIES - ); const [postalcode, setPostalcode] = useState(""); const [showLegend, setShowLegend] = useState(false); @@ -131,7 +127,6 @@ const Map = () => { const tokenEndtime = linkrec.tokenEndtime; setPublisherName(linkrec.publisherName); - setCongregationMaxTries(linkrec.maxTries); setPostalcode(linkrec.postalCode); const currentTimestamp = new Date().getTime(); setTokenEndTime(tokenEndtime); @@ -164,27 +159,37 @@ const Map = () => { useEffect(() => { const getMapData = async () => { if (!code || !postalcode) return; - const options = await getOptions(code); - const isMultiselect = await getOptionIsMultiSelect(code); - const origin = await getCongregationOrigin(code); + const congregationDetails = await getCongregationDetails(code); + if (!congregationDetails.exists()) { + setIsLoading(false); + return; + } + const congregationData = congregationDetails.val(); + const options = processOptions(congregationData.options?.list); + const isMultiselect = + congregationData.options?.isMultiSelect || + DEFAULT_CONGREGATION_OPTION_IS_MULTIPLE; + const origin = + congregationData.origin || DEFAULT_MAP_DIRECTION_CONGREGATION_LOCATION; + const congregationMaxTries = + congregationData.maxTries || DEFAULT_CONGREGATION_MAX_TRIES; setOptions(options); setPolicy( new Policy( undefined, options, congregationMaxTries, - isMultiselect.exists() - ? isMultiselect.val() - : DEFAULT_CONGREGATION_OPTION_IS_MULTIPLE, - origin.exists() - ? origin.val() - : DEFAULT_MAP_DIRECTION_CONGREGATION_LOCATION + isMultiselect, + origin ) ); onValue( child(ref(database), `addresses/${code}/${postalcode}`), - (snapshot) => { - if (snapshot.exists()) { + async (snapshot) => { + try { + if (!snapshot.exists()) { + return; + } const postalSnapshot = snapshot.val(); setValues((values) => ({ ...values, @@ -197,14 +202,15 @@ const Map = () => { postalSnapshot.coordinates || DEFAULT_COORDINATES.Singapore ); setAggregate(postalSnapshot.aggregates); - processAddressData(code, postalcode, postalSnapshot.units) - .then((data) => { - setFloors(data); - }) - .finally(() => { - setIsLoading(false); - }); + const data = await processAddressData( + code, + postalcode, + postalSnapshot.units + ); + setFloors(data); document.title = postalSnapshot.name; + } finally { + setIsLoading(false); } } ); diff --git a/src/utils/helpers/checkcongexp.ts b/src/utils/helpers/checkcongexp.ts deleted file mode 100644 index 67e38e0b..00000000 --- a/src/utils/helpers/checkcongexp.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { get, child, ref } from "firebase/database"; -import { database } from "../../firebase"; -import pollingQueryFunction from "./pollingquery"; - -const checkCongregationExpireHours = async (code: string) => { - return await pollingQueryFunction(() => - get(child(ref(database), `congregations/${code}/expiryHours`)) - ); -}; - -export default checkCongregationExpireHours; diff --git a/src/utils/helpers/checkmaxtries.ts b/src/utils/helpers/checkmaxtries.ts deleted file mode 100644 index 073333f6..00000000 --- a/src/utils/helpers/checkmaxtries.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { get, child, ref } from "firebase/database"; -import { database } from "../../firebase"; -import pollingQueryFunction from "./pollingquery"; - -const checkCongregationMaxTries = async (code: string) => { - return await pollingQueryFunction(() => - get(child(ref(database), `congregations/${code}/maxTries`)) - ); -}; - -export default checkCongregationMaxTries; diff --git a/src/utils/helpers/getcongoptions.ts b/src/utils/helpers/getcongoptions.ts index 9db0860f..37f817a4 100644 --- a/src/utils/helpers/getcongoptions.ts +++ b/src/utils/helpers/getcongoptions.ts @@ -28,4 +28,24 @@ const getOptions = async (code: string) => { return householdTypes; }; -export default getOptions; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const processOptions = (optionList: any) => { + const householdTypes = new Array(); + + // Retrieve the household types from the snapshot + Object.keys(optionList).forEach((key) => { + const value = optionList[key]; + householdTypes.push({ + code: key, + description: value.description, + isCountable: value.isCountable, + isDefault: value.isDefault, + sequence: value.sequence + }); + }); + // Sort the household types by sequence + householdTypes.sort((a, b) => a.sequence - b.sequence); + return householdTypes; +}; + +export { getOptions, processOptions }; diff --git a/src/utils/helpers/getterritorydetails.ts b/src/utils/helpers/getterritorydetails.ts index 1817ce16..10e251fa 100644 --- a/src/utils/helpers/getterritorydetails.ts +++ b/src/utils/helpers/getterritorydetails.ts @@ -1,4 +1,4 @@ -import { get, query, ref, orderByValue, child } from "firebase/database"; +import { get, query, ref, orderByValue } from "firebase/database"; import { database } from "../../firebase"; import pollingQueryFunction from "./pollingquery"; @@ -6,38 +6,24 @@ const getTerritoryData = async ( code: string, selectedTerritoryCode: string ) => { - const [territoryAddsResult, territoryNameResult, territoryAggregates] = - await Promise.all([ - pollingQueryFunction(() => - get( - query( - ref( - database, - `congregations/${code}/territories/${selectedTerritoryCode}/addresses` - ), - orderByValue() - ) - ) + try { + const territoryRef = query( + ref( + database, + `congregations/${code}/territories/${selectedTerritoryCode}/addresses` ), - pollingQueryFunction(() => - get( - child( - ref(database), - `congregations/${code}/territories/${selectedTerritoryCode}/name` - ) - ) - ), - pollingQueryFunction(() => - get( - child( - ref(database), - `congregations/${code}/territories/${selectedTerritoryCode}/aggregates` - ) - ) - ) - ]); + orderByValue() + ); + + const territoryAddsResult = await pollingQueryFunction(() => + get(territoryRef) + ); - return { territoryAddsResult, territoryNameResult, territoryAggregates }; + return territoryAddsResult; + } catch (error) { + console.error("Error fetching territory data:", error); + return; + } }; export default getTerritoryData;