🚚(app-desk) change next router to pages

2 routers exists in Next.js, "app" router and "page" router.
The "app" router has a bug introduced in Next.js 13.4.14, which is
not fixed yet. For the moment we cannot use dynamic routes with
"app" router with an SPA. As advised by the Next.js team, we
migrated to the "pages" router.
This commit is contained in:
Anthony LC
2024-02-07 15:31:13 +01:00
committed by Anthony LC
parent 7d90092020
commit f818715a45
25 changed files with 219 additions and 144 deletions

View File

@@ -1,6 +1,13 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true,
},
compiler: {
// Enables the styled-components SWC transform
styledComponents: true,
},
webpack(config) {
// Grab the existing rule that handles SVG imports
const fileLoaderRule = config.module.rules.find((rule) =>

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react';
import { AppWrapper } from '@/tests/utils';
import Page from '../page';
import Page from '../pages';
describe('Page', () => {
it('checks Page rendering', () => {

View File

@@ -1,7 +0,0 @@
'use client';
import { Box } from '@/components';
export default function Contacts() {
return <Box>Contacts</Box>;
}

View File

@@ -1,7 +0,0 @@
'use client';
import { Box } from '@/components';
export default function Favorite() {
return <Box>Favorite</Box>;
}

View File

@@ -1,7 +0,0 @@
'use client';
import { Box } from '@/components';
export default function Groups() {
return <Box>Groups</Box>;
}

View File

@@ -1,7 +0,0 @@
'use client';
import { Box } from '@/components';
export default function Help() {
return <Box>Help</Box>;
}

View File

@@ -1,37 +0,0 @@
'use client';
import { CunninghamProvider } from '@openfun/cunningham-react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { useCunninghamTheme } from '@/cunningham';
import { Auth } from '@/features/auth/Auth';
import '@/i18n/initI18n';
import InnerLayout from './InnerLayout';
import './globals.css';
const queryClient = new QueryClient();
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const { theme } = useCunninghamTheme();
return (
<html lang="en">
<body suppressHydrationWarning={process.env.NODE_ENV === 'development'}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<CunninghamProvider theme={theme}>
<Auth>
<InnerLayout>{children}</InnerLayout>
</Auth>
</CunninghamProvider>
</QueryClientProvider>
</body>
</html>
);
}

View File

@@ -1,35 +0,0 @@
'use client';
import { Button } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next';
import styled from 'styled-components';
import { Box, StyledLink } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { Panel } from '@/features/teams';
const StyledButton = styled(Button)`
width: fit-content;
`;
export default function Home() {
const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
return (
<Box $height="inherit" $direction="row">
<Panel />
<Box
$background={colorsTokens()['primary-bg']}
$justify="center"
$align="center"
$width="100%"
$gap="5rem"
>
<StyledLink href="/teams/create">
<StyledButton>{t('Create a new team')}</StyledButton>
</StyledLink>
</Box>
</Box>
);
}

View File

@@ -1,7 +0,0 @@
'use client';
import { Box } from '@/components';
export default function Recent() {
return <Box>Recent</Box>;
}

View File

@@ -1,27 +0,0 @@
'use client';
import { PropsWithChildren } from 'react';
import { Box } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { Panel } from '@/features/teams';
export default function Layout({ children }: PropsWithChildren) {
const { colorsTokens } = useCunninghamTheme();
return (
<Box $height="inherit" $direction="row">
<Panel />
<Box
$background={colorsTokens()['primary-bg']}
$justify="center"
$align="center"
$width="100%"
$gap="5rem"
$css="overflow:auto;"
>
{children}
</Box>
</Box>
);
}

View File

@@ -95,7 +95,6 @@ export const Header = () => {
priority
src={IconMyAccount}
alt={t(`Profile picture`)}
unoptimized
/>
</Box>
<Button

View File

@@ -0,0 +1,26 @@
import { CunninghamProvider } from '@openfun/cunningham-react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { useCunninghamTheme } from '@/cunningham';
import { Auth } from '@/features/auth/Auth';
import '@/i18n/initI18n';
const queryClient = new QueryClient();
export default function AppProvider({
children,
}: {
children: React.ReactNode;
}) {
const { theme } = useCunninghamTheme();
return (
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<CunninghamProvider theme={theme}>
<Auth>{children}</Auth>
</CunninghamProvider>
</QueryClientProvider>
);
}

View File

@@ -2,17 +2,17 @@ import { Box } from '@/components';
import { HEADER_HEIGHT, Header } from '@/features/header';
import { Menu } from '@/features/menu';
export default function InnerLayout({
export default function MainLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<Box as="main" $height="100vh" $css="overflow:hidden;">
<Box $height="100vh" $css="overflow:hidden;">
<Header />
<Box $css="flex: 1;" $direction="row">
<Menu />
<Box $height={`calc(100vh - ${HEADER_HEIGHT})`} $width="100%">
<Box as="main" $height={`calc(100vh - ${HEADER_HEIGHT})`} $width="100%">
{children}
</Box>
</Box>

View File

@@ -0,0 +1,28 @@
import type { AppProps } from 'next/app';
import Head from 'next/head';
import { useTranslation } from 'react-i18next';
import { NextPageWithLayout } from '@/types/next';
import AppProvider from './AppProvider';
import './globals.css';
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
export default function App({ Component, pageProps }: AppPropsWithLayout) {
const getLayout = Component.getLayout ?? ((page) => page);
const { t } = useTranslation();
return (
<>
<Head>
<title>{t('People')}</title>
<meta name="description" content={t('People Description')} />
<link rel="icon" href="/favicon.ico" sizes="any" />
</Head>
<AppProvider>{getLayout(<Component {...pageProps} />)}</AppProvider>
</>
);
}

View File

@@ -0,0 +1,15 @@
import { Head, Html, Main, NextScript } from 'next/document';
import '@/i18n/initI18n';
export default function RootLayout() {
return (
<Html lang="en">
<Head />
<body suppressHydrationWarning={process.env.NODE_ENV === 'development'}>
<Main />
<NextScript />
</body>
</Html>
);
}

View File

@@ -0,0 +1,16 @@
import { ReactElement } from 'react';
import { Box } from '@/components';
import { NextPageWithLayout } from '@/types/next';
import MainLayout from '../MainLayout';
const Page: NextPageWithLayout = () => {
return <Box>Contacts</Box>;
};
Page.getLayout = function getLayout(page: ReactElement) {
return <MainLayout>{page}</MainLayout>;
};
export default Page;

View File

@@ -0,0 +1,16 @@
import { ReactElement } from 'react';
import { Box } from '@/components';
import { NextPageWithLayout } from '@/types/next';
import MainLayout from '../MainLayout';
const Page: NextPageWithLayout = () => {
return <Box>Favorite</Box>;
};
Page.getLayout = function getLayout(page: ReactElement) {
return <MainLayout>{page}</MainLayout>;
};
export default Page;

View File

@@ -0,0 +1,16 @@
import { ReactElement } from 'react';
import { Box } from '@/components';
import { NextPageWithLayout } from '@/types/next';
import MainLayout from '../MainLayout';
const Page: NextPageWithLayout = () => {
return <Box>Groups</Box>;
};
Page.getLayout = function getLayout(page: ReactElement) {
return <MainLayout>{page}</MainLayout>;
};
export default Page;

View File

@@ -0,0 +1,29 @@
import { Button } from '@openfun/cunningham-react';
import type { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import styled from 'styled-components';
import { StyledLink } from '@/components';
import { NextPageWithLayout } from '@/types/next';
import TeamLayout from './teams/TeamLayout';
const StyledButton = styled(Button)`
width: fit-content;
`;
const Page: NextPageWithLayout = () => {
const { t } = useTranslation();
return (
<StyledLink href="/teams/create">
<StyledButton>{t('Create a new team')}</StyledButton>
</StyledLink>
);
};
Page.getLayout = function getLayout(page: ReactElement) {
return <TeamLayout>{page}</TeamLayout>;
};
export default Page;

View File

@@ -0,0 +1,16 @@
import { ReactElement } from 'react';
import { Box } from '@/components';
import { NextPageWithLayout } from '@/types/next';
import MainLayout from '../MainLayout';
const Page: NextPageWithLayout = () => {
return <Box>Recent</Box>;
};
Page.getLayout = function getLayout(page: ReactElement) {
return <MainLayout>{page}</MainLayout>;
};
export default Page;

View File

@@ -0,0 +1,29 @@
import { PropsWithChildren } from 'react';
import { Box } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { Panel } from '@/features/teams';
import MainLayout from '../MainLayout';
export default function TeamLayout({ children }: PropsWithChildren) {
const { colorsTokens } = useCunninghamTheme();
return (
<MainLayout>
<Box $height="inherit" $direction="row">
<Panel />
<Box
$background={colorsTokens()['primary-bg']}
$justify="center"
$align="center"
$width="100%"
$gap="5rem"
$css="overflow:auto;"
>
{children}
</Box>
</Box>
</MainLayout>
);
}

View File

@@ -1,12 +1,13 @@
'use client';
import { Button, Field, Input } from '@openfun/cunningham-react';
import { useState } from 'react';
import { ReactElement, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useCreateTeam } from '@/features/teams';
import { NextPageWithLayout } from '@/types/next';
export default function Page() {
import TeamLayout from './TeamLayout';
const Page: NextPageWithLayout = () => {
const { t } = useTranslation();
const { mutate: createTeam } = useCreateTeam();
const [teamName, setTeamName] = useState('');
@@ -23,4 +24,10 @@ export default function Page() {
</Button>
</Field>
);
}
};
Page.getLayout = function getLayout(page: ReactElement) {
return <TeamLayout>{page}</TeamLayout>;
};
export default Page;

View File

@@ -0,0 +1,5 @@
import type { NextPage } from 'next';
export type NextPageWithLayout = NextPage & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
};