Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking โ€œSign up for GitHubโ€, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weekly branch merge to Develop branch #97

Merged
merged 60 commits into from
Nov 4, 2024
Merged
Changes from 1 commit
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
ae27adc
Refactor/#47 6์ฃผ์ฐจ ์ฝ”๋“œ๋ฆฌ๋ทฐ ๋ฆฌํŒฉํ† ๋ง (#48)
kang-kibong Oct 15, 2024
8355b25
Feat/#42, #43 ์ง€์›์ž ๋ชฉ๋ก ํŽ˜์ด์ง€ ๋ฐ ํŒ์—… ๊ตฌํ˜„ (#51)
KimJi-An Oct 16, 2024
89d9065
refactor: MyAccount ํŽ˜์ด์ง€ ๊ตฌ์กฐ ๋ณ€๊ฒฝ ๋ฐ CompanyRecruitments๋กœ ํŒŒ์ผ๋ช… ๋ณ€๊ฒฝ
KimJi-An Oct 16, 2024
55ba78b
refactor: visaRegistration ๊ด€๋ จ ํŒŒ์ผ ๊ตฌ์กฐ ๋ณ€๊ฒฝ
KimJi-An Oct 16, 2024
8923cea
feat: Table ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„
KimJi-An Oct 17, 2024
88e063a
feat: ๋ณ€๊ฒฝ๋œ ๊ณ ์šฉ์ฃผ ๋งˆ์ดํŽ˜์ด์ง€ ๊ตฌํ˜„
KimJi-An Oct 17, 2024
073a389
refactor: ํšŒ์‚ฌ ๊ด€๋ จ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ features/companies๋กœ ์ด๋™ ๋ฐ CompanyInfo ์ˆ˜์ •
KimJi-An Oct 17, 2024
26156cd
refactor: CompanyRecruitments ํŽ˜์ด์ง€ ์ด๋ฆ„์„ MyCompany๋กœ ๋ณ€๊ฒฝ
KimJi-An Oct 17, 2024
7925d21
feat: EmployerMyAccount path ์„ค์ •
KimJi-An Oct 17, 2024
018882d
refactor: ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ ์‚ญ์ œ ๋ฐ ํด๋”๋ช… ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๋ณ€๊ฒฝ
KimJi-An Oct 17, 2024
a20fddc
Feat/#50 Select ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#53)
kang-kibong Oct 18, 2024
83f4b89
refactor: EmployerMyAccount ํŽ˜์ด์ง€์—์„œ mock ๋ฐ์ดํ„ฐ ๋ถ„๋ฆฌ ๋ฐ ์ฝ”๋“œ ์ •๋ฆฌ
KimJi-An Oct 19, 2024
414f62a
refactor: visaRegistration ๋ฐ applicants ํŽ˜์ด์ง€์˜ mock, style ํŒŒ์ผ ๋ถ„๋ฆฌ
KimJi-An Oct 19, 2024
cc112d9
refactor: RecruitmentList ์ปดํฌ๋„ŒํŠธ ๋ฆฌํŒฉํ† ๋ง ๋ฐ RecruitmentsTable ๋ถ„๋ฆฌ
KimJi-An Oct 20, 2024
7442410
refactor: CompanyInfo ๋ฐ˜์‘ํ˜• ๋””์ž์ธ ์ˆ˜์ •
KimJi-An Oct 20, 2024
9458fab
refactor: ์™ธ๊ตญ์ธ ๋ฒˆํ˜ธ ๋ฐ ๋น„์ž ๋ฐœ๊ธ‰ ์ผ์ž ๋“ฑ๋ก ํŽ˜์ด์ง€ ์Šคํƒ€์ผ ์ˆ˜์ •
KimJi-An Oct 20, 2024
adc6008
refactor: Header ์ปดํฌ๋„ŒํŠธ์˜ ๋‹‰๋„ค์ž„ ๋ฒ„ํŠผ์„ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€๋กœ ๋ณ€๊ฒฝ
KimJi-An Oct 21, 2024
2d40e4f
Refactor/#54 Modal ์ปดํฌ๋„ŒํŠธ ์žฌ์„ค๊ณ„ (#55)
kang-kibong Oct 22, 2024
e0d26eb
refactor: ์ฝ”๋“œ ๋ฆฌ๋ทฐ ๋ฐ˜์˜
KimJi-An Oct 22, 2024
63d9a90
Feat/#56 ๋ฉ”์ธ ํŽ˜์ด์ง€ API ์—ฐ๋™ (#57)
kang-kibong Oct 23, 2024
64a27e0
Feat/#58 OAuth ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ ๊ตฌํ˜„ (#59)
kang-kibong Oct 23, 2024
a44ea1f
Feat/#60 ๊ฐ€์ž…์ž ์ •๋ณด ์„ ํƒ API ์—ฐ๋™ (#61)
kang-kibong Oct 23, 2024
763d0ef
Merge branch 'feat/#52' of https://github.com/KimJi-An/Team18_FE intoโ€ฆ
kang-kibong Oct 23, 2024
0c091e2
style: Button ์ปดํฌ๋„ŒํŠธ Props ์ด๋ฆ„๋ณ€๊ฒฝ theme->design
YIMSEBIN Oct 24, 2024
04b5241
feat: ๊ทผ๋กœ์ž๋งˆ์ดํŽ˜์ด์ง€ ์•„์ด์ฝ˜ ์„ค์ •
YIMSEBIN Oct 24, 2024
38bd68c
feat: ๊ทผ๋กœ์ž ๋งˆ์ดํŽ˜์ด์ง€ ๊ตฌํ˜„
YIMSEBIN Oct 24, 2024
8da4a9b
feat: ๊ทผ๋กœ์ž๋งˆ์ดํŽ˜์ด์ง€ ๋ผ์šฐํ„ฐ ์„ค์ •
YIMSEBIN Oct 24, 2024
9e1cc13
style: Button props ์ด๋ฆ„ ๋ณ€๊ฒฝ
YIMSEBIN Oct 24, 2024
bd85e56
feat: msw ์„ธํŒ… ๋ฐ API path ์ž‘์„ฑ
YIMSEBIN Oct 24, 2024
5210eeb
feat: ๊ตฌ์ธ๊ธ€ ๋“ฑ๋ก API ์—ฐ๊ฒฐ ๋ฐ msw ์„ธํŒ…
YIMSEBIN Oct 24, 2024
f3e1e2b
fix: ๊ตฌ์ธ๊ธ€ ์—…๋กœ๋“œ mock ํ•ธ๋“ค๋Ÿฌ ์ˆ˜์ •
YIMSEBIN Oct 24, 2024
20847b3
feat: ๊ทผ๋กœ์ž ๋งˆ์ดํŽ˜์ด์ง€ mock ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€
YIMSEBIN Oct 24, 2024
97fed35
feat: ๊ทผ๋กœ์ž ๋งˆ์ดํŽ˜์ด์ง€ API ์—ฐ๊ฒฐ ๋ฐ msw ์„ค์ •
YIMSEBIN Oct 24, 2024
19e1a90
feat: ์ด๋ ฅ์„œ ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#63)
tteokbokki-master Oct 24, 2024
ec1d9a6
Merge branch 'main' of https://github.com/YIMSEBIN/Team18_FE into Weekly
kang-kibong Oct 24, 2024
1bdf9eb
fix: change button prop
kang-kibong Oct 24, 2024
f4545c6
feat: add GitHub Actions workflow for linting and type checking
kang-kibong Oct 24, 2024
21c3b41
Feat/#74 ์‚ฌ์ธ ๋“ฑ๋ก ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#75)
tteokbokki-master Oct 28, 2024
7ad9fc4
Feat/#77 ํšŒ์‚ฌ ๋“ฑ๋ก ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#78)
YIMSEBIN Oct 28, 2024
89d3b41
Feat/#76 ์ง€์›์„œ ํŽ˜์ด์ง€ API ์—ฐ๋™(msw) (#79)
tteokbokki-master Oct 29, 2024
b2f35ed
Feat/#69 API ์—ฐ๋™ (#80)
KimJi-An Oct 29, 2024
4a4a27b
feat: ๊ทผ๋กœ๊ณ„์•ฝ์„œ path ์„ค์ •
YIMSEBIN Oct 30, 2024
684a542
Merge pull request #82 from YIMSEBIN/Weekly
YIMSEBIN Oct 30, 2024
ed7cd75
Feat/#81 ๊ตฌ์ธ ๊ธ€ ์ƒ์„ธ ํ™”๋ฉด ์ˆ˜์ • ๋ฐ API ์—ฐ๊ฒฐ (#83)
tteokbokki-master Oct 30, 2024
6d2d80e
Refactor/#71 9์ฃผ์ฐจ ๊ธฐ๋Šฅ ๊ฐœ์„  ๋ฐ ๋ฆฌํŒฉํ† ๋ง (#84)
KimJi-An Oct 30, 2024
c4383b3
Feat/#85 Header ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๋ฐ ๊ฐœ์„  (#87)
KimJi-An Oct 31, 2024
323d7ce
feat: ๊ทผ๋กœ์ž ๋งˆ์ดํŽ˜์ด์ง€ path ์—ฐ๊ฒฐ ์™„๋ฃŒ
YIMSEBIN Oct 31, 2024
5a2a46a
feat: ๊ตฌ์ธ๊ธ€ ์—…๋กœ๋“œ path ์—ฐ๊ฒฐ ์™„๋ฃŒ
YIMSEBIN Oct 31, 2024
096bc5c
feat: ํšŒ์‚ฌ ๋“ฑ๋ก API ์—ฐ๊ฒฐ
YIMSEBIN Oct 31, 2024
5bd6021
feat: i18n ๋ฒˆ์—ญ ๋ฐ์ดํ„ฐ - ๊ตฌ์ธ๊ธ€ ์—…๋กœ๋“œ, ๊ทผ๋กœ์ž ๋งˆ์ดํŽ˜์ด์ง€, ํšŒ์‚ฌ ๋“ฑ๋ก ํŽ˜์ด์ง€
YIMSEBIN Oct 31, 2024
139ea3e
refactor: ๊ตฌ์ธ๊ธ€ ์—…๋กœ๋“œ ๋ฐ ๊ทผ๋กœ์ž ๋งˆ์ดํŽ˜์ด์ง€ ํด๋”๊ตฌ์กฐ ์ •๋ฆฌ
YIMSEBIN Oct 31, 2024
13109cc
feat: ๊ณ ์šฉ์ฃผ ๊ทผ๋กœ๊ณ„์•ฝ์„œ ์ž‘์„ฑ API ์—ฐ๊ฒฐ ๋ฐ ๊ตฌ์ธ๊ธ€ ์ž‘์„ฑ API ํด๋”๊ตฌ์กฐ ์ •๋ฆฌ
YIMSEBIN Oct 31, 2024
d1dd3eb
feat: ๊ทผ๋กœ์ž ๊ทผ๋กœ๊ณ„์•ฝ์„œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ API ์—ฐ๊ฒฐ
YIMSEBIN Oct 31, 2024
17c16c9
feat: ๊ทผ๋กœ์ž ๊ทผ๋กœ๊ณ„์•ฝ์„œ ์ €์žฅํ•˜๊ธฐ API ์—ฐ๊ฒฐ
YIMSEBIN Oct 31, 2024
11e6f78
Merge pull request #89 from YIMSEBIN/Weekly
YIMSEBIN Nov 1, 2024
46f6372
Merge branch 'Develop' into Weekly
kang-kibong Nov 1, 2024
59c52ec
fix: ์ด์ „ merge๋œ ์ฝ”๋“œ์—์„œ ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜ ๋ฐ ์ž˜๋ชป๋œ ๋ถ€๋ถ„ ์ˆ˜์ •
KimJi-An Nov 1, 2024
48140ed
chore: npm ํŒจํ‚ค์ง€ ์—…๋ฐ์ดํŠธ
KimJi-An Nov 1, 2024
7f71e37
Merge pull request #94 from KimJi-An/fix
YIMSEBIN Nov 1, 2024
521ed2c
Merge branch 'Develop' into Weekly
kang-kibong Nov 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor/#54 Modal ์ปดํฌ๋„ŒํŠธ ์žฌ์„ค๊ณ„ (#55)
* chore: add loadable component package

