diff --git a/ex.css b/ex.css
new file mode 100644
index 0000000..e64d2c4
--- /dev/null
+++ b/ex.css
@@ -0,0 +1,4 @@
+p {
+ justify-content: space-between;
+ flex-direction: column;
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 3a0df99..cde0503 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,9 @@
"cra-template": "1.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-router-dom": "^7.1.5",
"react-scripts": "5.0.1",
+ "styled-components": "^6.1.15",
"web-vitals": "^4.2.4"
}
},
@@ -2208,6 +2210,27 @@
"postcss-selector-parser": "^6.0.10"
}
},
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
+ "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==",
+ "license": "MIT"
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
+ "license": "MIT"
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
@@ -3303,6 +3326,12 @@
"@types/node": "*"
}
},
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "license": "MIT"
+ },
"node_modules/@types/eslint": {
"version": "8.56.12",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz",
@@ -3525,6 +3554,12 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
},
+ "node_modules/@types/stylis": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
+ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==",
+ "license": "MIT"
+ },
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
@@ -4947,6 +4982,15 @@
"node": ">= 6"
}
},
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/caniuse-api": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
@@ -5446,6 +5490,15 @@
"postcss": "^8.4"
}
},
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/css-declaration-sorter": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz",
@@ -5587,6 +5640,17 @@
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
},
+ "node_modules/css-to-react-native": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
"node_modules/css-tree": {
"version": "1.0.0-alpha.37",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
@@ -5774,6 +5838,12 @@
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
},
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "license": "MIT"
+ },
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -12720,6 +12790,55 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.5.tgz",
+ "integrity": "sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/cookie": "^0.6.0",
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0",
+ "turbo-stream": "2.4.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.5.tgz",
+ "integrity": "sha512-/4f9+up0Qv92D3bB8iN5P1s3oHAepSGa9h5k6tpTFlixTTskJZwKGhJ6vRJ277tLD1zuaZTt95hyGWV1Z37csQ==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.1.5"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/react-router/node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -13556,6 +13675,12 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -13604,6 +13729,12 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
+ "node_modules/shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -14207,6 +14338,68 @@
"webpack": "^5.0.0"
}
},
+ "node_modules/styled-components": {
+ "version": "6.1.15",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.15.tgz",
+ "integrity": "sha512-PpOTEztW87Ua2xbmLa7yssjNyUF9vE7wdldRfn1I2E6RTkqknkBYpj771OxM/xrvRGinLy2oysa7GOd7NcZZIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/is-prop-valid": "1.2.2",
+ "@emotion/unitless": "0.8.1",
+ "@types/stylis": "4.2.5",
+ "css-to-react-native": "3.2.0",
+ "csstype": "3.1.3",
+ "postcss": "8.4.49",
+ "shallowequal": "1.1.0",
+ "stylis": "4.3.2",
+ "tslib": "2.6.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/styled-components"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0",
+ "react-dom": ">= 16.8.0"
+ }
+ },
+ "node_modules/styled-components/node_modules/postcss": {
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/styled-components/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "license": "0BSD"
+ },
"node_modules/stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
@@ -14222,6 +14415,12 @@
"postcss": "^8.2.15"
}
},
+ "node_modules/stylis": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
+ "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==",
+ "license": "MIT"
+ },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@@ -14809,6 +15008,12 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
+ "node_modules/turbo-stream": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
+ "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
+ "license": "ISC"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/package.json b/package.json
index f70e9ed..88fb4db 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,9 @@
"cra-template": "1.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-router-dom": "^7.1.5",
"react-scripts": "5.0.1",
+ "styled-components": "^6.1.15",
"web-vitals": "^4.2.4"
},
"scripts": {
diff --git a/src/App.js b/src/App.js
index d24509b..7e692ee 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,9 +1,13 @@
-import './App.css';
+import React, { useState } from 'react';
+import AllList from './pages/AllList.jsx';
+import Complete from './pages/Complete.jsx';
-function App() {
+const App = () => {
return (
-
+ <>
+
+ >
);
-}
+};
export default App;
diff --git a/src/components/AllList/AddPopup.jsx b/src/components/AllList/AddPopup.jsx
new file mode 100644
index 0000000..26f8b14
--- /dev/null
+++ b/src/components/AllList/AddPopup.jsx
@@ -0,0 +1,106 @@
+import React, { useState } from 'react';
+import styled from 'styled-components';
+import cancel from '../../images/CancelBtn.png'
+
+
+
+const Popup = styled.div `
+ width: 336px;
+ height: 297px;
+ border-radius: 15px;
+ /*position: relative;*/
+ position: absolute;
+ top: 180px;
+ left: 28px;
+ background-color: #fff;
+ z-index: 1000; /* 팝업이 앞에 보이도록 z-index 설정 */
+`;
+
+const Content = styled.form `
+display: flex;
+ flex-direction: column; /* 세로로 쌓이도록 설정 */
+ margin: 12px 0 0 20px;
+`;
+
+const CancelBtn = styled.img `
+ position: absolute;
+ top: 12px;
+ right: 12px;
+ cursor: pointer; /* 클릭 가능하게 커서 변경 */
+`;
+
+const CategorySelect = styled.select `
+ width: 158px;
+ height: 35px;
+ border-radius: 20px;
+ border: 1px solid #000;
+ font-size: 15px;
+ padding: 9px 14px;
+ margin-bottom: 13px;
+`;
+
+const DifficultySelect = styled(CategorySelect) `
+
+`;
+
+const Title = styled.p `
+ margin: 0;
+font-size: 15px;
+ margin-bottom: 8px;
+ margin-left: 3px;
+
+`;
+
+const MissionText = styled.textarea `
+width: 287px;
+ height: 99px;
+ border: 1px solid #000;
+ border-radius: 3px;
+ resize: none; /* 크기 조절 불가능하게 설정 */
+`;
+
+const Submit = styled.button `
+ width: 104px;
+ height: 32px;
+ border-radius: 20px;
+ border: none;
+ background-color: #5AB2FF;
+ color: #fff;
+ font-size: 18px;
+ padding: 0 5px;
+ position: absolute;
+ bottom: 12px;
+ right: 22px;
+`;
+
+const AddPopup = ({ onClose }) => {
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 미션 내용
+
+ 추가하기
+
+
+
+ >
+ );
+};
+
+export default AddPopup;
diff --git a/src/components/AllList/DeletePopup.jsx b/src/components/AllList/DeletePopup.jsx
new file mode 100644
index 0000000..14c5709
--- /dev/null
+++ b/src/components/AllList/DeletePopup.jsx
@@ -0,0 +1,77 @@
+
+import React, { useState } from 'react';
+import styled from 'styled-components';
+
+
+
+const Popup = styled.div `
+ width: 336px;
+ height: 142px;
+ border-radius: 15px;
+ /*position: relative;*/
+ position: absolute;
+ top: 180px;
+ left: 28px;
+ background-color: #fff;
+ z-index: 1000; /* 팝업이 앞에 보이도록 z-index 설정 */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ `;
+
+const Content = styled.form `
+ display: flex;
+ flex-direction: column;
+`;
+
+const CancelBtn = styled.img `
+ position: absolute;
+ top: 12px;
+ right: 12px;
+ cursor: pointer; /* 클릭 가능하게 커서 변경 */
+`;
+
+const Warning = styled.p `
+ font-size: 20px;
+`;
+
+const ButtonWrap = styled.div `
+ display: flex;
+
+`;
+
+const Yes = styled.button `
+ width: 104px;
+ height: 32px;
+ border-radius: 20px;
+ border: none;
+ background-color: #fff;
+ border: 1px solid #000;
+ color: #000;
+ font-size: 18px;
+ padding: 0 5px;
+
+`;
+
+const No = styled(Yes) `
+margin-left: 22px;
+`;
+
+const DeletePopup = ({ onClose }) => {
+
+ return (
+ <>
+
+
+ 미션을 삭제하시겠습니까?
+
+ 예
+ 아니오
+
+
+
+ >
+ );
+};
+
+export default DeletePopup;
diff --git a/src/components/AllList/EditPopup.jsx b/src/components/AllList/EditPopup.jsx
new file mode 100644
index 0000000..0ce4b54
--- /dev/null
+++ b/src/components/AllList/EditPopup.jsx
@@ -0,0 +1,104 @@
+import React, { useState } from 'react';
+import styled from 'styled-components';
+import cancel from '../../images/CancelBtn.png'
+
+const Popup = styled.div `
+ width: 336px;
+ height: 297px;
+ border-radius: 15px;
+ /*position: relative;*/
+ position: absolute;
+ top: 180px;
+ left: 28px;
+ background-color: #fff;
+ z-index: 1000; /* 팝업이 앞에 보이도록 z-index 설정 */
+`;
+
+const Content = styled.form `
+display: flex;
+ flex-direction: column; /* 세로로 쌓이도록 설정 */
+ margin: 12px 0 0 20px;
+`;
+
+const CancelBtn = styled.img `
+ position: absolute;
+ top: 12px;
+ right: 12px;
+ cursor: pointer; /* 클릭 가능하게 커서 변경 */
+`;
+
+const CategorySelect = styled.select `
+ width: 158px;
+ height: 35px;
+ border-radius: 20px;
+ border: 1px solid #000;
+ font-size: 15px;
+ padding: 9px 14px;
+ margin-bottom: 13px;
+`;
+
+const DifficultySelect = styled(CategorySelect) `
+
+`;
+
+const Title = styled.p `
+ margin: 0;
+font-size: 15px;
+ margin-bottom: 8px;
+ margin-left: 3px;
+
+`;
+
+const MissionText = styled.textarea `
+width: 287px;
+ height: 99px;
+ border: 1px solid #000;
+ border-radius: 3px;
+ resize: none; /* 크기 조절 불가능하게 설정 */
+`;
+
+const Submit = styled.button `
+ width: 104px;
+ height: 32px;
+ border-radius: 20px;
+ border: none;
+ background-color: #5AB2FF;
+ color: #fff;
+ font-size: 18px;
+ padding: 0 5px;
+ position: absolute;
+ bottom: 12px;
+ right: 22px;
+`;
+
+const EditPopup = ({ onClose }) => {
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 미션 내용
+
+ 추가하기
+
+
+
+ >
+ );
+};
+
+export default EditPopup;
diff --git a/src/components/AllList/FuncPopup.jsx b/src/components/AllList/FuncPopup.jsx
new file mode 100644
index 0000000..6a972a4
--- /dev/null
+++ b/src/components/AllList/FuncPopup.jsx
@@ -0,0 +1,64 @@
+import React, { useState } from 'react';
+import styled from 'styled-components';
+import cancel from '../../images/CancelBtn.png'
+
+
+
+const Popup = styled.div `
+ width: 336px;
+ height: 142px;
+ border-radius: 15px;
+ /*position: relative;*/
+ position: absolute;
+ top: 180px;
+ left: 28px;
+ background-color: #fff;
+ z-index: 1000; /* 팝업이 앞에 보이도록 z-index 설정 */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ `;
+
+const Content = styled.form `
+ display: flex;
+`;
+
+const CancelBtn = styled.img `
+ position: absolute;
+ top: 12px;
+ right: 12px;
+ cursor: pointer; /* 클릭 가능하게 커서 변경 */
+`;
+
+const Edit = styled.button `
+ width: 104px;
+ height: 32px;
+ border-radius: 20px;
+ border: none;
+ background-color: #5AB2FF;
+ color: #fff;
+ font-size: 18px;
+ padding: 0 5px;
+
+`;
+
+const Delete = styled(Edit) `
+margin-left: 22px;
+`;
+
+const FuncPopup = ({ onClose }) => {
+
+ return (
+ <>
+
+
+ 수정하기
+ 삭제하기
+
+
+
+ >
+ );
+};
+
+export default FuncPopup;
diff --git a/src/components/AllList/Mission.jsx b/src/components/AllList/Mission.jsx
new file mode 100644
index 0000000..28a152d
--- /dev/null
+++ b/src/components/AllList/Mission.jsx
@@ -0,0 +1,76 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const missionColors = {
+ ing: '#FFEA63', // 진행중
+ yet: '#FFF9D0', // 미완료
+ done: '#D9D9D9', // 완료
+};
+
+
+const MissionDiv = styled.div`
+ width: 340px;
+ height: 45px;
+ background-color: ${({ type }) => missionColors[type] || '#E5E5E5'}; // 상태에 따라 배경색 변경
+ margin-bottom: 10px;
+ padding: 7px 0px 7px 8px;
+ `;
+
+const MissionDetail = styled.div `
+ display: flex;
+`;
+
+const MissionCategory = styled.p`
+ background-color: ${({ color }) => color};
+ border-radius: 5px;
+ font-size: 10px;
+ color: #000;
+ margin: 0;
+ width: 52px;
+ height: 13px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-right: 3px;
+`;
+
+const MissionDifficulty = styled.p`
+ width: 17px;
+ height: 12px;
+ background-color: #FFF9D0;
+ font-size: 10px;
+ color: #fff;
+ margin: 0;
+ border-radius: 5px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`;
+
+const MissionText = styled.p`
+ flex-grow: 1;
+ font-size: 14px;
+ margin: 0;
+`;
+
+const Mission = ({ type, category, text }) => {
+ const categoryData = {
+ 자기계발: '#FFF1F1',
+ 공부: '#FFE4CC',
+ 건강: '#E8FFE3',
+ 취미: '#E9F2FF',
+ 기타: '#F2E9FF',
+ };
+
+ return (
+
+
+ {category}
+ 상
+
+ {text}
+
+ );
+};
+
+export default Mission;
diff --git a/src/components/Challenge/CardDetail.jsx b/src/components/Challenge/CardDetail.jsx
new file mode 100644
index 0000000..54e4a13
--- /dev/null
+++ b/src/components/Challenge/CardDetail.jsx
@@ -0,0 +1,155 @@
+import React, { useState } from 'react';
+import styled from 'styled-components';
+import cancel from '../../images/CancelBtn.png'
+
+
+
+const Popup = styled.div `
+ width: 226px;
+ height: 292px;
+ border-radius: 15px;
+ /*position: relative;*/
+ position: absolute;
+ top: 200px;
+ left: 75px;
+ box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.3);
+ background-color: ${({ color }) => color};
+ z-index: 1000; /* 팝업이 앞에 보이도록 z-index 설정 */
+`;
+
+const Content = styled.form `
+display: flex;
+ flex-direction: column; /* 세로로 쌓이도록 설정 */
+ margin: 25px 0 0 15px;
+`;
+
+const CancelBtn = styled.img `
+ position: absolute;
+ top: 12px;
+ right: 12px;
+ cursor: pointer; /* 클릭 가능하게 커서 변경 */
+`;
+
+const MissionText = styled.h3 `
+ margin: 0;
+ font-size: 15px;
+ margin-bottom: 8px;
+ font-weight: bold;
+
+`;
+
+const MissionDetail = styled.div `
+ display: flex;
+ margin-bottom: 8px;
+ align-items: center;
+`;
+
+const MissionCategory = styled.p`
+ border-radius: 5px;
+ font-size: 10px;
+ color: #000;
+ margin: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`;
+
+const MissionDifficulty = styled.p`
+ width: 17px;
+ height: 12px;
+ background-color: #FFF9D0;
+ font-size: 10px;
+ color: #000;
+ margin: 0;
+ border-radius: 5px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-left: 5px;
+`;
+
+const SubTitle = styled.p`
+ margin: 0;
+ font-size: 12px;
+ margin-bottom: 8px;
+ font-weight: bold;
+`;
+
+const RateWrap = styled.div `
+ display: flex;
+ margin-bottom: 8px;
+
+`;
+
+const RateYellow = styled.div `
+ width: 147px;
+ height: 12px;
+ border-radius: 20px;
+ background-color: #FFFDF0;
+`;
+
+const RateBlue = styled.div `
+ width: ${({ rate }) => rate}%;
+ height: 12px;
+ border-radius: 20px;
+ background-color: #A0DEFF;
+`;
+
+const RateText = styled.p `
+ margin: 0;
+ font-size: 10px;
+ margin-left: 9px;
+`;
+
+const Memo = styled.div `
+ width: 195px;
+ height: 112px;
+ border-radius: 15px;
+ background-color: #FBFBFB;
+ display: flex;
+ justify-content: center;
+ padding-top: 11px;
+`;
+
+const MemoText = styled.p `
+ font-size: 10px;
+ width: 156px;
+ height: 84px;
+ overflow: hidden;
+`;
+
+
+const CardDetail = ({ onClose, category, rate }) => {
+ const categoryData = {
+ 자기계발: '#FFF1F1',
+ 공부: '#FFE4CC',
+ 건강: '#E8FFE3',
+ 취미: '#E9F2FF',
+ 기타: '#F2E9FF',
+ };
+ return (
+ <>
+
+
+ 미션 내용
+
+ {category}
+ 상
+
+ 성취율
+
+
+
+
+ {rate}%
+
+ 메모
+ 어쩌구저쩌구
+
+
+
+ >
+ );
+};
+
+export default CardDetail;
diff --git a/src/components/Challenge/Cards.jsx b/src/components/Challenge/Cards.jsx
new file mode 100644
index 0000000..b63c0e1
--- /dev/null
+++ b/src/components/Challenge/Cards.jsx
@@ -0,0 +1,95 @@
+import React from 'react';
+import styled from 'styled-components';
+import star from '../../images/Star.png';
+import noStar from '../../images/NoStar.png';
+
+const categoryColors = {
+ develope: '#FFF1F1', // 자기계발 카테고리 색상
+ study: '#FFE4CC', // 공부 카테고리 색상
+ health: '#E8FFE3', // 건강 카테고리 색상
+ hobby: '#E9F2FF', // 취미 카테고리 색상
+ others: '#F2E9FF', // 기타 카테고리 색상
+ };
+
+const Card = styled.div `
+ width: 115px;
+ height: 140px;
+ border-radius: 15px;
+ background-color: ${({ category }) => categoryColors[category] || '#E5E5E5'}; // 카테고리에 따라 배경색 변경
+ display: flex;
+ flex-direction: column;
+ align-items:center;
+ box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.3);
+ margin-bottom: 36px;
+
+ &:hover {
+ background-color: ${({ category }) => categoryColors[category] ? darkenColor(categoryColors[category], 0.1) : '#ccc'};
+ }
+ `;
+
+const CardContent = styled.div `
+ width: 100px;
+ padding: 18px 0 15px 0;
+ border-bottom: 1px solid #B0B0B0;
+ display: flex;
+ flex-direction: column;
+ align-items:center;
+`;
+
+const Mission = styled.p `
+ font-size: 15px;
+ margin: 0;
+`;
+
+const MissionNum = styled.p `
+ font-size: 40px;
+ margin: 0;
+`;
+
+const StarWrap = styled.div `
+ width: 90px;
+ display: flex;
+ justify-content: space-between;
+ margin-top: 3px;
+`;
+
+const Star = styled.img `
+`;
+
+// 색상을 어둡게 만드는 함수 (옵션)
+const darkenColor = (color, percentage) => {
+ const colorCode = color.slice(1);
+ const num = parseInt(colorCode, 16);
+ const amt = Math.round(2.55 * percentage * 100);
+ const R = (num >> 16) + amt;
+ const G = ((num >> 8) & 0x00ff) + amt;
+ const B = (num & 0x0000ff) + amt;
+ return `#${(
+ 0x1000000 +
+ (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +
+ (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +
+ (B < 255 ? (B < 1 ? 0 : B) : 255)
+ )
+ .toString(16)
+ .slice(1)}`;
+ };
+
+const Cards = ({category, number}) => {
+ return (
+ <>
+
+
+ mission
+ {number}
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default Cards;
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
new file mode 100644
index 0000000..2f5b0be
--- /dev/null
+++ b/src/components/Footer.jsx
@@ -0,0 +1,66 @@
+import React from 'react';
+import styled from 'styled-components';
+
+const FooterDiv = styled.div`
+ width: 365px;
+ height: 102px;
+ background-color: black;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ padding-left: 28px;
+ position: absolute;
+ top: 750px;
+ `;
+
+const AppTitle = styled.h3 `
+ font-size: 15px;
+ font-weight: bold;
+ color: #ffffff;
+ margin: 0;
+ margin-bottom: 5px;
+`;
+
+const Team = styled.p `
+ font-size: 12px;
+ color: #ffffff;
+ margin: 0;
+ margin-bottom: 3px;
+`;
+
+const MemberDiv = styled.div `
+ display: flex;
+`;
+
+const Member = styled(Team) `
+ font-size: 10px;
+ margin-right: 9px;
+`;
+
+const Position = styled(Member) `
+ font-weight: bold;
+ margin-right: 5px;
+`;
+
+const Club = styled.p `
+ margin: 0;
+ font-size: 12px;
+ color: #ffffff;
+ margin-top: 10px;
+`;
+
+const Footer = () => {
+
+ return (
+ <>
+
+ 작심3일
+ N3W
+ 백엔드김미주 심수빈 정민주프론트엔드 박민주 박소이
+ DSWU CORNER
+
+ >
+ );
+};
+
+export default Footer;
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
new file mode 100644
index 0000000..8d9751f
--- /dev/null
+++ b/src/components/Header.jsx
@@ -0,0 +1,54 @@
+import React, { useState } from 'react';
+import styled from 'styled-components';
+import logoimg from '../images/Logo.png';
+import hamburger from '../images/hamburger.png';
+import Sidebar from './Sidebar.jsx';
+
+const HeaderDiv = styled.div`
+ width: 393px;
+ height: 66px;
+ border: 1.5px solid #B5B5B5;
+ display: flex;
+ align-items: center;
+`;
+
+const Logo = styled.img`
+ height: 29.38px;
+ margin-left: 24.48px;
+`;
+
+const HamburgerBtn = styled.button`
+ background: none;
+ border: none;
+ margin-left: auto;
+ margin-right: 24.48px;
+`;
+
+const HamburgerImg = styled.img`
+ width: 24px;
+ height: 24px;
+`;
+
+const Header = () => {
+ // useState를 컴포넌트 함수 내에 선언
+ const [isOpen, setIsOpen] = useState(false);
+
+ // 사이드바를 열고 닫는 함수
+ const toggleSide = () => {
+ setIsOpen(!isOpen);
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default Header;
diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx
new file mode 100644
index 0000000..ce0126b
--- /dev/null
+++ b/src/components/Sidebar.jsx
@@ -0,0 +1,103 @@
+import React, { useRef, useEffect } from 'react';
+import styled from 'styled-components';
+import Complete from '../images/Complete.png';
+import AllList from '../images/AllList.png';
+import Challenge from '../images/Challenge.png';
+
+
+// styled-components를 사용한 스타일링
+
+const Display = styled.div`
+ width: 393px;
+ height: 852px;
+ position: relative;
+ border: 1px solid #ccc; /* 확인을 위해 경계선 추가 */
+`;
+
+const SideBarWrap = styled.div`
+ z-index: 5;
+ padding: 12px;
+ border-radius: 15px 0 0 15px;
+ background-color: #FFFFFF80;
+ height: 100%;
+ width: 200px;
+ right: -200px; /* 닫혔을 때는 화면 밖에 위치 */
+ top: 0;
+ position: absolute;
+ transition: 0.5s ease;
+
+ &.open {
+ right: 15px; /* 열렸을 때는 화면 안으로 이동 */
+ transition: 0.5s ease;
+ }
+`;
+
+
+const MenuWrap = styled.ul `
+ list-style: none;
+ padding: 0;
+ margin-top: 100px;
+`;
+
+const MenuImg = styled.img `
+ width: 24px;
+ heigiht: 24px;
+`;
+
+const Menu = styled.li`
+ display: flex;
+ padding-top: 20px;
+ padding-bottom: 15px;
+ border-bottom: 1.5px solid rgb(231, 231, 231);
+
+ &:last-child {
+ border: none;
+ }
+`;
+
+const MenuText = styled.p `
+ font-size: 15px;
+ margin: 0;
+ margin-left: 24px;
+`;
+
+const ExitMenu = styled.span`
+ position: absolute;
+ bottom: 26px;
+ font-size: 0.8rem;
+`;
+
+function Sidebar({ isOpen, setIsOpen }) {
+ const outside = useRef(null);
+
+ // 사이드바 외부 클릭 시 닫히는 로직
+ const handlerOutside = (e) => {
+ if (outside.current && !outside.current.contains(e.target)) {
+ toggleSide();
+ }
+ };
+
+ useEffect(() => {
+ document.addEventListener('mousedown', handlerOutside);
+ return () => {
+ document.removeEventListener('mousedown', handlerOutside);
+ };
+ }, []); // 한 번만 실행되도록 설정
+
+ // 사이드바를 닫는 함수
+ const toggleSide = () => {
+ setIsOpen(false);
+ };
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+export default Sidebar;
\ No newline at end of file
diff --git a/src/images/AllList.png b/src/images/AllList.png
new file mode 100644
index 0000000..aedf5e3
Binary files /dev/null and b/src/images/AllList.png differ
diff --git a/src/images/CancelBtn.png b/src/images/CancelBtn.png
new file mode 100644
index 0000000..8eaf092
Binary files /dev/null and b/src/images/CancelBtn.png differ
diff --git a/src/images/Challenge.png b/src/images/Challenge.png
new file mode 100644
index 0000000..4be13c9
Binary files /dev/null and b/src/images/Challenge.png differ
diff --git a/src/images/Complete.png b/src/images/Complete.png
new file mode 100644
index 0000000..e30fafc
Binary files /dev/null and b/src/images/Complete.png differ
diff --git a/src/images/Logo.png b/src/images/Logo.png
new file mode 100644
index 0000000..85db456
Binary files /dev/null and b/src/images/Logo.png differ
diff --git a/src/images/Logout.png b/src/images/Logout.png
new file mode 100644
index 0000000..089e887
Binary files /dev/null and b/src/images/Logout.png differ
diff --git a/src/images/NoStar.png b/src/images/NoStar.png
new file mode 100644
index 0000000..bd99617
Binary files /dev/null and b/src/images/NoStar.png differ
diff --git a/src/images/PlusBtn.png b/src/images/PlusBtn.png
new file mode 100644
index 0000000..a7d29b3
Binary files /dev/null and b/src/images/PlusBtn.png differ
diff --git a/src/images/Star.png b/src/images/Star.png
new file mode 100644
index 0000000..e71c96d
Binary files /dev/null and b/src/images/Star.png differ
diff --git a/src/images/hamburger.png b/src/images/hamburger.png
new file mode 100644
index 0000000..9f5b206
Binary files /dev/null and b/src/images/hamburger.png differ
diff --git a/src/pages/AllList.jsx b/src/pages/AllList.jsx
new file mode 100644
index 0000000..69657db
--- /dev/null
+++ b/src/pages/AllList.jsx
@@ -0,0 +1,129 @@
+import React, { useState } from 'react';
+import Header from '../components/Header.jsx';
+import Footer from '../components/Footer.jsx';
+import PlusBtn from '../images/PlusBtn.png';
+import Mission from '../components/AllList/Mission.jsx';
+import styled from 'styled-components';
+import AddPopup from '../components/AllList/AddPopup.jsx';
+import FuncPopup from '../components/Challenge/CardDetail.jsx';
+import DeletePopup from '../components/AllList/DeletePopup.jsx';
+import CardDetail from '../components/Challenge/CardDetail.jsx';
+
+const Display = styled.div `
+ width: 393px;
+ height: 852px;
+ border: 1px solid #000;
+`;
+
+const Content = styled.div `
+ display: flex;
+ align-items: center;
+ flex-direction: column; /* 세로로 쌓이도록 설정 */
+ margin-top: 26px;
+`;
+
+const FuncDiv = styled.div `
+ display: flex;
+ width: 340px;
+ margin-bottom: 20px;
+ justify-content: space-between;
+`;
+
+const AddMission = styled.div `
+ width: 51px;
+ height: 35px;
+ border-radius: 20px;
+ background-color: #CAF4FF;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`;
+
+const Plus = styled.img `
+`;
+
+const CategorySelect = styled.select `
+ width: 158px;
+ height: 35px;
+ border-radius: 20px;
+ border: 1px solid #000;
+ font-size: 15px;
+ padding: 9px 14px;
+`;
+
+const MissionWrap = styled.div`
+ width: 393px;
+ height: 599px;
+ display: flex;
+ flex-direction: column; /* 세로로 쌓이도록 설정 */
+ align-items: center;
+ overflow-y: scroll; /* 세로 스크롤 */
+
+ /* 스크롤바 숨기기 */
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+`;
+
+const AllList = () => {
+
+ const [showPopup, setShowPopup] = useState(false); // 팝업 상태 관리
+
+ const handleAddMission = () => {
+ setShowPopup(true); // 플러스 버튼 클릭 시 팝업 열기
+ };
+
+ const handleClosePopup = () => {
+ setShowPopup(false); // 팝업 닫기
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {showPopup && } {/* 팝업 표시 */}
+
+
+
+ >
+ );
+};
+
+export default AllList;
diff --git a/src/pages/Complete.jsx b/src/pages/Complete.jsx
new file mode 100644
index 0000000..a2d0f45
--- /dev/null
+++ b/src/pages/Complete.jsx
@@ -0,0 +1,113 @@
+import React, { useState } from 'react';
+
+import styled from 'styled-components';
+import Cards from '../components/Challenge/Cards.jsx';
+import Header from '../components/Header.jsx';
+import Footer from '../components/Footer.jsx';
+import CardDetail from '../components/Challenge/CardDetail.jsx';
+
+const Display = styled.div `
+ width: 393px;
+ height: 852px;
+ border: 1px solid #000;
+`;
+
+const CategoryWrap = styled.div `
+ width: 320px;
+ display: flex;
+ justify-content: space-around;
+ margin-top: 25px;
+ padding: 0 5px 18px 5px;
+ border-bottom: 1px solid #B0B0B0;
+`;
+
+const Category = styled.div `
+ width: 46px;
+ height: 20px;
+ border-radius: 50px;
+ font-size: 10px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`;
+
+const Content = styled.div `
+ width: 393px;
+ display: flex;
+ flex-direction: column;
+ align-items:center;
+`;
+
+const CardWarp = styled.div`
+ width: 365px;
+ height: 595px;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ gap: 0;
+ margin-top: 22px;
+ overflow-y: scroll;
+
+ /* 스크롤바 숨기기 */
+ &::-webkit-scrollbar {
+ display: none;
+ }
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+`;
+
+const Complete = () => {
+
+ const [showPopup, setShowPopup] = useState(false); // 팝업 상태 관리
+
+ const handleOpenPopup = () => {
+ setShowPopup(true); // 플러스 버튼 클릭 시 팝업 열기
+ };
+
+ const handleClosePopup = () => {
+ setShowPopup(false); // 팝업 닫기
+ };
+
+ const categoryData = [
+ { name: '전체', color: '#E5E5E5' },
+ { name: '자기계발', color: '#FFF1F1' },
+ { name: '공부', color: '#FFE4CC' },
+ { name: '건강', color: '#E8FFE3' },
+ { name: '취미', color: '#E9F2FF' },
+ { name: '기타', color: '#F2E9FF' },
+ ];
+
+ return (
+ <>
+
+
+
+
+ {categoryData.map((category, index) => (
+
+ {category.name}
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {showPopup && } {/* 팝업 표시 */}
+
+
+
+
+ >
+ );
+};
+
+export default Complete;