Skip to content

Commit

Permalink
feat: handle promises and errors
Browse files Browse the repository at this point in the history
  • Loading branch information
maximeBAY committed Dec 19, 2024
1 parent d2e431a commit 6692ade
Show file tree
Hide file tree
Showing 25 changed files with 319 additions and 88 deletions.
19 changes: 18 additions & 1 deletion canopeum_frontend/src/components/MainLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useContext, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { Navigate, Outlet, Route, Routes } from 'react-router-dom'

import { AuthenticationContext } from './context/AuthenticationContext'
import Navbar from './Navbar'
import TermsAndPolicies from '@components/settings/TermsAndPolicies'
import { appRoutes } from '@constants/routes.constant'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import Analytics from '@pages/Analytics'
import AnalyticsSite from '@pages/AnalyticsSite'
import Home from '@pages/Home'
Expand Down Expand Up @@ -53,9 +55,24 @@ const AuthenticatedRoutes = () => {

const MainLayout = () => {
const { initAuth } = useContext(AuthenticationContext)
const { t: translate } = useTranslation()
const { getErrorMessage } = useErrorHandling()


// Try authenticating user on app start if token was saved in storage
useEffect(() => void initAuth(), [initAuth])
useEffect(() => {
const runInitAuth = async () => initAuth()

runInitAuth().catch((error: unknown) => {
const errorMessage = getErrorMessage(
error,
translate('auth.user-token-not-found')
)
console.error(errorMessage);
});
}, []);



return (
<Routes>
Expand Down
13 changes: 11 additions & 2 deletions canopeum_frontend/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { useTranslation } from 'react-i18next'
import { Link, useLocation } from 'react-router-dom'

import { AuthenticationContext } from './context/AuthenticationContext'
import { SnackbarContext } from '@components/context/SnackbarContext'
import { appRoutes } from '@constants/routes.constant'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import type { RoleEnum } from '@services/api'

type NavbarItem = {
Expand Down Expand Up @@ -46,15 +48,22 @@ const Navbar = () => {
const { i18n: { changeLanguage, language }, t: translate } = useTranslation()
const [currentLanguage, setCurrentLanguage] = useState(language)
const { currentUser } = useContext(AuthenticationContext)

const { getErrorMessage } = useErrorHandling()
const { openAlertSnackbar } = useContext(SnackbarContext)
const location = useLocation()

const handleChangeLanguage = () => {
const newLanguage = currentLanguage === 'en'
? 'fr'
: 'en'
setCurrentLanguage(newLanguage)
void changeLanguage(newLanguage)
changeLanguage(newLanguage).catch((error: unknown) => {
const errorMessage = getErrorMessage(
error,
translate('errors.change-language-failed')
)
openAlertSnackbar(errorMessage, { severity: 'error' })
})
}

const { isAuthenticated, showLogoutModal } = useContext(AuthenticationContext)
Expand Down
29 changes: 16 additions & 13 deletions canopeum_frontend/src/components/analytics/BatchActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import EditBatchModal from '@components/analytics/batch-modal/EditBatchModal'
import { SnackbarContext } from '@components/context/SnackbarContext'
import ConfirmationDialog from '@components/dialogs/ConfirmationDialog'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import type { BatchDetail } from '@services/api'

type Props = {
Expand All @@ -19,6 +20,7 @@ const BatchActions = ({ onEdit, onDelete, batchDetail }: Props) => {
const { t: translate } = useTranslation()
const { openAlertSnackbar } = useContext(SnackbarContext)
const { getApiClient } = useApiClient()
const { getErrorMessage } = useErrorHandling()

const whisperRef = useRef<OverlayTriggerHandle>(null)

Expand All @@ -27,23 +29,24 @@ const BatchActions = ({ onEdit, onDelete, batchDetail }: Props) => {

const deleteBatch = async () => {
whisperRef.current?.close()
try {
await getApiClient().batchClient.delete(batchDetail.id)
openAlertSnackbar(
translate('analyticsSite.delete-batch.success', { batchName: batchDetail.name }),
)
onDelete()
} catch {
openAlertSnackbar(
translate('analyticsSite.delete-batch.error', { batchName: batchDetail.name }),
{ severity: 'error' },
)
}

await getApiClient().batchClient.delete(batchDetail.id)
openAlertSnackbar(
translate('analyticsSite.delete-batch.success', { batchName: batchDetail.name }),
)
onDelete()

}

const handleConfirmDeleteClose = (proceed: boolean) => {
setConfirmDeleteOpen(false)
if (proceed) void deleteBatch()
if (proceed) deleteBatch().catch((error: unknown) =>
openAlertSnackbar(
getErrorMessage(error, translate('analyticsSite.delete-batch.error',
{ batchName: batchDetail.name })),
{ severity: 'error' },
)
)
}

return (
Expand Down
12 changes: 11 additions & 1 deletion canopeum_frontend/src/components/analytics/BatchTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { useTranslation } from 'react-i18next'
import BatchActions from '@components/analytics/BatchActions'
import BatchSponsorLogo from '@components/batches/BatchSponsorLogo'
import { LanguageContext } from '@components/context/LanguageContext'
import { SnackbarContext } from '@components/context/SnackbarContext'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import type { BatchDetail } from '@services/api'

const BATCH_HEADER_CLASS =
Expand All @@ -22,6 +24,8 @@ const BatchTable = (props: Props) => {
const { t } = useTranslation()
const { translateValue } = useContext(LanguageContext)
const { getApiClient } = useApiClient()
const { openAlertSnackbar } = useContext(SnackbarContext)
const { getErrorMessage } = useErrorHandling()

const [batches, setBatches] = useState(props.batches)

Expand Down Expand Up @@ -71,7 +75,13 @@ const BatchTable = (props: Props) => {
<BatchActions
batchDetail={batch}
onDelete={() => setBatches(previous => previous.filter(b => b.id !== batch.id))}
onEdit={() => void fetchBatch(props.siteId)}
onEdit={() => fetchBatch(props.siteId).catch((error: unknown) =>
openAlertSnackbar(
getErrorMessage(error, t('errors.fetch-batch-failed',
{ batchName: batch.name })),
{ severity: 'error' },
)
)}
/>
</div>
</th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { useTranslation } from 'react-i18next'

import OptionQuantitySelector, { type SelectorOption, type SelectorOptionQuantity } from '@components/analytics/OptionQuantitySelector'
import { LanguageContext } from '@components/context/LanguageContext'
import { SnackbarContext } from '@components/context/SnackbarContext'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import { FertilizerType } from '@services/api'
import { notEmpty } from '@utils/arrayUtils'

Expand All @@ -17,6 +19,8 @@ const FertilizersSelector = ({ onChange, fertilizers }: Props) => {
const { t: translate } = useTranslation()
const { translateValue } = useContext(LanguageContext)
const { getApiClient } = useApiClient()
const { openAlertSnackbar } = useContext(SnackbarContext)
const { getErrorMessage } = useErrorHandling()

const [availableFertilizers, setAvailableFertilizers] = useState<Map<number, FertilizerType>>(
new Map(),
Expand All @@ -41,8 +45,11 @@ const FertilizersSelector = ({ onChange, fertilizers }: Props) => {
setAvailableFertilizers(fertilizerMap)
setOptions(fertilizerOptions)
}
void fetchFertilizers()
}, [getApiClient, translateValue])
fetchFertilizers().catch((error: unknown) =>
openAlertSnackbar(getErrorMessage(error, translate('errors.fetch-fertilizers-failed')),
{ severity: 'error' })
)
}, [])

useEffect(() =>
fertilizers
Expand Down
12 changes: 10 additions & 2 deletions canopeum_frontend/src/components/analytics/MulchLayersSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { useTranslation } from 'react-i18next'

import OptionQuantitySelector, { type SelectorOption, type SelectorOptionQuantity } from '@components/analytics/OptionQuantitySelector'
import { LanguageContext } from '@components/context/LanguageContext'
import { SnackbarContext } from '@components/context/SnackbarContext'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import { MulchLayerType } from '@services/api'
import { notEmpty } from '@utils/arrayUtils'

Expand All @@ -17,6 +19,8 @@ const MulchLayersSelector = ({ onChange, mulchLayers }: Props) => {
const { t: translate } = useTranslation()
const { translateValue } = useContext(LanguageContext)
const { getApiClient } = useApiClient()
const { getErrorMessage } = useErrorHandling()
const { openAlertSnackbar } = useContext(SnackbarContext)

const [availableMulchLayers, setAvailableMulchLayers] = useState<Map<number, MulchLayerType>>(
new Map(),
Expand All @@ -41,8 +45,12 @@ const MulchLayersSelector = ({ onChange, mulchLayers }: Props) => {
setAvailableMulchLayers(mulchLayerMap)
setOptions(mulchLayerOptions)
}
void fetchMulchLayers()
}, [getApiClient, translateValue])
fetchMulchLayers().catch((error: unknown) =>
openAlertSnackbar(
getErrorMessage(error, translate('errors.fetch-mulch-layers-failed'))
)
)
}, [])

useEffect(() =>
mulchLayers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SnackbarContext } from '@components/context/SnackbarContext'
import ConfirmationDialog from '@components/dialogs/ConfirmationDialog'
import SearchBar from '@components/SearchBar'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import type { SiteSummary, User } from '@services/api'
import { PatchedSiteAdminUpdateRequest } from '@services/api'

Expand All @@ -22,6 +23,7 @@ const SiteSummaryActions = ({ siteSummary, admins, onSiteChange, onSiteEdit }: P
const { t: translate } = useTranslation()
const { openAlertSnackbar } = useContext(SnackbarContext)
const { getApiClient } = useApiClient()
const { getErrorMessage } = useErrorHandling()
const whisperRef = useRef<OverlayTriggerHandle>(null)

const [filteredAdmins, setFilteredAdmins] = useState(admins)
Expand Down Expand Up @@ -111,7 +113,11 @@ const SiteSummaryActions = ({ siteSummary, admins, onSiteChange, onSiteEdit }: P
return
}

void deleteSite()
deleteSite().catch((error: unknown)=>
openAlertSnackbar(
getErrorMessage(error, translate('errors.delete-site-failed'))
)
)
}

const administratorsSelection = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { useTranslation } from 'react-i18next'

import OptionQuantitySelector, { type SelectorOption, type SelectorOptionQuantity } from '@components/analytics/OptionQuantitySelector'
import { LanguageContext } from '@components/context/LanguageContext'
import { SnackbarContext } from '@components/context/SnackbarContext'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import { TreeType } from '@services/api'
import { notEmpty } from '@utils/arrayUtils'

Expand All @@ -17,6 +19,8 @@ const SupportSpeciesSelector = ({ onChange, species }: Props) => {
const { t: translate } = useTranslation()
const { translateValue } = useContext(LanguageContext)
const { getApiClient } = useApiClient()
const { getErrorMessage } = useErrorHandling()
const { openAlertSnackbar } = useContext(SnackbarContext)

const [availableSpecies, setAvailableSpecies] = useState<Map<number, TreeType>>(new Map())
const [options, setOptions] = useState<SelectorOption<number>[]>([])
Expand All @@ -39,8 +43,12 @@ const SupportSpeciesSelector = ({ onChange, species }: Props) => {
setAvailableSpecies(speciesMap)
setOptions(speciesOptions)
}
void fetchTreeSpecies()
}, [getApiClient, translateValue])
fetchTreeSpecies().catch((error: unknown) =>
openAlertSnackbar(
getErrorMessage(error, translate('errors.fetch-support-species-failed'))
)
)
}, [])

useEffect(() =>
species
Expand Down
12 changes: 10 additions & 2 deletions canopeum_frontend/src/components/analytics/TreeSpeciesSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { useTranslation } from 'react-i18next'

import OptionQuantitySelector, { type SelectorOption, type SelectorOptionQuantity } from '@components/analytics/OptionQuantitySelector'
import { LanguageContext } from '@components/context/LanguageContext'
import { SnackbarContext } from '@components/context/SnackbarContext'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import { Species, type TreeType } from '@services/api'
import { notEmpty } from '@utils/arrayUtils'

Expand All @@ -20,6 +22,8 @@ const TreeSpeciesSelector = (
const { t: translate } = useTranslation()
const { translateValue } = useContext(LanguageContext)
const { getApiClient } = useApiClient()
const { getErrorMessage } = useErrorHandling()
const { openAlertSnackbar } = useContext(SnackbarContext)

const [availableSpecies, setAvailableSpecies] = useState<Map<number, TreeType>>(new Map())
const [options, setOptions] = useState<SelectorOption<number>[]>([])
Expand All @@ -42,8 +46,12 @@ const TreeSpeciesSelector = (
setAvailableSpecies(speciesMap)
setOptions(speciesOptions)
}
void fetchTreeSpecies()
}, [getApiClient, translateValue])
fetchTreeSpecies().catch((error: unknown) =>
openAlertSnackbar(
getErrorMessage(error, translate('errors.fetch-tree-species-failed'))
)
)
}, [setAvailableSpecies, setOptions])

useEffect(() =>
species
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import ImageUpload from '@components/analytics/ImageUpload'
import SiteCoordinates from '@components/analytics/site-modal/SiteCoordinates'
import TreeSpeciesSelector from '@components/analytics/TreeSpeciesSelector'
import { LanguageContext } from '@components/context/LanguageContext'
import { SnackbarContext } from '@components/context/SnackbarContext'
import useApiClient from '@hooks/ApiClientHook'
import useErrorHandling from '@hooks/ErrorHandlingHook'
import { type DefaultCoordinate, defaultLatitude, defaultLongitude, extractCoordinate } from '@models/Coordinate'
import { type SiteType, Species } from '@services/api'
import { getApiBaseUrl } from '@services/apiSettings'
Expand Down Expand Up @@ -46,6 +48,8 @@ const SiteModal = ({ open, handleClose, siteId }: Props) => {
const { t } = useTranslation()
const { getApiClient } = useApiClient()
const { translateValue } = useContext(LanguageContext)
const { getErrorMessage } = useErrorHandling()
const { openAlertSnackbar } = useContext(SnackbarContext)

const [site, setSite] = useState(defaultSiteDto)
const [availableSiteTypes, setAvailableSiteTypes] = useState<SiteType[]>([])
Expand Down Expand Up @@ -84,23 +88,32 @@ const SiteModal = ({ open, handleClose, siteId }: Props) => {
setSiteImageURL(URL.createObjectURL(blob))
}, [siteId, getApiClient])

const fetchSiteTypes = useCallback(
async () => setAvailableSiteTypes(await getApiClient().siteClient.types()),
[getApiClient],
)

const onImageUpload = (file: File) => {
setSite(value => ({ ...value, siteImage: file }))
setSiteImageURL(URL.createObjectURL(file))
}

useEffect(() => void fetchSiteTypes(), [fetchSiteTypes])
useEffect(() => {
const fetchSiteTypes = async () =>
setAvailableSiteTypes(await getApiClient().siteClient.types())


fetchSiteTypes().catch((error: unknown) =>
openAlertSnackbar(
getErrorMessage(error, t('errors.fetch-site-types-failed'))
)
)
}, [])

useEffect(() => {
if (!open) return

void fetchSite()
}, [open, fetchSite])
fetchSite().catch((error: unknown) =>
openAlertSnackbar(
getErrorMessage(error, t('errors.fetch-site-failed'))
)
)
}, [])

useEffect(() => setSite(defaultSiteDto), [siteId])

Expand Down
Loading

0 comments on commit 6692ade

Please sign in to comment.