* feat: implement modal management system with context and dynamic loading
  • Loading branch information
kang-kibong authored Oct 22, 2024

Verified

This commit was created on GitHub.com and signed with GitHubโ€™s verified signature.
commit 2d40e4fd513ba231c13b9452d92d24cff339ce0b
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ export default tseslint.config(
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'react-refresh/only-export-components': 'off',
'react-hooks/rules-of-hooks': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
},
);
42 changes: 40 additions & 2 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
"@emotion/css": "^11.13.0",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@loadable/component": "^5.16.4",
"@tanstack/react-query": "^5.56.2",
"csstype": "^3.1.3",
"react": "^18.3.1",
@@ -46,6 +47,7 @@
"@storybook/react": "^8.3.0",
"@storybook/react-vite": "^8.3.0",
"@storybook/test": "^8.3.0",
"@types/loadable__component": "^5.13.9",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-slick": "^0.23.13",
30 changes: 30 additions & 0 deletions src/components/common/Modal/Modals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useContext } from 'react';
import { ModalsDispatchContext, ModalsStateContext } from './index.context';
import loadable from '@loadable/component';

export interface ModalProps {
[key: string]: unknown;
}

export const modals = {
roleModal: loadable(() => import('@features/auth/SignUp/components/common/RoleModal')),
};

