(app-desk) design static Header

Design static Header, we will add the interactivity later.
This commit is contained in:
Anthony LC
2024-01-18 14:04:46 +01:00
committed by Anthony LC
parent 5b4fe1e77f
commit 5062cac623
17 changed files with 185 additions and 23 deletions

View File

@@ -16,6 +16,7 @@ module.exports = {
},
rules: {
'block-scoped-var': 'error',
curly: ['error', 'all'],
'import/no-duplicates': ['error', { considerQueryString: false }],
'import/order': [
'error',
@@ -48,6 +49,10 @@ module.exports = {
],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error',
'react/jsx-curly-brace-presence': [
'error',
{ props: 'never', children: 'never', propElementValues: 'always' },
],
'sort-imports': [
'error',
{

View File

@@ -0,0 +1,82 @@
import { Button } from '@openfun/cunningham-react';
import Image from 'next/image';
import React from 'react';
import styled from 'styled-components';
import { Box, Text } from '@/components/';
import { default as IconCells } from './assets/icon-cells.svg';
import { default as IconDesk } from './assets/icon-desk.svg';
import { default as IconFAQ } from './assets/icon-faq.svg';
import { default as IconGouv } from './assets/icon-gouv.svg';
import { default as IconMarianne } from './assets/icon-marianne.svg';
const RedStripe = styled.div`
position: absolute;
height: 5px;
width: 100%;
background: var(--c--theme--colors--danger-500);
top: 0;
`;
const Header = () => {
return (
<Box
className="mb-l"
as="header"
$height="100px"
$width="100%"
$direction="column"
$justify="center"
$css="box-shadow: 0 1px 4px #00000040;"
>
<RedStripe />
<Box className="ml-l mr-l" $align="center" $justify="space-between">
<Box $direction="column">
<Image priority src={IconMarianne} alt="Marianne Logo" />
<Box $align="center" $gap="6rem">
<Image
priority
src={IconGouv}
alt="Freedom Equality Fraternity Logo"
/>
<Box $align="center" $gap="1rem">
<Image priority src={IconDesk} alt="Desk Logo" />
<Text className="m-0" as="h2">
Desk
</Text>
</Box>
</Box>
</Box>
<Box
$align="center"
$css={`
& > button {
padding: 0;
}
`}
$gap="5rem"
$justify="flex-end"
>
<Box $align="center">
<Button
aria-label="Access to FAQ"
icon={<Image priority src={IconFAQ} alt="FAQ Icon" />}
className="m-s c__button-no-bg p-0"
>
FAQ
</Button>
</Box>
<Button
aria-label="Access to the cells menu"
icon={<Image priority src={IconCells} alt="Cells icon" />}
color="tertiary"
className="c__button-no-bg p-0 m-0"
/>
</Box>
</Box>
</Box>
);
};
export default Header;

View File

@@ -0,0 +1,10 @@
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect opacity="0.1" x="1" y="1" width="58" height="58" rx="1" fill="white" stroke="#000091" stroke-width="2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.4103 24.6079L34.1507 27.3446V32.8178L29.4103 35.5544L24.6699 32.8178V27.3446L29.4103 24.6079Z" fill="#000091"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M34.7463 15L39.4867 17.7367V23.2099L34.7463 25.9465L30.0059 23.2099V17.7367L34.7463 15Z" fill="#000091"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M34.7463 34.0537L39.4867 36.7904V42.2636L34.7463 45.0002L30.0059 42.2636V36.7904L34.7463 34.0537Z" fill="#000091"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.7404 24.6079L23.4808 27.3446V32.8178L18.7404 35.5544L14 32.8178V27.3446L18.7404 24.6079Z" fill="#000091"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.0744 15L28.8148 17.7367V23.2099L24.0744 25.9465L19.334 23.2099V17.7367L24.0744 15Z" fill="#000091"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.0744 34.0537L28.8148 36.7904V42.2636L24.0744 45.0002L19.334 42.2636V36.7904L24.0744 34.0537Z" fill="#000091"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.2717 24.6079L45.0121 27.3446V32.8178L40.2717 35.5544L35.5312 32.8178V27.3446L40.2717 24.6079Z" fill="#000091"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,5 @@
<svg width="48" height="49" viewBox="0 0 48 49" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M41.7012 0.558594C45.1791 0.558594 47.9995 3.3445 47.9995 6.91157C47.9995 16.0522 47.9995 33.1064 47.9995 42.247C47.9995 45.7026 45.1791 48.6 41.7012 48.6C32.5048 48.6 15.5055 48.6 6.30916 48.6C2.82012 48.6 0 45.7026 0 42.247C0 33.1064 0 16.0522 0 6.91157C0 3.3445 2.82012 0.558594 6.30916 0.558594H41.7012Z" fill="white"/>
<path d="M35.0137 22.6992C35.6937 22.6992 36.3537 22.7792 37.0137 22.8792V13.2392L22.0137 6.69922L7.01367 13.2392V23.0592C7.01367 32.1392 13.4137 40.6392 22.0137 42.6992C23.1137 42.4392 24.1737 42.0592 25.2137 41.5992C23.8337 39.6392 23.0137 37.2592 23.0137 34.6992C23.0137 28.0792 28.3937 22.6992 35.0137 22.6992Z" fill="#000091"/>
<path d="M35.0137 26.6992C30.5937 26.6992 27.0137 30.2792 27.0137 34.6992C27.0137 39.1192 30.5937 42.6992 35.0137 42.6992C39.4337 42.6992 43.0137 39.1192 43.0137 34.6992C43.0137 30.2792 39.4337 26.6992 35.0137 26.6992ZM35.0137 29.4592C36.2537 29.4592 37.2537 30.4792 37.2537 31.6992C37.2537 32.9192 36.2337 33.9392 35.0137 33.9392C33.7937 33.9392 32.7737 32.9192 32.7737 31.6992C32.7737 30.4792 33.7737 29.4592 35.0137 29.4592ZM35.0137 40.1992C33.1537 40.1992 31.5337 39.2792 30.5337 37.8592C30.6337 36.4192 33.5537 35.6992 35.0137 35.6992C36.4737 35.6992 39.3937 36.4192 39.4937 37.8592C38.4937 39.2792 36.8737 40.1992 35.0137 40.1992Z" fill="#E1000F"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M21 3C21.5523 3 22 3.44772 22 4V18C22 18.5523 21.5523 19 21 19H6.455L2 22.5V4C2 3.44772 2.44772 3 3 3H21ZM20 5H4V18.385L5.763 17H20V5ZM13 14V16H11V14H13ZM12.4592 6.02822C14.2875 6.27003 15.6148 7.88878 15.4936 9.72908C15.3724 11.5694 13.8443 13.0001 12 13H11V11H12C12.7902 11 13.4448 10.387 13.4967 9.59851C13.5486 8.81006 12.9799 8.11655 12.1966 8.01295C11.4133 7.90935 10.6839 8.43117 10.529 9.206L8.567 8.813C8.92838 7.00447 10.6308 5.78641 12.4592 6.02822Z" fill="#000091"/>
</svg>

After

Width:  |  Height:  |  Size: 631 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -2,7 +2,7 @@ import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import fetchMock from 'fetch-mock';
import { WrapperReactQuery } from '@/tests/utils';
import { AppWrapper } from '@/tests/utils';
import { Teams } from '..';
@@ -25,7 +25,7 @@ describe('Teams', () => {
],
});
render(<Teams />, { wrapper: WrapperReactQuery });
render(<Teams />, { wrapper: AppWrapper });
expect(screen.getByRole('status')).toBeInTheDocument();

View File

@@ -9,12 +9,13 @@ export const Teams = () => {
const { mutate: createTeam } = useCreateTeam();
const [teamName, setTeamName] = useState('');
if (isPending)
if (isPending) {
return (
<div>
<Loader />
</div>
);
}
return (
<>

View File

@@ -2,13 +2,13 @@ import '@testing-library/jest-dom';
import { act, render, screen } from '@testing-library/react';
import useAuthStore from '@/auth/useAuthStore';
import { WrapperReactQuery } from '@/tests/utils';
import { AppWrapper } from '@/tests/utils';
import Page from '../page';
describe('Page', () => {
it('checks Page rendering', () => {
render(<Page />, { wrapper: WrapperReactQuery });
render(<Page />, { wrapper: AppWrapper });
expect(screen.getByRole('status')).toBeInTheDocument();
@@ -16,8 +16,6 @@ describe('Page', () => {
useAuthStore.setState({ authenticated: true });
});
expect(screen.getByRole('heading', { level: 2 })).toHaveTextContent(
'Hello world!',
);
expect(screen.getByRole('heading', { level: 2 })).toHaveTextContent('Desk');
});
});

View File

@@ -1 +1,6 @@
@import url('../cunningham/cunningham-style.css');
body {
margin: 0;
padding: 0;
}

View File

@@ -1,7 +0,0 @@
.main {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 6rem;
}

View File

@@ -5,8 +5,8 @@ import { useEffect } from 'react';
import useAuthStore from '@/auth/useAuthStore';
import Header from './Header/Header';
import { Teams } from './Teams';
import styles from './page.module.css';
export default function Home() {
const { initAuth, authenticated, initialized } = useAuthStore();
@@ -24,8 +24,8 @@ export default function Home() {
}
return (
<main className={styles.main}>
<h2>Hello world!</h2>
<main>
<Header />
<Teams />
</main>
);

View File

@@ -1,4 +1,8 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
declare module '*.svg' {
const content: string;
export default content;
}
namespace NodeJS {
interface ProcessEnv {

View File

@@ -1,7 +1,8 @@
import { CunninghamProvider } from '@openfun/cunningham-react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { PropsWithChildren } from 'react';
export const WrapperReactQuery = ({ children }: PropsWithChildren) => {
export const AppWrapper = ({ children }: PropsWithChildren) => {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
@@ -11,6 +12,8 @@ export const WrapperReactQuery = ({ children }: PropsWithChildren) => {
});
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
<QueryClientProvider client={queryClient}>
<CunninghamProvider theme="dsfr">{children}</CunninghamProvider>
</QueryClientProvider>
);
};

View File

@@ -7,9 +7,10 @@ test.beforeEach(async ({ page }) => {
await keyCloakSignIn(page);
});
test.describe('App', () => {
test('should display the homepage after keycloak login', async ({ page }) => {
await expect(page.locator('h2')).toContainText('Hello world!');
test.describe("App", () => {
test("should display the main elements", async ({ page }) => {
await expect(page.locator('header').first()).toContainText('Desk');
await expect(page.getByLabel('Team name')).toBeVisible();
});
test('creates 2 teams and displayed them', async ({ page }) => {

View File

@@ -0,0 +1,38 @@
import { expect, test } from "@playwright/test";
import { keyCloakSignIn } from "./common";
test.beforeEach(async ({ page }) => {
await page.goto("/");
await keyCloakSignIn(page);
});
test.describe("Header", () => {
test("checks all the elements are visible", async ({ page }) => {
const header = page.locator("header").first();
await expect(header.getByAltText("Marianne Logo")).toBeVisible();
await expect(
header.getByAltText("Freedom Equality Fraternity Logo"),
).toBeVisible();
await expect(header.getByAltText("Desk Logo")).toBeVisible();
await expect(header.locator("h2").getByText("Desk")).toHaveCSS(
"color",
"rgb(0, 0, 145)",
);
await expect(header.locator("h2").getByText("Desk")).toHaveCSS(
"font-family",
"marianne",
);
await expect(
header.getByRole("button", { name: "Access to FAQ" }),
).toBeVisible();
await expect(header.getByAltText("FAQ Icon")).toBeVisible();
await expect(header.getByText("FAQ")).toBeVisible();
await expect(header.getByAltText("Cells icon")).toBeVisible();
});
});