diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..a6d42278
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# 디폴트 무시된 파일
+/shelf/
+/workspace.xml
+# 에디터 기반 HTTP 클라이언트 요청
+/httpRequests/
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..03d9549e
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml
new file mode 100644
index 00000000..66d9454f
--- /dev/null
+++ b/.idea/jsLinters/eslint.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..90a5036a
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
new file mode 100644
index 00000000..5968543a
--- /dev/null
+++ b/.idea/prettier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/wiki.iml b/.idea/wiki.iml
new file mode 100644
index 00000000..24643cc3
--- /dev/null
+++ b/.idea/wiki.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index cfacdb0b..d15f7f80 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"name": "wiki",
"version": "0.1.0",
"dependencies": {
+ "@ant-design/icons": "^5.2.6",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
@@ -20,9 +21,11 @@
"antd": "^5.9.0",
"dotenv": "^16.3.1",
"firebase": "^10.3.1",
+ "framer-motion": "^10.16.4",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-dom": "^18.2.0",
+ "react-modal": "^3.16.1",
"react-router-dom": "^6.15.0",
"react-scripts": "5.0.1",
"recoil": "^0.7.7",
@@ -33,6 +36,7 @@
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/react-beautiful-dnd": "^13.1.4",
+ "@types/styled-components": "^5.1.27",
"eslint": "^8.49.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
@@ -5122,6 +5126,15 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-modal": {
+ "version": "3.16.0",
+ "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz",
+ "integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-redux": {
"version": "7.1.26",
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.26.tgz",
@@ -5196,6 +5209,17 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
},
+ "node_modules/@types/styled-components": {
+ "version": "5.1.27",
+ "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.27.tgz",
+ "integrity": "sha512-oY9c1SdztRRF0QDQdwXEenfAjGN4WGUkaMpx5hvdTbYYqw01qoY2GrHi+kAR6SVofynzD6KbGoF5ITP0zh5pvg==",
+ "dev": true,
+ "dependencies": {
+ "@types/hoist-non-react-statics": "*",
+ "@types/react": "*",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/@types/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.0.tgz",
@@ -9148,6 +9172,11 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
+ "node_modules/exenv": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
+ "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
+ },
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -9707,6 +9736,44 @@
"url": "https://github.com/sponsors/rawify"
}
},
+ "node_modules/framer-motion": {
+ "version": "10.16.4",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.4.tgz",
+ "integrity": "sha512-p9V9nGomS3m6/CALXqv6nFGMuFOxbWsmaOrdmhyQimMIlLl3LC7h7l86wge/Js/8cRu5ktutS/zlzgR7eBOtFA==",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ },
+ "optionalDependencies": {
+ "@emotion/is-prop-valid": "^0.8.2"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/framer-motion/node_modules/@emotion/is-prop-valid": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
+ "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+ "optional": true,
+ "dependencies": {
+ "@emotion/memoize": "0.7.4"
+ }
+ },
+ "node_modules/framer-motion/node_modules/@emotion/memoize": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
+ "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
+ "optional": true
+ },
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -16730,6 +16797,29 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
+ "node_modules/react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
+ "node_modules/react-modal": {
+ "version": "3.16.1",
+ "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz",
+ "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==",
+ "dependencies": {
+ "exenv": "^1.2.0",
+ "prop-types": "^15.7.2",
+ "react-lifecycles-compat": "^3.0.0",
+ "warning": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "peerDependencies": {
+ "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18",
+ "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18"
+ }
+ },
"node_modules/react-redux": {
"version": "7.2.9",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
@@ -19181,6 +19271,14 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/warning": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+ "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
diff --git a/package.json b/package.json
index 53c9657a..d7f5ac07 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
+ "@ant-design/icons": "^5.2.6",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
@@ -15,9 +16,11 @@
"antd": "^5.9.0",
"dotenv": "^16.3.1",
"firebase": "^10.3.1",
+ "framer-motion": "^10.16.4",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-dom": "^18.2.0",
+ "react-modal": "^3.16.1",
"react-router-dom": "^6.15.0",
"react-scripts": "5.0.1",
"recoil": "^0.7.7",
@@ -52,6 +55,7 @@
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/react-beautiful-dnd": "^13.1.4",
+ "@types/styled-components": "^5.1.27",
"eslint": "^8.49.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
diff --git a/src/components/Employee/CardAddMember.tsx b/src/components/Employee/CardAddMember.tsx
new file mode 100644
index 00000000..4b9cfd2a
--- /dev/null
+++ b/src/components/Employee/CardAddMember.tsx
@@ -0,0 +1,28 @@
+import { PlusOutlined } from "@ant-design/icons";
+import React from "react";
+import { Button, Dropdown } from "antd";
+import type { MenuProps } from "antd";
+
+const items: MenuProps["items"] = [
+ {
+ label: "Add Member",
+ key: "addMember",
+ },
+ {
+ label: "Add Team",
+ key: "addTeam",
+ },
+];
+
+export default function TableAddMember() {
+ return (
+
+ } size="large" />
+
+ );
+}
diff --git a/src/components/Employee/CardExportBtn.tsx b/src/components/Employee/CardExportBtn.tsx
new file mode 100644
index 00000000..699bf174
--- /dev/null
+++ b/src/components/Employee/CardExportBtn.tsx
@@ -0,0 +1,12 @@
+import { CloudDownloadOutlined } from "@ant-design/icons";
+import React from "react";
+import { Button } from "antd";
+
+export default function TableExportBtn() {
+ return (
+
+ );
+}
diff --git a/src/components/Employee/CardFilter.tsx b/src/components/Employee/CardFilter.tsx
new file mode 100644
index 00000000..01cf7356
--- /dev/null
+++ b/src/components/Employee/CardFilter.tsx
@@ -0,0 +1,59 @@
+import { FilterFilled } from "@ant-design/icons";
+import React from "react";
+import { Button, Dropdown } from "antd";
+import type { MenuProps } from "antd";
+
+const items: MenuProps["items"] = [
+ {
+ type: "group",
+ label: "SORT BY:",
+ children: [
+ {
+ label: "default",
+ key: "sortDefault",
+ },
+ {
+ label: "Name",
+ key: "sortName",
+ },
+ {
+ label: "Team",
+ key: "sortTeam",
+ },
+ ],
+ },
+ {
+ type: "group",
+ label: "MEMBERS:",
+ children: [
+ {
+ label: "All",
+ key: "membersAll",
+ },
+ {
+ label: "Manager",
+ key: "membersManager",
+ },
+ {
+ label: "Member",
+ key: "membersMember",
+ },
+ ],
+ },
+];
+
+export default function TableFilter() {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/Employee/CardHeading.tsx b/src/components/Employee/CardHeading.tsx
new file mode 100644
index 00000000..afedbcba
--- /dev/null
+++ b/src/components/Employee/CardHeading.tsx
@@ -0,0 +1,45 @@
+import React from "react";
+import { Button, Space } from "antd";
+import styled from "styled-components";
+import TableFilter from "./CardFilter";
+import TableSearch from "./CardSearch";
+import TableAddMember from "./CardAddMember";
+import TableExportBtn from "./CardExportBtn";
+
+const CardHeader = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ position: relative;
+ padding: 1.5rem;
+`;
+
+const ToggleWrap = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ align-items: center;
+`;
+
+export default function CardHeading() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Employee/CardSearch.tsx b/src/components/Employee/CardSearch.tsx
new file mode 100644
index 00000000..7786882d
--- /dev/null
+++ b/src/components/Employee/CardSearch.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+
+import { Input } from "antd";
+
+const { Search } = Input;
+
+export default function TableSearch() {
+ return (
+
+ );
+}
diff --git a/src/components/Employee/CardTable.tsx b/src/components/Employee/CardTable.tsx
new file mode 100644
index 00000000..46546a6f
--- /dev/null
+++ b/src/components/Employee/CardTable.tsx
@@ -0,0 +1,186 @@
+import { EllipsisOutlined } from "@ant-design/icons";
+import React, { useState } from "react";
+import { Col, Row, Table, Dropdown } from "antd";
+import type { ColumnsType } from "antd/es/table";
+import type { MenuProps } from "antd";
+
+import styled from "styled-components";
+
+interface DataType {
+ key: React.Key;
+ name: string;
+ department: string;
+ position: string;
+ phone: string;
+ address: string;
+ team: string;
+ profile: string;
+ accessLevel: string;
+}
+
+const Image = styled.span`
+ display: block;
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ overflow: hidden;
+ & > img {
+ width: 100%;
+ }
+`;
+const Btn = styled.a`
+ display: block;
+ padding: 0.3rem;
+`;
+
+const items: MenuProps["items"] = [
+ {
+ key: "1",
+ label: (
+
+ Edit
+
+ ),
+ },
+ {
+ key: "2",
+ label: (
+
+ View Profile
+
+ ),
+ },
+ {
+ key: "3",
+ label: (
+
+ Delete
+
+ ),
+ danger: true,
+ },
+];
+
+export default function CardTable() {
+ const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+
+ const columns: ColumnsType = [
+ {
+ title: "Name",
+ render: (record) => (
+
+
+ {" "}
+
+
+ {" "}
+
+
+ {" "}
+ {record.name}
+ {record.address}
+
+
+ ),
+ },
+ {
+ title: "Department",
+ render: (record) => (
+
+
+ {record.department}
+ {record.position}
+
+
+ ),
+ },
+ {
+ title: "Team",
+ dataIndex: "team",
+ },
+ {
+ title: "Phone",
+ dataIndex: "phone",
+ },
+ {
+ title: "AccessLevel",
+ dataIndex: "accessLevel",
+ },
+ {
+ title: ,
+ dataIndex: "",
+ render: () => (
+
+
+ e.preventDefault()}>
+
+
+
+
+ ),
+ },
+ ];
+
+ const dataSource: DataType[] = [
+ {
+ key: "1",
+ name: "박나영",
+ department: "Information Technology",
+ position: "Front-end Developer",
+ phone: "010-5555-5555",
+ address: "myemail@example.com",
+ team: "이정도면 껌이조",
+ profile:
+ "https://deploy-preview-66--effulgent-axolotl-ab38e8.netlify.app/asset/member1.png",
+ accessLevel: "Member",
+ },
+ {
+ key: "2",
+ name: "김땡땡",
+ department: "Information Technology",
+ position: "Back-end Developer",
+ phone: "010-5555-5555",
+ address: "myemail@example.com",
+ team: "가보자고",
+ profile:
+ "https://deploy-preview-66--effulgent-axolotl-ab38e8.netlify.app/asset/member2.png",
+ accessLevel: "Member",
+ },
+ {
+ key: "3",
+ name: "이땡땡",
+ department: "Information Technology",
+ position: "Front-end Developer",
+ phone: "010-5555-5555",
+ address: "myemail@example.com",
+ team: "가보자고",
+ profile:
+ "https://deploy-preview-66--effulgent-axolotl-ab38e8.netlify.app/asset/member3.png",
+ accessLevel: "Manager",
+ },
+ ];
+ const rowSelection = {
+ onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => {
+ console.log(
+ `selectedRowKeys: ${selectedRowKeys}`,
+ "selectedRows: ",
+ selectedRows,
+ );
+ },
+ };
+
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/src/components/SignUp/Navigation.tsx b/src/components/SignUp/Navigation.tsx
new file mode 100644
index 00000000..fc6dd22e
--- /dev/null
+++ b/src/components/SignUp/Navigation.tsx
@@ -0,0 +1,32 @@
+import { useNavigate } from "react-router-dom";
+
+export const useNavigation = () => {
+ const navigate = useNavigate();
+
+ const moveUserRegister = () => {
+ navigate("/user-register");
+ };
+
+ const moveStartRegister = () => {
+ navigate("/start-register");
+ };
+
+ const moveEndRegister = () => {
+ navigate("/end-register");
+ };
+
+ const moveMain = () => {
+ navigate("/");
+ };
+
+ const moveMyTeam = () => {
+ navigate("/wiki");
+ };
+ return {
+ moveUserRegister,
+ moveStartRegister,
+ moveEndRegister,
+ moveMain,
+ moveMyTeam,
+ };
+};
diff --git a/src/components/SignUp/Pagination.tsx b/src/components/SignUp/Pagination.tsx
new file mode 100644
index 00000000..ae9e5d18
--- /dev/null
+++ b/src/components/SignUp/Pagination.tsx
@@ -0,0 +1,21 @@
+import React from "react";
+import { styled } from "styled-components";
+
+export const SlideCounter = styled.div`
+ display: flex;
+ justify-content: center;
+ margin-top: 20px;
+ gap: 10px;
+`;
+export const ActiveDot = styled.div`
+ background-color: #5b617c;
+ width: 10px;
+ height: 10px;
+ border-radius: 50px;
+`;
+export const Dot = styled.div`
+ background-color: #5b617c19;
+ width: 10px;
+ height: 10px;
+ border-radius: 50px;
+`;
diff --git a/src/components/SignUp/Register/EndRegister.tsx b/src/components/SignUp/Register/EndRegister.tsx
new file mode 100644
index 00000000..a7081b75
--- /dev/null
+++ b/src/components/SignUp/Register/EndRegister.tsx
@@ -0,0 +1,68 @@
+import React from "react";
+import { styled } from "styled-components";
+import { ActiveDot, Dot, SlideCounter } from "../Pagination";
+import { useNavigation } from "../Navigation";
+import { EndSubTitle, EndTitle } from "../Title";
+import { motion } from "framer-motion";
+const Container = styled.div`
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+`;
+const EndContainer = styled.div`
+ width: 50%;
+ margin: 100px auto;
+ text-align: center;
+`;
+const EndBtnContainer = styled.div`
+ display: flex;
+ justify-content: center;
+ margin-top: 50px;
+ gap: 20px;
+`;
+const EndBtn = styled.button`
+ width: 200px;
+ height: 50px;
+ border-radius: 10px;
+ text-align: center;
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ &:hover {
+ color: #fff;
+ background-color: #000;
+ }
+`;
+export default function EndRegister() {
+ const { moveMain, moveMyTeam } = useNavigation();
+ return (
+
+
+
+
+ 이제 Wiki를 통해
+
+ 일의 능률을 향상시켜보세요!
+
+ 아래 버튼을 누르시면 이동됩니다!
+
+ Home
+ My Team
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/SignUp/Register/StartRegister.tsx b/src/components/SignUp/Register/StartRegister.tsx
new file mode 100644
index 00000000..1abd132b
--- /dev/null
+++ b/src/components/SignUp/Register/StartRegister.tsx
@@ -0,0 +1,56 @@
+import React from "react";
+import { styled } from "styled-components";
+import { ActiveDot, Dot, SlideCounter } from "../Pagination";
+import { useNavigation } from "../Navigation";
+import { StartSubTitle, StartTitle } from "../Title";
+import { motion } from "framer-motion";
+const Container = styled.div`
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+`;
+const StartContainer = styled.div`
+ width: 50%;
+ margin: 100px auto;
+ text-align: center;
+`;
+const StartBtn = styled.button`
+ width: 400px;
+ height: 50px;
+ margin: 50px auto;
+ border-radius: 10px;
+ text-align: center;
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ &:hover {
+ color: #fff;
+ background-color: #000;
+ }
+`;
+export default function StartRegister() {
+ const { moveUserRegister } = useNavigation();
+ return (
+
+
+
+ Wiki에 오신 것을 환영합니다!
+ 아래 버튼을 통해 정보를 입력해주세요!
+ 시작하기
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/SignUp/Register/UserRegister.tsx b/src/components/SignUp/Register/UserRegister.tsx
new file mode 100644
index 00000000..ab9d1e00
--- /dev/null
+++ b/src/components/SignUp/Register/UserRegister.tsx
@@ -0,0 +1,171 @@
+import React, { useState } from "react";
+import { styled } from "styled-components";
+import { PlusOutlined } from "@ant-design/icons";
+import { Button, Input, Select, Upload, message } from "antd";
+import { UploadOutlined, ArrowLeftOutlined } from "@ant-design/icons";
+import type { UploadProps } from "antd";
+import { MainTitle } from "../Title";
+import { SlideCounter, Dot, ActiveDot } from "../Pagination";
+import { useNavigation } from "../Navigation";
+import { motion } from "framer-motion";
+
+const props: UploadProps = {
+ name: "file",
+ action: "https://www.mocky.io/v2/5cc8019d300000980a055e76",
+ headers: {
+ authorization: "authorization-text",
+ },
+ onChange(info) {
+ if (info.file.status !== "uploading") {
+ console.log(info.file, info.fileList);
+ }
+ if (info.file.status === "done") {
+ message.success(`${info.file.name} file uploaded successfully`);
+ } else if (info.file.status === "error") {
+ message.error(`${info.file.name} file upload failed.`);
+ }
+ },
+};
+
+const Container = styled.div`
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+`;
+const UserInfoContainer = styled.div`
+ border: 1px solid black;
+ margin: 20px auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ text-align: start;
+ span {
+ font-weight: 500;
+ }
+`;
+const UserNameCategory = styled.div`
+ margin: 20px 20px;
+ display: flex;
+ flex-direction: column;
+`;
+const UserCompanyCategory = styled(UserNameCategory)``;
+const UserRankCategory = styled(UserNameCategory)``;
+const UserImageCategory = styled(UserNameCategory)``;
+const BtnContainer = styled.div`
+ display: flex;
+ justify-content: center;
+ gap: 10px;
+ margin: 20px;
+ height: 30px;
+`;
+const BackBtn = styled.button`
+ border: 1px solid black;
+ width: 60px;
+ font-size: 16px;
+ cursor: pointer;
+ transition: transform 0.3s ease-in-out;
+ &:hover {
+ background-color: #000;
+ color: #fff;
+ transform: translateX(-5px);
+ }
+`;
+const SubmitBtn = styled.button`
+ border: 1px solid black;
+ width: 240px;
+ font-size: 16px;
+ cursor: pointer;
+ &:hover {
+ background-color: #000;
+ color: #fff;
+ }
+`;
+export default function UserRegister() {
+ const { moveStartRegister, moveEndRegister } = useNavigation();
+ return (
+
+
+ 회원님의 정보를 입력해주세요!
+
+
+ 이름
+
+
+
+ 소속 팀
+
+
+ 직급
+
+
+
+ 프로필 사진
+
+ }>프로필 사진 업로드
+
+
+
+
+
+
+ 완료
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/SignUp/SignUpEmail.tsx b/src/components/SignUp/SignUpEmail.tsx
new file mode 100644
index 00000000..330b689b
--- /dev/null
+++ b/src/components/SignUp/SignUpEmail.tsx
@@ -0,0 +1,113 @@
+import React, { useState } from "react";
+import { Button, Modal, Checkbox, Form, Input } from "antd";
+import { styled } from "styled-components";
+import { auth } from "../../libs/firebase";
+import { signInWithEmailAndPassword } from "firebase/auth";
+import { createUserWithEmailAndPassword } from "firebase/auth";
+
+interface FieldType {
+ userEmail?: string;
+ password?: string;
+ remember?: string;
+}
+const Container = styled.div`
+ margin: 0;
+ padding: 0;
+`;
+const ModalContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ border-radius: 20px;
+ text-align: start;
+`;
+const ModalTitle = styled.p`
+ font-size: 20px;
+ margin-top: 50px;
+ margin-bottom: 0;
+ text-align: center;
+`;
+const onFinish = (values: any) => {
+ console.log("Success: ", values);
+};
+const onFinishFailed = (errorInfo: any) => {
+ console.log("Failed: ", errorInfo);
+};
+
+const SignUpEmailModal = () => {
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+
+ const handleEmailChange = (e: React.ChangeEvent) => {
+ setEmail(e.target.value);
+ };
+
+ const handlePasswordChange = (e: React.ChangeEvent) => {
+ setPassword(e.target.value);
+ };
+
+ const handleSignUp = async () => {
+ try {
+ const userCredential = await createUserWithEmailAndPassword(
+ auth,
+ email,
+ password,
+ );
+ const user = userCredential.user;
+ console.log("로그인 성공:", user);
+ alert("회원가입 완료되었습니다!");
+ } catch (error) {
+ console.error("로그인 실패:", error);
+ }
+ };
+ return (
+
+
+ Wiki에서 사용하실 이메일을 적어주세요!
+
+ label="이메일주소"
+ name="userEmail"
+ rules={[
+ {
+ required: true,
+ message: "사용하실 이메일을 입력해주세요!",
+ },
+ ]}
+ >
+
+
+
+
+ label="비밀번호"
+ name="password"
+ rules={[{ required: true, message: "비밀번호를 입력해주세요!" }]}
+ >
+
+
+
+ name="remember"
+ valuePropName="checked"
+ wrapperCol={{ offset: 8, span: 16 }}
+ >
+
+
+
+
+
+
+
+ );
+};
+export default SignUpEmailModal;
diff --git a/src/components/SignUp/Title.tsx b/src/components/SignUp/Title.tsx
new file mode 100644
index 00000000..33e2461d
--- /dev/null
+++ b/src/components/SignUp/Title.tsx
@@ -0,0 +1,30 @@
+import React from "react";
+import { styled } from "styled-components";
+
+export const MainTitle = styled.p`
+ font-size: 20px;
+ font-weight: 500;
+ text-align: start;
+ margin: 0 auto;
+`;
+
+export const StartTitle = styled.p`
+ margin-top: 30px;
+ font-size: 32px;
+ font-weight: bold;
+ text-align: center;
+`;
+export const StartSubTitle = styled.p`
+ font-size: 20px;
+ color: #d9d9d9;
+ text-align: center;
+`;
+export const EndTitle = styled(StartTitle)``;
+export const EndSubTitle = styled(StartSubTitle)``;
+
+export const ModalTitle = styled.p`
+ font-size: 20px;
+ margin-top: 50px;
+ margin-bottom: 0;
+ text-align: center;
+`;
diff --git a/src/components/Timer/TimerApp.tsx b/src/components/Timer/TimerApp.tsx
new file mode 100644
index 00000000..2f89cabf
--- /dev/null
+++ b/src/components/Timer/TimerApp.tsx
@@ -0,0 +1,219 @@
+import React from "react";
+import { useState, useEffect } from "react";
+import { styled } from "styled-components";
+import { Button, Alert } from "antd";
+import {
+ ClockCircleOutlined,
+ CheckOutlined,
+ PoweroffOutlined,
+} from "@ant-design/icons";
+
+// 타이머 스타일링
+interface TimerProps {
+ fontSize?: string;
+}
+const TimerText = styled.div`
+ font-size: ${(props) => props.fontSize || "1.5rem"};
+`;
+
+const TimerAlign = styled.div`
+ style={
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "right",
+ alignItems: "center"}`;
+
+const GreetingText = styled.div`
+ font-size: "1.5rem";
+`;
+
+const TimerApp = () => {
+ const nowDate = new Date().toLocaleDateString("ko-KR", {
+ year: "2-digit",
+ month: "2-digit",
+ day: "2-digit",
+ weekday: "narrow",
+ });
+
+ const [nowTime, setNowTime] = useState(
+ new Date().toLocaleTimeString(),
+ ); // 현재 시간 표시
+ const [startWorkTime, setStartWorkTime] = useState(null); // 출근 시간 기록
+ const [finishWorkTime, setFinishWorkTime] = useState(null); // 퇴근 시간 기록
+ const [startWorkBtnClicked, setStartWorkBtnClicked] =
+ useState(false); // 출근 버튼 클릭 가능 상태로 시작
+ const [finishWorkBtnClicked, setFinishWorkBtnClicked] =
+ useState(false); // 퇴근 버튼 클릭 가능 상태로 시작
+ const [clickedStartBtnText, setClickedStartBtnText] = useState(""); // 출근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시
+ const [clickedFinishBtnText, setClickedFinishBtnText] = useState(""); // 퇴근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시
+ const [userName, setUserName] = useState("");
+
+ const UpdateTime = () => {
+ let nowTime = new Date().toLocaleTimeString();
+ setNowTime(nowTime);
+ };
+
+ useEffect(() => {
+ const interval = setInterval(UpdateTime, 1000);
+
+ return () => {
+ clearInterval(interval);
+ };
+ }, []);
+
+ const recordStartWork = (e: React.MouseEvent) => {
+ e.preventDefault();
+ // 현재 시간을 출근 시간으로 기록
+ const startWorkTime = new Date();
+ const hours = startWorkTime.getHours().toString().padStart(2, "0");
+ const minutes = startWorkTime.getMinutes().toString().padStart(2, "0");
+ const seconds = startWorkTime.getSeconds().toString().padStart(2, "0");
+ setStartWorkTime(`${hours}:${minutes}:${seconds}`);
+ setStartWorkBtnClicked(true); // 출근 시간 기록 후 버튼 비활성화
+ setClickedStartBtnText(nowTime);
+ };
+
+ const recordFinishWork = (e: React.MouseEvent) => {
+ e.preventDefault();
+ // 현재 시간을 퇴근 시간으로 기록
+
+ if (!startWorkBtnClicked) {
+ return alert("출근한 상태일 때만 퇴근 기록이 가능합니다!");
+ }
+
+ const finishWorkTime = new Date();
+ const hours = finishWorkTime.getHours().toString().padStart(2, "0");
+ const minutes = finishWorkTime.getMinutes().toString().padStart(2, "0");
+ const seconds = finishWorkTime.getSeconds().toString().padStart(2, "0");
+ setFinishWorkTime(`${hours}:${minutes}:${seconds}`);
+ setFinishWorkBtnClicked(true); // 퇴근 시간 기록 후 버튼 비활성화
+ setClickedFinishBtnText(nowTime);
+ };
+
+ const calcWorkTime = () => {
+ if (startWorkTime && finishWorkTime) {
+ const startTime = startWorkTime.split(":");
+ const finishTime = finishWorkTime.split(":");
+ const startHours = parseInt(startTime[0], 10);
+ const startMinutes = parseInt(startTime[1], 10);
+ const finishHours = parseInt(finishTime[0], 10);
+ const finishMinutes = parseInt(finishTime[1], 10);
+
+ let hours = finishHours - startHours;
+ let minutes = finishMinutes - startMinutes;
+
+ if (minutes < 0) {
+ hours -= 1;
+ minutes += 60;
+ }
+
+ return `오늘 총 근무 시간은 ${hours}시간 ${minutes}분 입니다.`;
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default TimerApp;
diff --git a/src/components/signin/SignInEmail.tsx b/src/components/signin/SignInEmail.tsx
new file mode 100644
index 00000000..d040db74
--- /dev/null
+++ b/src/components/signin/SignInEmail.tsx
@@ -0,0 +1,113 @@
+import React, { useState } from "react";
+import { Button, Modal, Checkbox, Form, Input } from "antd";
+import { styled } from "styled-components";
+import { auth } from "../../libs/firebase";
+import { signInWithEmailAndPassword } from "firebase/auth";
+import { createUserWithEmailAndPassword } from "firebase/auth";
+
+interface FieldType {
+ userEmail?: string;
+ password?: string;
+ remember?: string;
+}
+const Container = styled.div`
+ margin: 0;
+ padding: 0;
+`;
+const ModalContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ border-radius: 20px;
+ text-align: start;
+`;
+const ModalTitle = styled.p`
+ font-size: 20px;
+ margin-top: 50px;
+ margin-bottom: 0;
+ text-align: center;
+`;
+const onFinish = (values: any) => {
+ console.log("Success: ", values);
+};
+const onFinishFailed = (errorInfo: any) => {
+ console.log("Failed: ", errorInfo);
+};
+
+const SignInEmailModal = () => {
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+
+ const handleEmailChange = (e: React.ChangeEvent) => {
+ setEmail(e.target.value);
+ };
+
+ const handlePasswordChange = (e: React.ChangeEvent) => {
+ setPassword(e.target.value);
+ };
+
+ const handleSignIn = async () => {
+ try {
+ const userCredential = await signInWithEmailAndPassword(
+ auth,
+ email,
+ password,
+ );
+ const user = userCredential.user;
+ console.log("로그인 성공:", user);
+ } catch (error) {
+ alert("회원가입부터 진행해주세요");
+ console.error("로그인 실패:", error);
+ }
+ };
+ return (
+
+
+ Wiki에서 사용하고 있는 이메일을 적어주세요!
+
+ label="이메일주소"
+ name="userEmail"
+ rules={[
+ {
+ required: true,
+ message: "사용하고 계신 이메일을 입력해주세요!",
+ },
+ ]}
+ >
+
+
+
+
+ label="비밀번호"
+ name="password"
+ rules={[{ required: true, message: "비밀번호를 입력해주세요!" }]}
+ >
+
+
+
+ name="remember"
+ valuePropName="checked"
+ wrapperCol={{ offset: 8, span: 16 }}
+ >
+
+
+
+
+
+
+
+ );
+};
+export default SignInEmailModal;
diff --git a/src/components/signin/SignInGoogle.tsx b/src/components/signin/SignInGoogle.tsx
new file mode 100644
index 00000000..53c3082c
--- /dev/null
+++ b/src/components/signin/SignInGoogle.tsx
@@ -0,0 +1,11 @@
+import { auth } from "../../libs/firebase";
+import { signInWithPopup, GoogleAuthProvider } from "firebase/auth";
+
+const provider = new GoogleAuthProvider();
+
+const signInGoogle = async () => {
+ const { user } = await signInWithPopup(auth, provider);
+ console.log(user);
+};
+
+export default signInGoogle;
diff --git a/src/libs/firebase.ts b/src/libs/firebase.ts
index 615b9227..20508c5b 100644
--- a/src/libs/firebase.ts
+++ b/src/libs/firebase.ts
@@ -1,7 +1,7 @@
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
-
+import { getAuth } from "firebase/auth";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
@@ -16,3 +16,4 @@ const firebaseConfig = {
const app = initializeApp(firebaseConfig);
// Initialize Cloud Firestore and get a reference to the service
export const db = getFirestore(app);
+export const auth = getAuth(app);
diff --git a/src/pages/Employee.tsx b/src/pages/Employee.tsx
index 71d0e905..f2b33125 100644
--- a/src/pages/Employee.tsx
+++ b/src/pages/Employee.tsx
@@ -1,7 +1,60 @@
import React from "react";
+import styled from "styled-components";
+
+import CardTable from "../components/Employee/CardTable";
+import CardHeading from "../components/Employee/CardHeading";
+
+export const Container = styled.div`
+ max-width: 100%;
+ margin: 0 auto;
+ padding: 0 1rem;
+
+ @media (min-width: 576px) {
+ max-width: 576px;
+ }
+
+ @media (min-width: 768px) {
+ max-width: 768px;
+ }
+
+ @media (min-width: 992px) {
+ max-width: 992px;
+ }
+
+ @media (min-width: 1200px) {
+ max-width: 1200px;
+ }
+`;
+const Header = styled.div`
+ font-size: 1.5rem;
+ font-weight: bold;
+`;
+
+const CarContainer = styled.div`
+ background-color: #fff;
+ border-radius: 8px;
+ color: #526484;
+ box-shadow: rgba(99, 99, 99, 0.2) 0px 0px 5px 0px;
+ word-wrap: break-word;
+`;
const Employee = () => {
- return Employee
;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};
export default Employee;
diff --git a/src/pages/SignIn.tsx b/src/pages/SignIn.tsx
index e12af16f..d6654575 100644
--- a/src/pages/SignIn.tsx
+++ b/src/pages/SignIn.tsx
@@ -1,7 +1,121 @@
-import React from "react";
+import { GoogleOutlined, MailOutlined } from "@ant-design/icons";
+import React, { useState } from "react";
+import { styled } from "styled-components";
+import SignInEmailModal from "../components/SignIn/SignInEmail";
+import { Modal } from "antd";
+import signInGoogle from "../components/SignIn/SignInGoogle";
+import { Link } from "react-router-dom";
+import { MainTitle } from "../components/SignUp/Title";
+const Container = styled.div`
+ margin: 0;
+ padding: 0;
+ width: 100vw;
+`;
+const SignInContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ border: 1px solid black;
+ border-radius: 20px;
+ width: 50vw;
+ margin: 100px auto;
+ text-align: center;
+`;
+const Logo = styled.div`
+ border: 1px solid black;
+ border-radius: 20px;
+ width: 150px;
+ height: 50px;
+ line-height: 50px;
+ margin: 60px auto;
+ text-align: center;
+`;
+const LoginBtnContainer = styled.div`
+ margin-top: 50px;
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+`;
+const GoogleLogin = styled.button`
+ border: 1px solid black;
+ border-radius: 10px;
+ width: 330px;
+ height: 40px;
+ text-align: center;
+ display: flex;
+ align-items: center;
+ padding-left: 5px;
+ margin: 30px auto;
+ cursor: pointer;
+ &:hover {
+ background-color: grey;
+ }
+ span {
+ padding-left: 35px;
+ }
+`;
+const EmailLogin = styled(GoogleLogin)`
+ margin-bottom: 20px;
+`;
+const IconContainer = styled.div`
+ margin-right: 20px;
+`;
+const MoveSingUp = styled(Link)`
+ text-align: center;
+ margin-bottom: 20px;
+ font-size: 12px;
+ font-weight: bold;
+ color: #1c49ff;
+ span {
+ color: #909090;
+ font-weight: normal;
+ }
+`;
const SignIn = () => {
- return SignIn
;
+ const [isEmailModalOpen, setEmailModalOpen] = useState(false);
+ const showModal = () => {
+ setEmailModalOpen(true);
+ };
+ const handleCancel = () => {
+ setEmailModalOpen(false);
+ };
+ const handleOk = () => {
+ setEmailModalOpen(false);
+ };
+ return (
+
+
+ LOGO
+
+
+ Wiki에 오신 것을 환영합니다!
+
+ 시작하시기 전에 로그인을 해주세요!
+
+
+
+
+
+ Google로 로그인
+
+ OR
+
+
+
+
+ 직접 이메일 입력
+
+
+
+ 아직 계정이 없으신가요? 회원가입하기
+
+
+
+
+
+
+ );
};
export default SignIn;
diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx
index b466e403..40e5143d 100644
--- a/src/pages/SignUp.tsx
+++ b/src/pages/SignUp.tsx
@@ -1,7 +1,121 @@
-import React from "react";
+import { GoogleOutlined, MailOutlined } from "@ant-design/icons";
+import React, { useState } from "react";
+import { styled } from "styled-components";
+import { Modal } from "antd";
+import signInGoogle from "../components/SignIn/SignInGoogle";
+import { Link } from "react-router-dom";
+import SignUpEmailModal from "../components/SignUp/SignUpEmail";
+import { MainTitle } from "../components/SignUp/Title";
+const Container = styled.div`
+ margin: 0;
+ padding: 0;
+ width: 100vw;
+`;
+const SignUpContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ border: 1px solid black;
+ border-radius: 20px;
+ width: 50vw;
+ margin: 100px auto;
+ text-align: center;
+`;
+const Logo = styled.div`
+ border: 1px solid black;
+ border-radius: 20px;
+ width: 150px;
+ height: 50px;
+ line-height: 50px;
+ margin: 60px auto;
+ text-align: center;
+`;
+const LoginBtnContainer = styled.div`
+ margin-top: 50px;
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+`;
+const GoogleLogin = styled.button`
+ border: 1px solid black;
+ border-radius: 10px;
+ width: 330px;
+ height: 40px;
+ text-align: center;
+ display: flex;
+ align-items: center;
+ padding-left: 5px;
+ margin: 30px auto;
+ cursor: pointer;
+ &:hover {
+ background-color: grey;
+ }
+ span {
+ padding-left: 35px;
+ }
+`;
+const EmailLogin = styled(GoogleLogin)`
+ margin-bottom: 20px;
+`;
+const IconContainer = styled.div`
+ margin-right: 20px;
+`;
+const MoveSingIn = styled(Link)`
+ text-align: center;
+ margin-bottom: 20px;
+ font-size: 12px;
+ font-weight: bold;
+ color: #1c49ff;
+ span {
+ color: #909090;
+ font-weight: normal;
+ }
+`;
const SignUp = () => {
- return SignUp
;
+ const [isEmailModalOpen, setEmailModalOpen] = useState(false);
+ const showModal = () => {
+ setEmailModalOpen(true);
+ };
+ const handleCancel = () => {
+ setEmailModalOpen(false);
+ };
+ const handleOk = () => {
+ setEmailModalOpen(false);
+ };
+ return (
+
+
+ LOGO
+
+
+ Wiki에 오신 것을 환영합니다!
+
+ 시작하시기 전에 회원가입을 해주세요!
+
+
+
+
+
+ Google로 가입
+
+ OR
+
+
+
+
+ 직접 이메일 입력
+
+
+
+ 이미 계정이 있으신가요? 로그인하기
+
+
+
+
+
+
+ );
};
export default SignUp;
diff --git a/src/pages/Timer.tsx b/src/pages/Timer.tsx
index 9941ca8d..031ddbca 100644
--- a/src/pages/Timer.tsx
+++ b/src/pages/Timer.tsx
@@ -1,7 +1,51 @@
-import React from "react";
+import React, { useState } from "react";
+import { styled } from "styled-components";
+import TimerApp from "../components/Timer/TimerApp";
+
+const TimerContainer = styled.div`
+ width: 320px;
+ height: 260px;
+ border: 2px solid #3956a3;
+ border-radius: 40px;
+ padding: 15px 25px;
+ box-sizing: border-box;
+ white-space: pre-line;
+ display: flex;
+ justify-content: flex-end;
+ font-size: 1rem;
+ z-index: 999;
+ position: absolute;
+ top: 10%;
+ right: 5%;
+`;
+
+const TextAlign = styled.div`
+ text-align: right;
+`;
+
+const CloseModalBtn = styled.div`
+ width: 5px;
+ height: 5px;
+ cursor: pointer;
+ color: #535353;
+`;
+// const [closeModal, setCloseModal] = useState(false);
const Timer = () => {
- return Timer
;
+ // const closeModal = () => {
+ // setCloseModal(true);
+ // };
+
+ return (
+
+ X
+
+
+ 환영합니다. OOO 님!
+
+
+
+ );
};
export default Timer;
diff --git a/src/router/Router.tsx b/src/router/Router.tsx
index bd5dbc78..a8983fbf 100644
--- a/src/router/Router.tsx
+++ b/src/router/Router.tsx
@@ -1,6 +1,5 @@
import React from "react";
import { Route, Routes } from "react-router-dom";
-// import Layout from "../layouts/Layout";
import SubLayout from "../layouts/SubLayout";
import Main from "../pages/Main";
import Wiki from "../pages/Wiki";
@@ -12,7 +11,9 @@ import Timer from "../pages/Timer";
import SignIn from "../pages/SignIn";
import SignUp from "../pages/SignUp";
import Employee from "../pages/Employee";
-
+import StartRegister from "../components/SignUp/Register/StartRegister";
+import UserRegister from "../components/SignUp/Register/UserRegister";
+import EndRegister from "../components/SignUp/Register/EndRegister";
const Router = () => {
return (
@@ -40,6 +41,9 @@ const Router = () => {
}>
}>
}>
+ }>
+ }>
+ }>
);