export default function Modals() {
const openedModals = useContext(ModalsStateContext);
const { close } = useContext(ModalsDispatchContext);

return openedModals.map((modal, index) => {
const { Component, props } = modal;
const { onSubmit, ...restProps } = props;

const handleClose = () => close(Component);

const handleSubmit = async () => {
if (typeof onSubmit === 'function') await onSubmit();
handleClose();
};

return <Component {...restProps} key={index} onClose={handleClose} onSubmit={handleSubmit} />;
});
}
19 changes: 19 additions & 0 deletions src/components/common/Modal/hooks/useModals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useContext } from 'react';
import { ModalsDispatchContext } from '../index.context';

export default function useModals() {
const { open, close } = useContext(ModalsDispatchContext);

const openModal = (Component: React.ComponentType<any>, props: any) => {
open(Component, props);
};

const closeModal = (Component: React.ComponentType<any>) => {
close(Component);
};

return {
openModal,
closeModal,
};
}
18 changes: 18 additions & 0 deletions src/components/common/Modal/index.context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createContext } from 'react';

interface ModalsDispatchContextProps {
open: (Component: React.ComponentType<any>, props: any) => void;
close: (Component: React.ComponentType<any>) => void;
}

export const ModalsDispatchContext = createContext<ModalsDispatchContextProps>({
open: () => {},
close: () => {},
});

