Skip to content

Commit

Permalink
Improve NotFound handling (#91)
Browse files Browse the repository at this point in the history
# Improve NotFound handling

## ♻️ Current situation & Problem
404 errors uses basic tanstack router not found.

## ⚙️ Release Notes 
* Improve NotFound handling


![image](https://github.com/user-attachments/assets/6f5c7cbd-1895-47ae-83b0-408e3c2be3d7)



### Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
arkadiuszbachorski authored Nov 11, 2024
1 parent 4707881 commit 41ceb1d
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 115 deletions.
34 changes: 34 additions & 0 deletions components/NotFound/NotFound.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// This source file is part of the Stanford Biodesign Digital Health ENGAGE-HF open-source project
//
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md)
//
// SPDX-License-Identifier: MIT
//

import { PageTitle } from '@stanfordspezi/spezi-web-design-system/molecules/DashboardLayout'
import {
NotFound as NotFoundBase,
type NotFoundProps,
} from '@stanfordspezi/spezi-web-design-system/molecules/NotFound'
import { useQuery } from '@tanstack/react-query'
import { RouteOff } from 'lucide-react'
import { currentUserQueryOptions } from '@/modules/firebase/UserProvider'
import { DashboardLayout } from '@/routes/~_dashboard/DashboardLayout'

/**
* NotFound component wrapped with DashboardLayout if user is signed in
* */
export const NotFound = (props: NotFoundProps) => {
const userQuery = useQuery(currentUserQueryOptions())

const notFound = <NotFoundBase {...props} />

return userQuery.data ?
<DashboardLayout
title={<PageTitle title="Not Found" icon={<RouteOff />} />}
>
{notFound}
</DashboardLayout>
: <div className="flex-center min-h-screen">{notFound}</div>
}
9 changes: 9 additions & 0 deletions components/NotFound/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//
// This source file is part of the Stanford Biodesign Digital Health ENGAGE-HF open-source project
//
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md)
//
// SPDX-License-Identifier: MIT
//

export * from './NotFound'
14 changes: 12 additions & 2 deletions main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@
// SPDX-License-Identifier: MIT
//

import { RouterProvider, createRouter } from '@tanstack/react-router'
import { createRouter, RouterProvider } from '@tanstack/react-router'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { NotFound } from '@/components/NotFound/NotFound'
import { routes } from '@/modules/routes'
import { routeTree } from './routeTree.gen'

const router = createRouter({ routeTree })
const router = createRouter({
routeTree,
defaultNotFoundComponent: () => (
<NotFound
backPage={{ name: 'home', href: routes.home }}
entityName="page"
/>
),
})

declare module '@tanstack/react-router' {
interface Register {
Expand Down
19 changes: 12 additions & 7 deletions modules/user/queries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import { UserType } from '@stanfordbdhg/engagehf-models'
import { queryOptions } from '@tanstack/react-query'
import { notFound } from '@tanstack/react-router'
import { query, where } from 'firebase/firestore'
import { docRefs, getCurrentUser, refs } from '@/modules/firebase/app'
import { type Invitation, type Organization } from '@/modules/firebase/models'
Expand Down Expand Up @@ -88,13 +87,13 @@ const getUserAuthData = async (userId: string) => {
displayName: data.auth.displayName,
}))
const authUser = allAuthData.at(0)
if (!authUser || !user) throw notFound()
if (!authUser || !user) return null
return { user, authUser, resourceType: 'user' as const }
}

