💄(frontend) add page 403
Add a page and integrate the design for the 403 error page.
This commit is contained in:
@@ -221,7 +221,7 @@ test.describe('Document list members', () => {
|
|||||||
await mySelfMoreActions.click();
|
await mySelfMoreActions.click();
|
||||||
await page.getByRole('button', { name: 'Delete' }).click();
|
await page.getByRole('button', { name: 'Delete' }).click();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText('You do not have permission to perform this action.'),
|
page.getByText('You do not have permission to view this document.'),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ test.describe('Doc Visibility: Restricted', () => {
|
|||||||
await page.goto(urlDoc);
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText('You do not have permission to perform this action.'),
|
page.getByText('You do not have permission to view this document.'),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
BIN
src/frontend/apps/impress/src/assets/icons/icon-403.png
Normal file
BIN
src/frontend/apps/impress/src/assets/icons/icon-403.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 267 KiB |
@@ -6,17 +6,27 @@ import { HEADER_HEIGHT, Header } from '@/features/header';
|
|||||||
import { LeftPanel } from '@/features/left-panel';
|
import { LeftPanel } from '@/features/left-panel';
|
||||||
import { useResponsiveStore } from '@/stores';
|
import { useResponsiveStore } from '@/stores';
|
||||||
|
|
||||||
export function PageLayout({ children }: PropsWithChildren) {
|
interface PageLayoutProps {
|
||||||
|
withFooter?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PageLayout({
|
||||||
|
children,
|
||||||
|
withFooter = true,
|
||||||
|
}: PropsWithChildren<PageLayoutProps>) {
|
||||||
const { isDesktop } = useResponsiveStore();
|
const { isDesktop } = useResponsiveStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box $minHeight="100vh" $margin={{ top: `${HEADER_HEIGHT}px` }}>
|
<Box
|
||||||
|
$minHeight={`calc(100vh - ${HEADER_HEIGHT}px)`}
|
||||||
|
$margin={{ top: `${HEADER_HEIGHT}px` }}
|
||||||
|
>
|
||||||
<Header />
|
<Header />
|
||||||
<Box as="main" $width="100%" $css="flex-grow:1;">
|
<Box as="main" $width="100%" $css="flex-grow:1;">
|
||||||
{!isDesktop && <LeftPanel />}
|
{!isDesktop && <LeftPanel />}
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
<Footer />
|
{withFooter && <Footer />}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
60
src/frontend/apps/impress/src/pages/403.tsx
Normal file
60
src/frontend/apps/impress/src/pages/403.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { Button } from '@openfun/cunningham-react';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import img403 from '@/assets/icons/icon-403.png';
|
||||||
|
import { Box, StyledLink, Text } from '@/components';
|
||||||
|
import { PageLayout } from '@/layouts';
|
||||||
|
import { NextPageWithLayout } from '@/types/next';
|
||||||
|
|
||||||
|
const StyledButton = styled(Button)`
|
||||||
|
width: fit-content;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Page: NextPageWithLayout = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
$align="center"
|
||||||
|
$margin="auto"
|
||||||
|
$gap="1rem"
|
||||||
|
$padding={{ bottom: '2rem' }}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={img403}
|
||||||
|
alt={t('Image 403')}
|
||||||
|
style={{
|
||||||
|
maxWidth: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box $align="center" $gap="0.8rem">
|
||||||
|
<Text as="p" $textAlign="center" $maxWidth="350px" $theme="primary">
|
||||||
|
{t('You do not have permission to view this document.')}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<StyledLink href="/">
|
||||||
|
<StyledButton
|
||||||
|
icon={
|
||||||
|
<Text $isMaterialIcon $color="white">
|
||||||
|
house
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('Home')}
|
||||||
|
</StyledButton>
|
||||||
|
</StyledLink>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Page.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
return <PageLayout withFooter={false}>{page}</PageLayout>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Page;
|
||||||
@@ -99,6 +99,11 @@ const DocPage = ({ id }: DocProps) => {
|
|||||||
}, [addTask, doc?.id, queryClient]);
|
}, [addTask, doc?.id, queryClient]);
|
||||||
|
|
||||||
if (isError && error) {
|
if (isError && error) {
|
||||||
|
if (error.status === 403) {
|
||||||
|
void replace(`/403`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (error.status === 404) {
|
if (error.status === 404) {
|
||||||
void replace(`/404`);
|
void replace(`/404`);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user