= (args) => {
+ return ;
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ children: "modal text",
+};
+
+export const LongContent = Template.bind({});
+
+LongContent.args = {
+ children: (
+ <>
+
+ 대통령은 국무회의의 의장이 되고, 국무총리는 부의장이 된다. 군인·군무원·경찰공무원 기타
+ 법률이 정하는 자가 전투·훈련등 직무집행과 관련하여 받은 손해에 대하여는 법률이 정하는
+ 보상외에 국가 또는 공공단체에 공무원의 직무상 불법행위로 인한 배상은 청구할 수 없다.
+ 국가원로자문회의의 의장은 직전대통령이 된다. 다만, 직전대통령이 없을 때에는 대통령이
+ 지명한다. 훈장등의 영전은 이를 받은 자에게만 효력이 있고, 어떠한 특권도 이에 따르지
+ 아니한다. 국정감사 및 조사에 관한 절차 기타 필요한 사항은 법률로 정한다. 국가는 모성의
+ 보호를 위하여 노력하여야 한다. 대법원장과 대법관이 아닌 법관의 임기는 10년으로 하며, 법률이
+ 정하는 바에 의하여 연임할 수 있다.
+
+
+
+ 대통령은 법률안의 일부에 대하여 또는 법률안을 수정하여 재의를 요구할 수 없다.
+ 저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 모든 국민은 근로의 의무를
+ 진다. 국가는 근로의 의무의 내용과 조건을 민주주의원칙에 따라 법률로 정한다. 제1항의
+ 해임건의는 국회재적의원 3분의 1 이상의 발의에 의하여 국회재적의원 과반수의 찬성이 있어야
+ 한다. 국가는 농·어민과 중소기업의 자조조직을 육성하여야 하며, 그 자율적 활동과 발전을
+ 보장한다. 한 회계연도를 넘어 계속하여 지출할 필요가 있을 때에는 정부는 연한을 정하여
+ 계속비로서 국회의 의결을 얻어야 한다. 근로조건의 기준은 인간의 존엄성을 보장하도록 법률로
+ 정한다.
+
+ >
+ ),
+};
diff --git a/frontend/src/components/@common/ModalWindow/ModalWindow.tsx b/frontend/src/components/@common/ModalWindow/ModalWindow.tsx
new file mode 100644
index 000000000..cc9ee9e3d
--- /dev/null
+++ b/frontend/src/components/@common/ModalWindow/ModalWindow.tsx
@@ -0,0 +1,20 @@
+import classNames from "classnames";
+import styles from "./ModalWindow.module.css";
+
+type ModalWindowProps = Omit, "role" | "aria-label">;
+
+const ModalWindow = ({ className, children, ...props }: ModalWindowProps) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default ModalWindow;
diff --git a/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.module.css b/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.module.css
new file mode 100644
index 000000000..f5b644b95
--- /dev/null
+++ b/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.module.css
@@ -0,0 +1,69 @@
+.box {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+ overflow: hidden;
+}
+
+.title {
+ font-size: 2rem;
+ font-weight: bold;
+}
+
+.content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 2.5rem;
+ overflow-y: auto;
+ font-size: 0.875rem;
+ line-height: 1.4rem;
+ text-align: justify;
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+
+.content::-webkit-scrollbar {
+ display: none;
+}
+
+.application-item-box {
+ display: flex;
+ flex-direction: column;
+}
+
+.application-item-title {
+ font-size: 1.125rem;
+ font-weight: bold;
+ margin-bottom: 0.5rem;
+}
+
+.application-item-description {
+ color: var(--gray-008);
+ margin-bottom: 0.5rem;
+}
+
+.application-item-answer-length {
+ color: var(--gray-007);
+ align-self: flex-end;
+}
+
+.application-item-answer {
+ white-space: pre-line;
+ word-break: break-all;
+}
+
+.application-item-url {
+ text-decoration: underline;
+}
+
+.button-box {
+ display: flex;
+ justify-content: center;
+ gap: 1rem;
+}
+
+.button {
+ width: 12rem;
+ max-width: 100%;
+}
diff --git a/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.stories.tsx b/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.stories.tsx
new file mode 100644
index 000000000..d4bb32a43
--- /dev/null
+++ b/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.stories.tsx
@@ -0,0 +1,45 @@
+import { ComponentMeta, ComponentStory } from "@storybook/react";
+import useModalContext from "../../hooks/useModalContext";
+import { recruitmentItemDummy } from "../../mock/dummy";
+import Button, { BUTTON_VARIANT } from "../@common/Button/Button";
+import ApplicationPreviewModal from "./ApplicationPreviewModal";
+
+export default {
+ title: "components/ApplicationPreviewModal",
+ component: ApplicationPreviewModal,
+} as ComponentMeta;
+
+const Template: ComponentStory = (args) => {
+ const { Modal, openModal } = useModalContext();
+
+ return (
+
+ );
+};
+
+export const Default = Template.bind({});
+
+Default.args = {
+ recruitmentItems: recruitmentItemDummy,
+ answers: [
+ "국가는 과학기술의 혁신과 정보 및 인력의 개발을 통하여 국민경제의 발전에 노력하여야 한다. 모든 국민은 법률이 정하는 바에 의하여 공무담임권을 가진다. 중앙선거관리위원회는 법령의 범위안에서 선거관리·국민투표관리 또는 정당사무에 관한 규칙을 제정할 수 있으며, 법률에 저촉되지 아니하는 범위안에서 내부규율에 관한 규칙을 제정할 수 있다.\n중앙선거관리위원회는 대통령이 임명하는 3인, 국회에서 선출하는 3인과 대법원장이 지명하는 3인의 위원으로 구성한다. 위원장은 위원중에서 호선한다. 재의의 요구가 있을 때에는 국회는 재의에 붙이고, 재적의원과반수의 출석과 출석의원 3분의 2 이상의 찬성으로 전과 같은 의결을 하면 그 법률안은 법률로서 확정된다.\n 헌법재판소의 조직과 운영 기타 필요한 사항은 법률로 정한다. 정부는 회계연도마다 예산안을 편성하여 회계연도 개시 90일전까지 국회에 제출하고, 국회는 회계연도 개시 30일전까지 이를 의결하여야 한다. 모든 국민은 양심의 자유를 가진다. 국가는 건전한 소비행위를 계도하고 생산품의 품질향상을 촉구하기 위한 소비자보호운동을 법률이 정하는 바에 의하여 보장한다.",
+ "모든 국민은 헌법과 법률이 정한 법관에 의하여 법률에 의한 재판을 받을 권리를 가진다. 공무원은 국민전체에 대한 봉사자이며, 국민에 대하여 책임을 진다. 정부는 예산에 변경을 가할 필요가 있을 때에는 추가경정예산안을 편성하여 국회에 제출할 수 있다. 모든 국민은 소급입법에 의하여 참정권의 제한을 받거나 재산권을 박탈당하지 아니한다. 이 헌법에 의한 최초의 대통령의 임기는 이 헌법시행일로부터 개시한다. 국회는 헌법개정안이 공고된 날로부터 60일 이내에 의결하여야 하며, 국회의 의결은 재적의원 3분의 2 이상의 찬성을 얻어야 한다. 대통령이 궐위된 때 또는 대통령 당선자가 사망하거나 판결 기타의 사유로 그 자격을 상실한 때에는 60일 이내에 후임자를 선거한다.\n감사원의 조직·직무범위·감사위원의 자격·감사대상공무원의 범위 기타 필요한 사항은 법률로 정한다. 각급 선거관리위원회는 선거인명부의 작성등 선거사무와 국민투표사무에 관하여 관계 행정기관에 필요한 지시를 할 수 있다. 모든 국민은 종교의 자유를 가진다. 국가의 세입·세출의 결산, 국가 및 법률이 정한 단체의 회계검사와 행정기관 및 공무원의 직무에 관한 감찰을 하기 위하여 대통령 소속하에 감사원을 둔다. 혼인과 가족생활은 개인의 존엄과 양성의 평등을 기초로 성립되고 유지되어야 하며, 국가는 이를 보장한다. 대통령은 국민의 보통·평등·직접·비밀선거에 의하여 선출한다. 지방의회의 조직·권한·의원선거와 지방자치단체의 장의 선임방법 기타 지방자치단체의 조직과 운영에 관한 사항은 법률로 정한다.\n재판의 전심절차로서 행정심판을 할 수 있다. 행정심판의 절차는 법률로 정하되, 사법절차가 준용되어야 한다. 공무원의 직무상 불법행위로 손해를 받은 국민은 법률이 정하는 바에 의하여 국가 또는 공공단체에 정당한 배상을 청구할 수 있다. 이 경우 공무원 자신의 책임은 면제되지 아니한다. 모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 국가는 개인이 가지는 불가침의 기본적 인권을 확인하고 이를 보장할 의무를 진다. 대통령은 국무회의의 의장이 되고, 국무총리는 부의장이 된다. 모든 국민은 행위시의 법률에 의하여 범죄를 구성하지 아니하는 행위로 소추되지 아니하며, 동일한 범죄에 대하여 거듭 처벌받지 아니한다.\n국회의 정기회는 법률이 정하는 바에 의하여 매년 1회 집회되며, 국회의 임시회는 대통령 또는 국회재적의원 4분의 1 이상의 요구에 의하여 집회된다. 모든 국민은 근로의 권리를 가진다. 국가는 사회적·경제적 방법으로 근로자의 고용의 증진과 적정임금의 보장에 노력하여야 하며, 법률이 정하는 바에 의하여 최저임금제를 시행하여야 한다. 국무회의는 대통령·국무총리와 15인 이상 30인 이하의 국무위원으로 구성한다. 국방상 또는 국민경제상 긴절한 필요로 인하여 법률이 정하는 경우를 제외하고는, 사영기업을 국유 또는 공유로 이전하거나 그 경영을 통제 또는 관리할 수 없다. 군사법원의 조직·권한 및 재판관의 자격은 법률로 정한다.",
+ ],
+ referenceUrl: "https://apply.techcourse.co.kr/",
+ onClickConfirmButton: () => {
+ alert("confirmed");
+ },
+};
diff --git a/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.tsx b/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.tsx
new file mode 100644
index 000000000..1547fa8f0
--- /dev/null
+++ b/frontend/src/components/ApplicationPreviewModal/ApplicationPreviewModal.tsx
@@ -0,0 +1,105 @@
+import { useState } from "react";
+import useModalContext from "../../hooks/useModalContext";
+import Button, { BUTTON_VARIANT } from "../@common/Button/Button";
+import styles from "./ApplicationPreviewModal.module.css";
+import CheckBox from "../form/CheckBox/CheckBox";
+import { RecruitmentItem } from "../../../types/domains/recruitments";
+import { Answer, ApplicationForm } from "../../../types/domains/applicationForms";
+
+type ApplicationPreviewModalProps = {
+ recruitmentItems: RecruitmentItem[];
+ answers: Answer["contents"][];
+ referenceUrl: ApplicationForm["referenceUrl"];
+ onClickConfirmButton: React.MouseEventHandler;
+};
+
+const ApplicationPreviewModal = ({
+ recruitmentItems,
+ answers,
+ referenceUrl,
+ onClickConfirmButton,
+}: ApplicationPreviewModalProps) => {
+ const { closeModal } = useModalContext();
+ const [isChecked, setIsChecked] = useState(false);
+
+ const handleChangeConfirmCheckbox: React.FormEventHandler = (e) => {
+ setIsChecked((e.target as HTMLInputElement).checked);
+ };
+
+ const handleClickDismissButton: React.MouseEventHandler = () => {
+ closeModal();
+ };
+
+ const handleClickConfirmButton: React.MouseEventHandler = (e) => {
+ onClickConfirmButton(e);
+ closeModal();
+ };
+
+ return (
+
+
+ 지원서 미리보기
+
+
+ {recruitmentItems.map((recruitmentItem, index) => (
+
+
+ {recruitmentItem.position}. {recruitmentItem.title}
+
+
+ {recruitmentItem.description}
+
+
+ {answers[index].length} / {recruitmentItem.maximumLength}
+
+
{answers[index]}
+
+ ))}
+
+
+
+
+
+
+
+ 취소
+
+
+ 최종 제출
+
+
+
+ );
+};
+
+export default ApplicationPreviewModal;
diff --git a/frontend/src/components/Header/Header.stories.js b/frontend/src/components/Header/Header.stories.js
index 703f04b4e..0080ffc68 100644
--- a/frontend/src/components/Header/Header.stories.js
+++ b/frontend/src/components/Header/Header.stories.js
@@ -1,9 +1,22 @@
-import React from "react";
+import { MemoryRouter, Route } from "react-router-dom";
import Header from "./Header";
export default {
title: "components/Header",
component: Header,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => ;
diff --git a/frontend/src/constants/messages.ts b/frontend/src/constants/messages.ts
index 06025173b..205fc4584 100644
--- a/frontend/src/constants/messages.ts
+++ b/frontend/src/constants/messages.ts
@@ -40,6 +40,7 @@ export const ERROR_MESSAGE = {
CANNOT_FIND_RECRUITMENT_CONTEXT: "recruitmentContext가 존재하지 않습니다",
CANNOT_FIND_TOKEN_CONTEXT: "TokenContext가 존재하지 않습니다",
CANNOT_FIND_USER_INFO_CONTEXT: "UserInfoContext가 존재하지 않습니다",
+ CANNOT_FIND_MODAL_CONTEXT: "ModalContext가 존재하지 않습니다",
},
} as const;
@@ -54,7 +55,6 @@ export const SUCCESS_MESSAGE = {
} as const;
export const CONFIRM_MESSAGE = {
- SUBMIT_APPLICATION: "제출하신 뒤에는 수정하실 수 없습니다. 정말로 제출하시겠습니까?",
RESET_APPLICATION: "정말 초기화하시겠습니까?",
CANCEL_ASSIGNMENT_SUBMIT: "정말 취소하시겠습니까? 작성하신 내용이 저장되지 않습니다.",
} as const;
diff --git a/frontend/src/hooks/useModalContext.tsx b/frontend/src/hooks/useModalContext.tsx
new file mode 100644
index 000000000..251b0700f
--- /dev/null
+++ b/frontend/src/hooks/useModalContext.tsx
@@ -0,0 +1,58 @@
+import React, { useState, useContext, createContext } from "react";
+import ModalWindow from "../components/@common/ModalWindow/ModalWindow";
+import ModalPortal from "../components/@common/ModalPortal/ModalPortal";
+import { ERROR_MESSAGE } from "../constants/messages";
+
+export type ModalContextValue = {
+ Modal: (props: { children: NonNullable }) => JSX.Element | null;
+ openModal: () => void;
+ closeModal: () => void;
+};
+
+type ModalProviderProps = { children: React.ReactNode };
+
+const ModalContext = createContext(null);
+
+export const ModalProvider = ({ children }: ModalProviderProps) => {
+ const [isModalOpened, setIsModalOpened] = useState(false);
+
+ const openModal: ModalContextValue["openModal"] = () => {
+ document.body.style.overflow = "hidden";
+ setIsModalOpened(true);
+ };
+
+ const closeModal: ModalContextValue["closeModal"] = () => {
+ document.body.style.overflow = "auto";
+ setIsModalOpened(false);
+ };
+
+ const Modal: ModalContextValue["Modal"] = ({ children, ...props }) => {
+ if (isModalOpened) {
+ return (
+
+ {children}
+
+ );
+ }
+
+ return null;
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+const useModalContext = () => {
+ const modalContext = useContext(ModalContext);
+
+ if (!modalContext) {
+ throw Error(ERROR_MESSAGE.HOOKS.CANNOT_FIND_MODAL_CONTEXT);
+ }
+
+ return modalContext;
+};
+
+export default useModalContext;
diff --git a/frontend/src/mock/dummy.ts b/frontend/src/mock/dummy.ts
index f73af3a29..bb30a1d55 100644
--- a/frontend/src/mock/dummy.ts
+++ b/frontend/src/mock/dummy.ts
@@ -53,6 +53,27 @@ export const recruitmentDummy = [
},
];
+export const recruitmentItemDummy = [
+ {
+ id: 1,
+ recruitmentId: 1,
+ title: "프로그래밍 학습 과정과 현재 자신이 생각하는 역량은",
+ position: 1,
+ maximumLength: 1000,
+ description:
+ "우아한테크코스는 프로그래밍에 대한 기본 지식과 경험을 가진 교육생을 선발하기 때문에 프로그래밍 경험이 있는 상태에서 지원하게 됩니다. 프로그래밍 학습을 어떤 계기로 시작했으며, 어떻게 학습해왔는지, 이를 통해 현재 어느 정도의 역량을 보유한 상태인지를 구체적으로 작성해 주세요.",
+ },
+ {
+ id: 2,
+ recruitmentId: 1,
+ title: "프로그래머가 되려는 이유는 무엇인가요?",
+ position: 2,
+ maximumLength: 1000,
+ description:
+ "어떤 계기로 프로그래머라는 직업을 꿈꾸게 되었나요? 프로그래밍을 배워 최종적으로 하고 싶은 일이 무엇인지, 프로그래밍을 통해 만들고 싶은 소프트웨어가 있다면 무엇인지에 대해 작성해 주세요.",
+ },
+];
+
export const myApplicationDummy = [
{
recruitmentId: 4,
diff --git a/frontend/src/pages/ApplicationRegister/ApplicationRegister.js b/frontend/src/pages/ApplicationRegister/ApplicationRegister.js
index cb90fd913..c7d5890cc 100644
--- a/frontend/src/pages/ApplicationRegister/ApplicationRegister.js
+++ b/frontend/src/pages/ApplicationRegister/ApplicationRegister.js
@@ -9,12 +9,14 @@ import MessageTextarea from "../../components/@common/MessageTextarea/MessageTex
import MessageTextInput from "../../components/@common/MessageTextInput/MessageTextInput";
import CheckBox from "../../components/form/CheckBox/CheckBox";
import Form from "../../components/form/Form/Form";
+import ApplicationPreviewModal from "../../components/ApplicationPreviewModal/ApplicationPreviewModal";
import { FORM } from "../../constants/form";
-import { CONFIRM_MESSAGE, SUCCESS_MESSAGE } from "../../constants/messages";
+import { SUCCESS_MESSAGE } from "../../constants/messages";
import { PATH, PARAM } from "../../constants/path";
import useApplicationRegisterForm, {
APPLICATION_REGISTER_FORM_NAME,
} from "../../hooks/useApplicationRegisterForm";
+import useModalContext from "../../hooks/useModalContext";
import useRecruitmentItem from "../../hooks/useRecruitmentItem";
import useTokenContext from "../../hooks/useTokenContext";
import { formatDateTime } from "../../utils/format/date";
@@ -29,6 +31,7 @@ const ApplicationRegister = () => {
const { recruitmentId = null } = parseQuery(location.search);
const currentRecruitment = location.state?.currentRecruitment ?? null;
const { recruitmentItems = [] } = useRecruitmentItem(recruitmentId);
+ const { Modal, openModal } = useModalContext();
const {
form,
@@ -113,8 +116,10 @@ const ApplicationRegister = () => {
const handleSubmit = (event) => {
event.preventDefault();
- if (!window.confirm(CONFIRM_MESSAGE.SUBMIT_APPLICATION)) return;
+ openModal();
+ };
+ const handleClickConfirmButton = () => {
save(form);
};
@@ -194,6 +199,14 @@ const ApplicationRegister = () => {
+
+
+
);
};
diff --git a/frontend/src/pages/ApplicationRegister/ApplicationRegister.stories.js b/frontend/src/pages/ApplicationRegister/ApplicationRegister.stories.js
index eaa9128e4..d94243964 100644
--- a/frontend/src/pages/ApplicationRegister/ApplicationRegister.stories.js
+++ b/frontend/src/pages/ApplicationRegister/ApplicationRegister.stories.js
@@ -1,6 +1,5 @@
-import React from "react";
import { rest } from "msw";
-import { Route, MemoryRouter } from "react-router-dom";
+import { MemoryRouter } from "react-router-dom";
import ApplicationRegister from "./ApplicationRegister";
import { API_BASE_URL } from "../../../.storybook/preview";
@@ -29,9 +28,7 @@ export default {
},
]}
>
-
-
-
+
),
],
diff --git a/frontend/src/pages/AssignmentSubmit/AssignmentSubmit.stories.js b/frontend/src/pages/AssignmentSubmit/AssignmentSubmit.stories.js
index 89a5bdf28..b6d0443e4 100644
--- a/frontend/src/pages/AssignmentSubmit/AssignmentSubmit.stories.js
+++ b/frontend/src/pages/AssignmentSubmit/AssignmentSubmit.stories.js
@@ -1,4 +1,4 @@
-import { MemoryRouter, Route } from "react-router-dom";
+import { MemoryRouter } from "react-router-dom";
import { missionsDummy } from "../../mock/dummy";
import AssignmentSubmit from "./AssignmentSubmit";
@@ -18,9 +18,7 @@ export default {
},
]}
>
-
-
-
+
),
],
diff --git a/frontend/src/pages/Login/Login.stories.js b/frontend/src/pages/Login/Login.stories.js
index 43a9126b7..498be38ab 100644
--- a/frontend/src/pages/Login/Login.stories.js
+++ b/frontend/src/pages/Login/Login.stories.js
@@ -1,9 +1,22 @@
-import React from "react";
+import { MemoryRouter } from "react-router-dom";
import Login from "./Login";
export default {
title: "pages/Login",
component: Login,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => ;
diff --git a/frontend/src/pages/MyApplication/MyApplication.stories.js b/frontend/src/pages/MyApplication/MyApplication.stories.js
index 531fa624c..fe3d6859c 100644
--- a/frontend/src/pages/MyApplication/MyApplication.stories.js
+++ b/frontend/src/pages/MyApplication/MyApplication.stories.js
@@ -2,10 +2,24 @@ import { rest } from "msw";
import { API_BASE_URL } from "../../../.storybook/preview";
import { missionsDummy, myApplicationDummy } from "../../mock/dummy";
import MyApplication from "./MyApplication";
+import { MemoryRouter } from "react-router-dom";
export default {
title: "pages/MyApplication",
component: MyApplication,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => ;
diff --git a/frontend/src/pages/MyPage/MyPage.stories.js b/frontend/src/pages/MyPage/MyPage.stories.js
index 29b1e892e..efbcadb8c 100644
--- a/frontend/src/pages/MyPage/MyPage.stories.js
+++ b/frontend/src/pages/MyPage/MyPage.stories.js
@@ -1,9 +1,22 @@
-import React from "react";
+import { MemoryRouter } from "react-router-dom";
import MyPage from "./MyPage";
export default {
title: "pages/MyPage",
component: MyPage,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => ;
diff --git a/frontend/src/pages/MyPageEdit/MyPageEdit.stories.js b/frontend/src/pages/MyPageEdit/MyPageEdit.stories.js
index 3f8250020..b4f584065 100644
--- a/frontend/src/pages/MyPageEdit/MyPageEdit.stories.js
+++ b/frontend/src/pages/MyPageEdit/MyPageEdit.stories.js
@@ -1,9 +1,22 @@
-import React from "react";
+import { MemoryRouter } from "react-router-dom";
import MyPageEdit from "./MyPageEdit";
export default {
title: "pages/MyPageEdit",
component: MyPageEdit,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => ;
diff --git a/frontend/src/pages/PasswordEdit/PasswordEdit.stories.js b/frontend/src/pages/PasswordEdit/PasswordEdit.stories.js
index e8487c464..44be7d24e 100644
--- a/frontend/src/pages/PasswordEdit/PasswordEdit.stories.js
+++ b/frontend/src/pages/PasswordEdit/PasswordEdit.stories.js
@@ -1,9 +1,22 @@
-import React from "react";
+import { MemoryRouter } from "react-router-dom";
import PasswordEdit from "./PasswordEdit";
export default {
title: "pages/PasswordEdit",
component: PasswordEdit,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => ;
diff --git a/frontend/src/pages/PasswordFind/PasswordFind.stories.js b/frontend/src/pages/PasswordFind/PasswordFind.stories.js
index 7e7574675..71f917c88 100644
--- a/frontend/src/pages/PasswordFind/PasswordFind.stories.js
+++ b/frontend/src/pages/PasswordFind/PasswordFind.stories.js
@@ -1,9 +1,22 @@
-import React from "react";
+import { MemoryRouter } from "react-router-dom";
import PasswordFind from "./PasswordFind";
export default {
title: "pages/PasswordFind",
component: PasswordFind,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => ;
diff --git a/frontend/src/pages/PasswordFindResult/PasswordFindResult.stories.js b/frontend/src/pages/PasswordFindResult/PasswordFindResult.stories.js
index fc553f4f1..6560df6aa 100644
--- a/frontend/src/pages/PasswordFindResult/PasswordFindResult.stories.js
+++ b/frontend/src/pages/PasswordFindResult/PasswordFindResult.stories.js
@@ -1,5 +1,4 @@
-import React from "react";
-import { MemoryRouter, Route } from "react-router-dom";
+import { MemoryRouter } from "react-router-dom";
import PasswordFindResult from "./PasswordFindResult";
export default {
@@ -15,9 +14,7 @@ export default {
},
]}
>
-
-
-
+
),
],
diff --git a/frontend/src/pages/Recruits/Recruits.stories.js b/frontend/src/pages/Recruits/Recruits.stories.js
index 57ce33f0f..550d3fb3e 100644
--- a/frontend/src/pages/Recruits/Recruits.stories.js
+++ b/frontend/src/pages/Recruits/Recruits.stories.js
@@ -1,3 +1,4 @@
+import { MemoryRouter } from "react-router-dom";
import "../../App.css";
import Header from "../../components/Header/Header";
import Recruits from "./Recruits";
@@ -5,6 +6,19 @@ import Recruits from "./Recruits";
export default {
title: "pages/Recruits",
component: Recruits,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
};
const Template = (args) => (
diff --git a/frontend/src/pages/SignUp/SignUp.stories.js b/frontend/src/pages/SignUp/SignUp.stories.js
index abe5c0e26..4a5947a30 100644
--- a/frontend/src/pages/SignUp/SignUp.stories.js
+++ b/frontend/src/pages/SignUp/SignUp.stories.js
@@ -1,4 +1,4 @@
-import { MemoryRouter, Route } from "react-router-dom";
+import { MemoryRouter } from "react-router-dom";
import SignUp from "./SignUp";
export default {
@@ -16,9 +16,7 @@ export default {
},
]}
>
-
-
-
+
),
],