interface ModalState {
Component: React.ComponentType<any>;
props: any;
}

export const ModalsStateContext = createContext<ModalState[]>([]);
5 changes: 2 additions & 3 deletions src/components/common/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -4,14 +4,13 @@ import { ReactNode } from 'react';
export type Props = {
textChildren: ReactNode;
buttonChildren: ReactNode;
borderRadius?: string;
onClose: () => void;
} & React.HTMLAttributes<HTMLDivElement>;

const Modal = ({ textChildren, buttonChildren, borderRadius = '12px', onClose, ...props }: Props) => {
const Modal = ({ textChildren, buttonChildren, onClose, ...props }: Props) => {
return (
<Overlay onClick={onClose}>
<Card borderRadius={borderRadius} {...props} onClick={(e) => e.stopPropagation()}>
<Card borderRadius="12px" {...props} onClick={(e) => e.stopPropagation()}>
<Wrapper>
<TextWrapper>{textChildren}</TextWrapper>
<ButtonWrapper>{buttonChildren}</ButtonWrapper>
29 changes: 29 additions & 0 deletions src/components/providers/Modals.provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ModalsDispatchContext, ModalsStateContext } from '../common/Modal/index.context';
import { PropsWithChildren, useState, useMemo } from 'react';

interface ModalState {
Component: React.ComponentType<any>;
props: any;
}

const ModalsProvider = ({ children }: PropsWithChildren<unknown>) => {
const [openedModals, setOpenedModals] = useState<ModalState[]>([]);

const open = (Component: React.ComponentType<any>, props: any) => {
setOpenedModals((modals) => [...modals, { Component, props }]);
};

const close = (Component: React.ComponentType<any>) => {
setOpenedModals((modals) => modals.filter((modal) => modal.Component !== Component));
};

const dispatch = useMemo(() => ({ open, close }), []);

return (
<ModalsStateContext.Provider value={openedModals}>
<ModalsDispatchContext.Provider value={dispatch}>{children}</ModalsDispatchContext.Provider>
</ModalsStateContext.Provider>
);
};

export default ModalsProvider;
11 changes: 10 additions & 1 deletion src/components/providers/index.provider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { ReactNode } from 'react';
import GlobalStylesProvider from './GlobalStylesProvider/index.provider';
import ModalsProvider from './Modals.provider';
import Modals from '../common/Modal/Modals';

export default function AppProviders({ children }: { children: ReactNode }) {
return <GlobalStylesProvider>{children}</GlobalStylesProvider>;
return (
<GlobalStylesProvider>
<ModalsProvider>
{children}
<Modals />
</ModalsProvider>
</GlobalStylesProvider>
);
}
13 changes: 5 additions & 8 deletions src/features/auth/SignUp/components/RoleSelection.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { Flex } from '@components/common';
import RoleSelector from './common/RoleSelector';
import { ReactNode } from 'react';

type Props = {
onRoleSelect: (modalContent: ReactNode) => void;
};
const FLEX_GAP_CONFIG = { x: '30px' };

export default function RoleSelection({ onRoleSelect }: Props) {
export default function RoleSelection() {
return (
<Flex justifyContent="center" alignItems="center" gap={{ x: '30px' }}>
<RoleSelector role="employer" onClick={onRoleSelect} />
<RoleSelector role="worker" onClick={onRoleSelect} />
<Flex justifyContent="center" alignItems="center" gap={FLEX_GAP_CONFIG}>
<RoleSelector role="employer" />
<RoleSelector role="worker" />
</Flex>
);
}
11 changes: 8 additions & 3 deletions src/features/auth/SignUp/components/common/RoleModal.tsx
Original file line number Diff line number Diff line change
@@ -6,10 +6,11 @@ const FLEX_GAP_CONFIG = { x: '16px' };

type Props = {
content: ReactNode;
onSubmit: () => void;
onClose: () => void;
};

export default function RoleModal({ content, onClose }: Props) {
export default function RoleModal({ content, onSubmit, onClose }: Props) {
return (
<Modal
textChildren={
@@ -27,8 +28,12 @@ export default function RoleModal({ content, onClose }: Props) {
}
buttonChildren={
<Flex gap={FLEX_GAP_CONFIG}>
<Button theme="default">๋“ฑ๋กํ• ๊ฒŒ์š”</Button>
<Button theme="outlined">๊ดœ์ฐฎ์•„์š”</Button>
<Button theme="default" onClick={() => onSubmit()}>
๋“ฑ๋กํ• ๊ฒŒ์š”
</Button>
<Button theme="outlined" onClick={() => onClose()}>
๊ดœ์ฐฎ์•„์š”
</Button>
</Flex>
}
onClose={onClose}
22 changes: 13 additions & 9 deletions src/features/auth/SignUp/components/common/RoleSelector/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Card, Flex, Typo } from '@components/common';
import { roleConfig } from './index.config';
import { bounceAnimation } from '@assets/styles/animations';
import { ReactNode } from 'react';
import { responsiveStyle } from '@utils/responsive';
import useModals from '@components/common/Modal/hooks/useModals';
import { modals } from '@/components/common/Modal/Modals';

const cardStyle = responsiveStyle({
default: { padding: '60px 120px', cursor: 'pointer' },
@@ -18,17 +19,20 @@ const iconStyle = responsiveStyle({

type Props = {
role: 'employer' | 'worker';
onClick: (modalContent: ReactNode) => void;
};

export default function RoleSelector({ role, onClick }: Props) {
export default function RoleSelector({ role }: Props) {
const { openModal } = useModals();

const handleClick = () => {
openModal(modals.roleModal, {
content: roleConfig[role].modalContent,
onSubmit: () => console.log('์ด๋ ฅ์„œ ๋“ฑ๋ก ํŽ˜์ด์ง€๋กœ ์ด๋™'),
});
};

return (
<Card
borderColor="blue"
borderRadius="12px"
css={[bounceAnimation, cardStyle]}
onClick={() => onClick(roleConfig[role].modalContent)}
>
<Card borderColor="blue" borderRadius="12px" css={[bounceAnimation, cardStyle]} onClick={handleClick}>
<Flex direction="column" alignItems="center">
<div css={iconStyle}>{roleConfig[role].icon}</div>
<Typo element="h2" color="blue" size="18px" bold>
14 changes: 1 addition & 13 deletions src/pages/auth/SignUp/index.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,20 @@
import { ReactNode, useState } from 'react';
import Layout from '@features/layout';
import { InnerContainer } from '@components/common';
import { responsiveStyle, responsiveSectionPadding } from '@utils/responsive';
import RoleSelection from '@/features/auth/SignUp/components/RoleSelection';
import RoleModal from '@/features/auth/SignUp/components/common/RoleModal';
import useToggle from '@hooks/useToggle';
import SignUpText from '@/features/auth/SignUp/components/SignUpText';

const sectionStyle = responsiveStyle(responsiveSectionPadding);

export default function SignUp() {
const [isToggle, toggle] = useToggle();
const [modalContent, setModalContent] = useState<ReactNode>();

const handleRoleSelect = (modalContent: ReactNode) => {
toggle();
setModalContent(modalContent);
};

return (
<Layout>
<section css={sectionStyle}>
<InnerContainer>
<SignUpText />
<RoleSelection onRoleSelect={handleRoleSelect} />
<RoleSelection />
</InnerContainer>
</section>
{isToggle && <RoleModal content={modalContent} onClose={toggle} />}
</Layout>
);
}