const getUserInvitationData = async (userId: string) => {
const invitation = await getDocData(docRefs.invitation(userId))
if (!invitation) throw notFound()
if (!invitation) return null
if (!invitation.auth) throw new Error('Incomplete data')
return {
user: {
Expand Down Expand Up @@ -129,7 +128,13 @@ export const parseUserId = (userId: string) =>
export const getUserData = async (
userId: string,
resourceType: ResourceType,
) =>
resourceType === 'invitation' ?
getUserInvitationData(userId)
: getUserAuthData(userId)
validUserTypes: UserType[],
) => {
const data =
resourceType === 'invitation' ?
await getUserInvitationData(userId)
: await getUserAuthData(userId)
return data && validUserTypes.includes(data.user.type) ? data : null
}

export type UserData = Exclude<Awaited<ReturnType<typeof getUserData>>, null>
113 changes: 14 additions & 99 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@stanfordbdhg/engagehf-models": "^0.4.0",
"@stanfordspezi/spezi-web-design-system": "^0.1.0",
"@stanfordspezi/spezi-web-design-system": "^0.2.1",
"@t3-oss/env-core": "^0.11.1",
"@tanstack/react-query": "^5.59.19",
"@tanstack/react-router": "^1.78.3",
Expand Down
4 changes: 2 additions & 2 deletions routes/~_dashboard/~patients/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { mapAuthData } from '@/modules/firebase/user'
import { getDocsData, type ResourceType } from '@/modules/firebase/utils'
import { queryClient } from '@/modules/query/queryClient'
import {
type getUserData,
type UserData,
userOrganizationQueryOptions,
} from '@/modules/user/queries'
import { labsObservationCollections } from '@/routes/~_dashboard/~patients/clientUtils'
Expand Down Expand Up @@ -221,7 +221,7 @@ export const getUserActivity = async ({
user,
resourceType,
authUser,
}: Awaited<ReturnType<typeof getUserData>>) => {
}: UserData) => {
const latestQuestionnaires = await getDocsData(
query(
refs.questionnaireResponses({ resourceType, userId: authUser.uid }),
Expand Down
12 changes: 10 additions & 2 deletions routes/~_dashboard/~patients/~$id/~index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { createFileRoute, notFound, useRouter } from '@tanstack/react-router'
import { Contact } from 'lucide-react'
import { Helmet } from 'react-helmet'
import { z } from 'zod'
import { NotFound } from '@/components/NotFound'
import { callables, db, docRefs, refs } from '@/modules/firebase/app'
import {
getMedicationRequestData,
Expand All @@ -30,6 +31,7 @@ import {
getDocsData,
type ResourceType,
} from '@/modules/firebase/utils'
import { routes } from '@/modules/routes'
import { getUserData, parseUserId } from '@/modules/user/queries'
import {
Medications,
Expand Down Expand Up @@ -245,11 +247,17 @@ export const Route = createFileRoute('/_dashboard/patients/$id/')({
validateSearch: z.object({
tab: z.nativeEnum(PatientPageTab).optional().catch(undefined),
}),
notFoundComponent: () => (
<NotFound
entityName="patient"
backPage={{ name: 'patients list', href: routes.patients.index }}
/>
),
loader: async ({ params }) => {
const { userId, resourceType } = parseUserId(params.id)
const userData = await getUserData(userId, resourceType)
const userData = await getUserData(userId, resourceType, [UserType.patient])
if (!userData) throw notFound()
const { user, authUser } = userData
if (user.type !== UserType.patient) throw notFound()

return {
user,
Expand Down
17 changes: 15 additions & 2 deletions routes/~_dashboard/~users/~$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import { PageTitle } from '@stanfordspezi/spezi-web-design-system/molecules/Dash
import { createFileRoute, notFound, useRouter } from '@tanstack/react-router'
import { Users } from 'lucide-react'
import { Helmet } from 'react-helmet'
import { NotFound } from '@/components/NotFound'
import { callables, docRefs, ensureType } from '@/modules/firebase/app'
import { getDocDataOrThrow } from '@/modules/firebase/utils'
import { queryClient } from '@/modules/query/queryClient'
import { routes } from '@/modules/routes'
import {
getUserData,
parseUserId,
Expand Down Expand Up @@ -89,10 +91,21 @@ const UserPage = () => {
export const Route = createFileRoute('/_dashboard/users/$id')({
component: UserPage,
beforeLoad: () => ensureType([UserType.admin, UserType.owner]),
notFoundComponent: () => (
<NotFound
backPage={{ name: 'users list', href: routes.users.index }}
entityName="user"
/>
),
loader: async ({ params }) => {
const { resourceType, userId } = parseUserId(params.id)
const { user, authUser } = await getUserData(userId, resourceType)
if (user.type === UserType.patient) throw notFound()
const userData = await getUserData(userId, resourceType, [
UserType.clinician,
UserType.admin,
UserType.owner,
])
if (!userData) throw notFound()
const { user, authUser } = userData

return {
user,
Expand Down

0 comments on commit 41ceb1d

Please sign in to comment.