✨ feat(App): add page tracking

This commit is contained in:
2025-05-28 10:29:48 +00:00
parent bf6d945c61
commit e0f90d5d87
6 changed files with 77 additions and 41 deletions
+7
View File
@@ -1,7 +1,14 @@
import { render, screen } from '@testing-library/react' import { render, screen } from '@testing-library/react'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { useAnalytics } from 'use-analytics'
import App from './App' import App from './App'
// Mock the analytics module
vi.mock('use-analytics', () => ({
useAnalytics: () => ({ plugins: { enable: vi.fn(), disable: vi.fn() }, page: vi.fn() }),
}))
describe('App component', () => { describe('App component', () => {
test('renders MainPage without crashing', async () => { test('renders MainPage without crashing', async () => {
render(<App />) render(<App />)
+37 -31
View File
@@ -1,8 +1,8 @@
import React from 'react' import React from 'react'
import { createBrowserRouter, RouterProvider } from 'react-router-dom' import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import { Backdrop, CircularProgress } from '@mui/material'
import { ErrorPage } from 'components/pages' import ErrorPage from 'components/pages/ErrorPage/index.js'
import RootLayout from 'components/templates/RouteTracker/index.js'
const MainPage = React.lazy(() => import('components/pages/MainPage')) const MainPage = React.lazy(() => import('components/pages/MainPage'))
const ProjectsPage = React.lazy(() => import('components/pages/ProjectsPage')) const ProjectsPage = React.lazy(() => import('components/pages/ProjectsPage'))
@@ -18,36 +18,42 @@ const Loading = () => (
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
path: '/', path: '/',
element: ( element: <RootLayout />,
<React.Suspense fallback={<Loading />}>
<MainPage />
</React.Suspense>
),
errorElement: <ErrorPage />, errorElement: <ErrorPage />,
}, children: [
{ {
path: '/projects', index: true,
element: ( element: (
<React.Suspense fallback={<Loading />}> <React.Suspense fallback={<Loading />}>
<ProjectsPage /> <MainPage />
</React.Suspense> </React.Suspense>
), ),
}, },
{ {
path: '/curriculum', path: 'projects',
element: ( element: (
<React.Suspense fallback={<Loading />}> <React.Suspense fallback={<Loading />}>
<CurriculumPage /> <ProjectsPage />
</React.Suspense> </React.Suspense>
), ),
}, },
{ {
path: '/contacts', path: 'curriculum',
element: ( element: (
<React.Suspense fallback={<Loading />}> <React.Suspense fallback={<Loading />}>
<ContactPage /> <CurriculumPage />
</React.Suspense> </React.Suspense>
), ),
},
{
path: 'contacts',
element: (
<React.Suspense fallback={<Loading />}>
<ContactPage />
</React.Suspense>
),
},
],
}, },
]) ])
+1 -1
View File
@@ -100,7 +100,7 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
sx={{ sx={{
display: 'flex', display: 'flex',
// maxWidth: '100%', // maxWidth: '100%',
// [theme.breakpoints.up('md')]: { width: '80em', mx: 'auto' }, // [theme.breakpoints.up('md')]: { width: theme => theme.breakpoints.values.lg, mx: 'auto' },
}}> }}>
<IconButton <IconButton
color="primary" color="primary"
@@ -0,0 +1,19 @@
import { useEffect } from 'react'
import { useAnalytics } from 'use-analytics'
import { Outlet, useLocation } from 'react-router-dom'
/**
* Route tracking component that wraps all routes and includes analytics page tracking
*/
const RouteTracker = () => {
const location = useLocation()
const analytics = useAnalytics()
useEffect(() => {
analytics.page()
}, [analytics, location])
return <Outlet />
}
export default RouteTracker
+2 -1
View File
@@ -1 +1,2 @@
export { default as Page } from './Page' export { default as Page } from './Page/index.js'
export { default as RouteTracker } from './RouteTracker/index.js'
+11 -8
View File
@@ -1,19 +1,22 @@
/* istanbul ignore file */ /* istanbul ignore file */
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import { ThemeProvider } from '@mui/material/styles' import { AnalyticsProvider } from 'use-analytics'
import { CssBaseline } from '@mui/material' import { ThemeProvider, CssBaseline } from '@mui/material'
import App from './App.tsx' import analytics from 'components/utils/analytics/index.js'
import theme from 'style/theme.ts' import theme from 'style/theme.js'
import App from './App.js'
import './index.css' import './index.css'
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<ThemeProvider theme={theme}> <AnalyticsProvider instance={analytics}>
<CssBaseline /> <ThemeProvider theme={theme}>
<App /> <CssBaseline />
</ThemeProvider> <App />
</ThemeProvider>
</AnalyticsProvider>
</React.StrictMode> </React.StrictMode>
) )