diff --git a/.github/workflows/react.yml b/.github/workflows/react.yml new file mode 100644 index 0000000..ef2409c --- /dev/null +++ b/.github/workflows/react.yml @@ -0,0 +1,35 @@ +name: Deploy React + +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: react docker build and push + run: | + docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} + docker build -t ${{ secrets.DOCKER_REPO }}/eum-react:latest . + docker push ${{ secrets.DOCKER_REPO }}/eum-react:latest + + - name: executing remote ssh commands using password + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_HOST }} + username: ${{ secrets.AWS_ID }} + key: ${{ secrets.AWS_KEY }} + script: | + if [ "$(sudo docker ps -qa)" ]; then + sudo docker rm -f $(sudo docker ps -qa) + fi + + sudo docker pull ${{ secrets.DOCKER_REPO }}/eum-react:latest + + cd alpha-e_um-deploy + sudo docker-compose -f docker-compose.yaml up -d + sudo docker image prune -f \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fb555f8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM node:alpine as builder +WORKDIR /usr/src/app +COPY package.json . +RUN npm install +COPY ./ ./ +RUN npm run build + +FROM nginx +EXPOSE 3000 +COPY ./default.conf /etc/nginx/conf.d/default.conf +COPY --from=builder usr/src/app/build /usr/share/nginx/html \ No newline at end of file diff --git a/Frontend.zip b/Frontend.zip new file mode 100644 index 0000000..e962a96 Binary files /dev/null and b/Frontend.zip differ diff --git a/default.conf b/default.conf new file mode 100644 index 0000000..daa86a0 --- /dev/null +++ b/default.conf @@ -0,0 +1,11 @@ +server { + listen 3000; + + location / { + + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c61aa3a..ef884aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,17 @@ "name": "front", "version": "0.1.0", "dependencies": { + "@react-oauth/google": "^0.12.1", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.6.8", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-modal": "^3.16.1", "react-router-dom": "^6.22.3", "react-scripts": "5.0.1", + "recoil": "^0.7.7", "styled-components": "^6.1.8", "web-vitals": "^2.1.4" } @@ -3372,6 +3376,15 @@ } } }, + "node_modules/@react-oauth/google": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@react-oauth/google/-/google-0.12.1.tgz", + "integrity": "sha512-qagsy22t+7UdkYAiT5ZhfM4StXi9PPNvw0zuwNmabrWyMKddczMtBIOARflbaIj+wHiQjnMAsZmzsUYuXeyoSg==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@remix-run/router": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", @@ -5500,6 +5513,29 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -8311,6 +8347,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", @@ -8611,9 +8652,9 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -9149,6 +9190,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hamt_plus": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz", + "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==" + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -14834,6 +14880,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -15122,6 +15173,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-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -15264,6 +15338,25 @@ "node": ">=8.10.0" } }, + "node_modules/recoil": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.7.tgz", + "integrity": "sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ==", + "dependencies": { + "hamt_plus": "1.0.2" + }, + "peerDependencies": { + "react": ">=16.13.1" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/recursive-readdir": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", @@ -17549,6 +17642,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 c732427..b4f9101 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,17 @@ "version": "0.1.0", "private": true, "dependencies": { + "@react-oauth/google": "^0.12.1", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.6.8", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-modal": "^3.16.1", "react-router-dom": "^6.22.3", "react-scripts": "5.0.1", + "recoil": "^0.7.7", "styled-components": "^6.1.8", "web-vitals": "^2.1.4" }, diff --git a/public/icons/alert.svg b/public/icons/alert.svg new file mode 100644 index 0000000..7c0db86 --- /dev/null +++ b/public/icons/alert.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/heart.svg b/public/icons/heart.svg new file mode 100644 index 0000000..02b1e1d --- /dev/null +++ b/public/icons/heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/poster.png b/public/images/poster.png new file mode 100644 index 0000000..8b17666 Binary files /dev/null and b/public/images/poster.png differ diff --git a/public/index.html b/public/index.html index aa069f2..36aecff 100644 --- a/public/index.html +++ b/public/index.html @@ -24,6 +24,15 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> + + + + + React App diff --git a/src/App.js b/src/App.js index 6b0d0d8..5e4adf1 100644 --- a/src/App.js +++ b/src/App.js @@ -1,13 +1,51 @@ import "./App.css"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import Main from "./pages/Main/main"; +import MyPage from "./pages/MyPage/myPage"; +import TeamSearch from "./pages/TeamSearch/teamSearch"; +import MemberSearch from "./pages/MemberSearch/memberSearch"; +import Login from "./pages/Login/login"; +import { useRecoilState } from "recoil"; +import { useEffect } from "react"; +import { axiosWithAuth } from "./lib/axios"; +import { userInfoState } from "./states/authState"; const App = () => { + const [userInfo, setUserInfo] = useRecoilState(userInfoState); + const accessToken = localStorage.getItem("access_token"); + + const getUserInfo = async () => { + axiosWithAuth + .get("/api/user/me") + .then((res) => { + setUserInfo({ + isLogin: true, + userId: res.data.userId, + email: res.data.email, + name: res.data.name.first, + fullName: res.data.name.fullName, + avatar: res.data.avatar, + mbti: res.data.mbti, + }); + console.log(res); + console.log("userInfo", userInfo); + }) + .catch((err) => console.error(err)); + }; + + useEffect(() => { + getUserInfo(); + }, []); + return (
} /> + } /> + } /> + } /> + } />
diff --git a/src/api/contestTestData.js b/src/api/contestTestData.js new file mode 100644 index 0000000..12738d5 --- /dev/null +++ b/src/api/contestTestData.js @@ -0,0 +1,32 @@ +const contestTestData = [ + { + id: 1, + deadline: 5, + name: "창의력을 키우는 공모전", + organizer: "창의력 협회", + views: "1,234", + }, + { + id: 2, + deadline: 6, + name: "예술과 기술을 결합한 공모전", + organizer: "미술과 기술 협회", + views: "987", + }, + { + id: 3, + deadline: 7, + name: "환경 보호를 위한 공모전", + organizer: "환경 보호 단체", + views: "5,678", + }, + { + id: 4, + deadline: 8, + name: "환경 보호를 위한 공모전", + organizer: "환경 보호 단체", + views: "5,678", + }, +]; + +export default contestTestData; diff --git a/src/api/memberTestData.js b/src/api/memberTestData.js new file mode 100644 index 0000000..a6e2bac --- /dev/null +++ b/src/api/memberTestData.js @@ -0,0 +1,67 @@ +const memberTestData = [ + { + id: 1, + name: "홍길동", + position: "프론트엔드 개발자", + gender: "남성", + location: "서울", + introduction: + "React와 JavaScript 경험이 있는 열정적인 프론트엔드 개발자입니다.", + skill1: "React", + skill2: "JavaScript", + }, + { + id: 2, + name: "이영희", + position: "백엔드 개발자", + gender: "여성", + location: "부산", + introduction: "Node.js와 MongoDB에 능숙한 백엔드 개발자입니다.", + skill1: "Node.js", + skill2: "MongoDB", + }, + { + id: 3, + name: "김철수", + position: "풀스택 개발자", + gender: "남성", + location: "인천", + introduction: "프론트엔드와 백엔드 기술에 능숙한 풀스택 개발자입니다.", + skill1: "React", + skill2: "Node.js", + }, + { + id: 4, + name: "박영미", + position: "UI/UX 디자이너", + gender: "여성", + location: "광주", + introduction: + "사용자 중심 설계에 열정을 가진 창의적인 UI/UX 디자이너입니다.", + skill1: "Adobe XD", + skill2: "Figma", + }, + { + id: 5, + name: "정영호", + position: "모바일 개발자", + gender: "남성", + location: "대전", + introduction: "iOS와 Android 개발에 능숙한 경험 많은 모바일 개발자입니다.", + skill1: "iOS", + skill2: "Android", + }, + { + id: 6, + name: "이수진", + position: "데이터 과학자", + gender: "여성", + location: "울산", + introduction: + "머신러닝과 데이터 분석에 대한 배경을 가진 데이터 과학자입니다.", + skill1: "Python", + skill2: "TensorFlow", + }, +]; + +export default memberTestData; diff --git a/src/api/memberTestData3.js b/src/api/memberTestData3.js new file mode 100644 index 0000000..a9d95ad --- /dev/null +++ b/src/api/memberTestData3.js @@ -0,0 +1,132 @@ +const memberTestData3 = [ + { + id: 1, + name: "홍길동", + position: "프론트엔드 개발자", + gender: "남성", + location: "서울", + introduction: + "React와 JavaScript 경험이 있는 열정적인 프론트엔드 개발자입니다.", + skill1: "React", + skill2: "JavaScript", + }, + { + id: 2, + name: "이영희", + position: "백엔드 개발자", + gender: "여성", + location: "부산", + introduction: "Node.js와 MongoDB에 능숙한 백엔드 개발자입니다.", + skill1: "Node.js", + skill2: "MongoDB", + }, + { + id: 3, + name: "김철수", + position: "풀스택 개발자", + gender: "남성", + location: "인천", + introduction: "프론트엔드와 백엔드 기술에 능숙한 풀스택 개발자입니다.", + skill1: "React", + skill2: "Node.js", + }, + { + id: 4, + name: "박영미", + position: "UI/UX 디자이너", + gender: "여성", + location: "광주", + introduction: + "사용자 중심 설계에 열정을 가진 창의적인 UI/UX 디자이너입니다.", + skill1: "Adobe XD", + skill2: "Figma", + }, + { + id: 5, + name: "정영호", + position: "모바일 개발자", + gender: "남성", + location: "대전", + introduction: "iOS와 Android 개발에 능숙한 경험 많은 모바일 개발자입니다.", + skill1: "iOS", + skill2: "Android", + }, + { + id: 6, + name: "이수진", + position: "데이터 과학자", + gender: "여성", + location: "울산", + introduction: + "머신러닝과 데이터 분석에 대한 배경을 가진 데이터 과학자입니다.", + skill1: "Python", + skill2: "TensorFlow", + }, + // 데이터 반복 추가 + { + id: 7, + name: "홍길동", + position: "프론트엔드 개발자", + gender: "남성", + location: "서울", + introduction: + "React와 JavaScript 경험이 있는 열정적인 프론트엔드 개발자입니다.", + skill1: "React", + skill2: "JavaScript", + }, + { + id: 8, + name: "이영희", + position: "백엔드 개발자", + gender: "여성", + location: "부산", + introduction: "Node.js와 MongoDB에 능숙한 백엔드 개발자입니다.", + skill1: "Node.js", + skill2: "MongoDB", + }, + { + id: 9, + name: "김철수", + position: "풀스택 개발자", + gender: "남성", + location: "인천", + introduction: "프론트엔드와 백엔드 기술에 능숙한 풀스택 개발자입니다.", + skill1: "React", + skill2: "Node.js", + }, + { + id: 10, + name: "박영미", + position: "UI/UX 디자이너", + gender: "여성", + location: "광주", + introduction: + "사용자 중심 설계에 열정을 가진 창의적인 UI/UX 디자이너입니다.", + skill1: "Adobe XD", + skill2: "Figma", + }, + { + id: 11, + name: "정영호", + position: "모바일 개발자", + gender: "남성", + location: "대전", + introduction: "iOS와 Android 개발에 능숙한 경험 많은 모바일 개발자입니다.", + skill1: "iOS", + skill2: "Android", + }, + { + id: 12, + name: "이수진", + position: "데이터 과학자", + gender: "여성", + location: "울산", + introduction: + "머신러닝과 데이터 분석에 대한 배경을 가진 데이터 과학자입니다.", + skill1: "Python", + skill2: "TensorFlow", + }, + // 추가 데이터 계속 반복 추가 +]; + +export default memberTestData3; diff --git a/src/api/memberTestDats2.js b/src/api/memberTestDats2.js new file mode 100644 index 0000000..8dc23e0 --- /dev/null +++ b/src/api/memberTestDats2.js @@ -0,0 +1,35 @@ +const memberTestData2 = [ + { + id: 1, + name: "홍길동", + position: "프론트엔드 개발자", + gender: "남성", + location: "서울", + introduction: + "React와 JavaScript 경험이 있는 열정적인 프론트엔드 개발자입니다.", + skill1: "React", + skill2: "JavaScript", + }, + { + id: 2, + name: "이영희", + position: "백엔드 개발자", + gender: "여성", + location: "부산", + introduction: "Node.js와 MongoDB에 능숙한 백엔드 개발자입니다.", + skill1: "Node.js", + skill2: "MongoDB", + }, + { + id: 3, + name: "김철수", + position: "풀스택 개발자", + gender: "남성", + location: "인천", + introduction: "프론트엔드와 백엔드 기술에 능숙한 풀스택 개발자입니다.", + skill1: "React", + skill2: "Node.js", + }, +]; + +export default memberTestData2; diff --git a/src/api/myResumeTestData.js b/src/api/myResumeTestData.js new file mode 100644 index 0000000..c983990 --- /dev/null +++ b/src/api/myResumeTestData.js @@ -0,0 +1,76 @@ +const MyResumeTestData = [ + { + name: "이름", + gender: "성별", + age: "나이", + belong: "소속", + region: "지역", + introduction: "한줄 소개가나다라마바사", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, + { + name: "최태호", + gender: "남", + age: "19", + belong: "국민대학교", + region: "서울", + introduction: "풂풂", + }, +]; + +export default MyResumeTestData; diff --git a/src/api/myTeamTestData.js b/src/api/myTeamTestData.js new file mode 100644 index 0000000..12953a4 --- /dev/null +++ b/src/api/myTeamTestData.js @@ -0,0 +1,157 @@ +const MyTeamTestData = [ + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: + "한줄 가나 가나 가나 가나 가나 가나 가나 가나 가나 가나 가나 가나 가나 가나", + }, + { + projectName: "알파", + teamName: "이음", + region: "서울/경기", + recruitment: false, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, + { + projectName: "프로젝트이름", + teamName: "팀이름", + region: "지역", + recruitment: true, + recruitmentTime: "1시간", + introduction: "한줄 소개", + }, +]; + +export default MyTeamTestData; diff --git a/src/api/supportTestData.js b/src/api/supportTestData.js new file mode 100644 index 0000000..91e503d --- /dev/null +++ b/src/api/supportTestData.js @@ -0,0 +1,233 @@ +const supportTestData = [ + { + projectName: "프로젝트이름", + teamName: "팀명", + region: "지역", + date: "2020.01.01", + time: "10:01", + introduction: "한줄소개", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: false, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: false, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, + { + projectName: "하이하이", + teamName: "하하", + region: "서울", + date: "2020.01.01", + time: "10:01", + introduction: + "한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄한줄", + pass: true, + }, +]; + +export default supportTestData; diff --git a/src/api/teamTestData.js b/src/api/teamTestData.js new file mode 100644 index 0000000..08512a1 --- /dev/null +++ b/src/api/teamTestData.js @@ -0,0 +1,80 @@ +const teamTestData = [ + { + id: 1, + projectName: "Awesome Project", + recruitmentStatus: true, + postedTime: "2024-03-16T12:00:00Z", + teamName: "Dream Team", + location: "서울", + projectDescription: + "이 프로젝트는 놀라운 기술을 개발하는 것을 목표로 합니다.", + category1: "웹 개발", + category2: "인공지능", + like: false, + }, + { + id: 2, + projectName: "Cool Project", + recruitmentStatus: false, + postedTime: "2024-03-15T09:30:00Z", + teamName: "Tech Savvy", + location: "경기", + projectDescription: + "최신 기술을 활용하여 혁신적인 솔루션을 개발하는 프로젝트입니다.", + category1: "앱 개발", + category2: "데이터 분석", + like: true, + }, + { + id: 3, + projectName: "Innovative Project", + recruitmentStatus: true, + postedTime: "2024-03-14T15:45:00Z", + teamName: "Code Masters", + location: "부산", + projectDescription: "창의적인 소프트웨어 솔루션을 개발하는 프로젝트입니다.", + category1: "게임 개발", + category2: "블록체인", + like: true, + }, + { + id: 4, + projectName: "Exciting Project", + recruitmentStatus: true, + postedTime: "2024-03-17T10:00:00Z", + teamName: "Innovators", + location: "서울", + projectDescription: + "흥미로운 프로젝트를 개발하여 혁신을 이끌어내는 팀입니다.", + category1: "데이터 사이언스", + category2: "클라우드 컴퓨팅", + like: true, + }, + { + id: 5, + projectName: "Future Project", + recruitmentStatus: false, + postedTime: "2024-03-18T14:30:00Z", + teamName: "Visionaries", + location: "경기", + projectDescription: "미래를 대비한 혁신적인 프로젝트를 수행하는 팀입니다.", + category1: "로봇공학", + category2: "인터넷 of Things (IoT)", + like: false, + }, + { + id: 6, + projectName: "Tech Project", + recruitmentStatus: true, + postedTime: "2024-03-19T09:45:00Z", + teamName: "Tech Wizards", + location: "부산", + projectDescription: + "기술적 도전에 재미를 느끼며 혁신적인 솔루션을 개발하는 팀입니다.", + category1: "소프트웨어 개발", + category2: "머신 러닝", + like: false, + }, +]; + +export default teamTestData; diff --git a/src/api/teamTestData2.js b/src/api/teamTestData2.js new file mode 100644 index 0000000..2d61697 --- /dev/null +++ b/src/api/teamTestData2.js @@ -0,0 +1,42 @@ +const teamTestData2 = [ + { + id: 1, + projectName: "Awesome Project", + recruitmentStatus: true, + postedTime: "2024-03-16T12:00:00Z", + teamName: "Dream Team", + location: "서울", + projectDescription: + "이 프로젝트는 놀라운 기술을 개발하는 것을 목표로 합니다.", + category1: "웹 개발", + category2: "인공지능", + like: false, + }, + { + id: 2, + projectName: "Cool Project", + recruitmentStatus: false, + postedTime: "2024-03-15T09:30:00Z", + teamName: "Tech Savvy", + location: "경기", + projectDescription: + "최신 기술을 활용하여 혁신적인 솔루션을 개발하는 프로젝트입니다.", + category1: "앱 개발", + category2: "데이터 분석", + like: true, + }, + { + id: 3, + projectName: "Innovative Project", + recruitmentStatus: true, + postedTime: "2024-03-14T15:45:00Z", + teamName: "Code Masters", + location: "부산", + projectDescription: "창의적인 소프트웨어 솔루션을 개발하는 프로젝트입니다.", + category1: "게임 개발", + category2: "블록체인", + like: true, + }, +]; + +export default teamTestData2; diff --git a/src/api/teamTestData3.js b/src/api/teamTestData3.js new file mode 100644 index 0000000..fcd08af --- /dev/null +++ b/src/api/teamTestData3.js @@ -0,0 +1,158 @@ +const teamTestData3 = [ + { + id: 1, + projectName: "Awesome Project", + recruitmentStatus: true, + postedTime: "2024-03-16T12:00:00Z", + teamName: "Dream Team", + location: "서울", + projectDescription: + "이 프로젝트는 놀라운 기술을 개발하는 것을 목표로 합니다.", + category1: "웹 개발", + category2: "인공지능", + like: false, + }, + { + id: 2, + projectName: "Cool Project", + recruitmentStatus: false, + postedTime: "2024-03-15T09:30:00Z", + teamName: "Tech Savvy", + location: "경기", + projectDescription: + "최신 기술을 활용하여 혁신적인 솔루션을 개발하는 프로젝트입니다.", + category1: "앱 개발", + category2: "데이터 분석", + like: true, + }, + { + id: 3, + projectName: "Innovative Project", + recruitmentStatus: true, + postedTime: "2024-03-14T15:45:00Z", + teamName: "Code Masters", + location: "부산", + projectDescription: "창의적인 소프트웨어 솔루션을 개발하는 프로젝트입니다.", + category1: "게임 개발", + category2: "블록체인", + like: true, + }, + // 더미 데이터 추가 + { + id: 4, + projectName: "Exciting Project", + recruitmentStatus: true, + postedTime: "2024-03-17T10:20:00Z", + teamName: "Innovators", + location: "서울", + projectDescription: "흥미로운 기술을 연구하고 개발하는 프로젝트입니다.", + category1: "로봇 공학", + category2: "사물 인터넷", + like: false, + }, + { + id: 5, + projectName: "Future Tech Project", + recruitmentStatus: false, + postedTime: "2024-03-18T14:00:00Z", + teamName: "Digital Pioneers", + location: "경기", + projectDescription: + "미래 기술에 대한 연구 및 개발을 목표로 하는 프로젝트입니다.", + category1: "가상 현실", + category2: "로봇 공학", + like: true, + }, + { + id: 6, + projectName: "Revolutionary Project", + recruitmentStatus: true, + postedTime: "2024-03-19T08:45:00Z", + teamName: "Tech Innovate", + location: "부산", + projectDescription: + "혁신적인 기술을 활용하여 사회적 문제를 해결하는 프로젝트입니다.", + category1: "인공지능", + category2: "사회 문제 해결", + like: true, + }, + { + id: 7, + projectName: "Next Gen Project", + recruitmentStatus: true, + postedTime: "2024-03-20T11:30:00Z", + teamName: "Visionaries", + location: "서울", + projectDescription: "다음 세대 기술을 개발하는 프로젝트입니다.", + category1: "바이오 테크놀로지", + category2: "DNA 염기서열 분석", + like: false, + }, + { + id: 8, + projectName: "Smart Solutions", + recruitmentStatus: false, + postedTime: "2024-03-21T13:20:00Z", + teamName: "Tech Wizards", + location: "경기", + projectDescription: + "스마트한 솔루션을 개발하여 일상적인 문제를 해결하는 프로젝트입니다.", + category1: "빅데이터", + category2: "사물 인터넷", + like: true, + }, + { + id: 9, + projectName: "Creative Project", + recruitmentStatus: true, + postedTime: "2024-03-22T09:15:00Z", + teamName: "Innovation Lab", + location: "부산", + projectDescription: + "창의적인 아이디어를 기반으로 기술을 개발하는 프로젝트입니다.", + category1: "가상 현실", + category2: "블록체인", + like: true, + }, + { + id: 10, + projectName: "Tech for Good Project", + recruitmentStatus: true, + postedTime: "2024-03-23T15:10:00Z", + teamName: "Future Thinkers", + location: "서울", + projectDescription: + "기술을 활용하여 사회에 긍정적인 영향을 미치는 프로젝트입니다.", + category1: "사회 문제 해결", + category2: "인공지능", + like: false, + }, + { + id: 11, + projectName: "Innovative Solutions", + recruitmentStatus: false, + postedTime: "2024-03-24T12:50:00Z", + teamName: "Tech Solutions", + location: "경기", + projectDescription: + "혁신적인 솔루션을 개발하여 산업에 기여하는 프로젝트입니다.", + category1: "데이터 분석", + category2: "사물 인터넷", + like: true, + }, + { + id: 12, + projectName: "Future Innovations", + recruitmentStatus: true, + postedTime: "2024-03-25T14:30:00Z", + teamName: "Innovation Hub", + location: "부산", + projectDescription: + "미래를 위한 혁신적인 기술을 연구 및 개발하는 프로젝트입니다.", + category1: "로봇 공학", + category2: "가상 현실", + like: true, + }, +]; + +export default teamTestData3; diff --git a/src/assets/icons/Vector.svg b/src/assets/icons/Vector.svg new file mode 100644 index 0000000..0edd84b --- /dev/null +++ b/src/assets/icons/Vector.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/Check.svg b/src/assets/myPage/Check.svg new file mode 100644 index 0000000..ed840f3 --- /dev/null +++ b/src/assets/myPage/Check.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/CheckCircleOff.svg b/src/assets/myPage/CheckCircleOff.svg new file mode 100644 index 0000000..5632d60 --- /dev/null +++ b/src/assets/myPage/CheckCircleOff.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/myPage/CheckCircleOn.svg b/src/assets/myPage/CheckCircleOn.svg new file mode 100644 index 0000000..195a748 --- /dev/null +++ b/src/assets/myPage/CheckCircleOn.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/myPage/Circle.svg b/src/assets/myPage/Circle.svg new file mode 100644 index 0000000..8cbe709 --- /dev/null +++ b/src/assets/myPage/Circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/Cross.svg b/src/assets/myPage/Cross.svg new file mode 100644 index 0000000..c8f4a82 --- /dev/null +++ b/src/assets/myPage/Cross.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/DeleteButton.svg b/src/assets/myPage/DeleteButton.svg new file mode 100644 index 0000000..6b4c05e --- /dev/null +++ b/src/assets/myPage/DeleteButton.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/Exit.svg b/src/assets/myPage/Exit.svg new file mode 100644 index 0000000..bd553c0 --- /dev/null +++ b/src/assets/myPage/Exit.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/HeartOff.svg b/src/assets/myPage/HeartOff.svg new file mode 100644 index 0000000..d428ada --- /dev/null +++ b/src/assets/myPage/HeartOff.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/MemberCenterLine.svg b/src/assets/myPage/MemberCenterLine.svg new file mode 100644 index 0000000..94358b3 --- /dev/null +++ b/src/assets/myPage/MemberCenterLine.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/ResumeCenterLine.svg b/src/assets/myPage/ResumeCenterLine.svg new file mode 100644 index 0000000..e1bac85 --- /dev/null +++ b/src/assets/myPage/ResumeCenterLine.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/ResumeProfile.svg b/src/assets/myPage/ResumeProfile.svg new file mode 100644 index 0000000..33c5bcc --- /dev/null +++ b/src/assets/myPage/ResumeProfile.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/SettingButton.svg b/src/assets/myPage/SettingButton.svg new file mode 100644 index 0000000..2fcad7c --- /dev/null +++ b/src/assets/myPage/SettingButton.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/SupportCenterLine.svg b/src/assets/myPage/SupportCenterLine.svg new file mode 100644 index 0000000..640ecc7 --- /dev/null +++ b/src/assets/myPage/SupportCenterLine.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/WithdrawalIcon.svg b/src/assets/myPage/WithdrawalIcon.svg new file mode 100644 index 0000000..0a5f2f0 --- /dev/null +++ b/src/assets/myPage/WithdrawalIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/myInfoVector1.svg b/src/assets/myPage/myInfoVector1.svg new file mode 100644 index 0000000..47fb6a3 --- /dev/null +++ b/src/assets/myPage/myInfoVector1.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/myInfoVector2.svg b/src/assets/myPage/myInfoVector2.svg new file mode 100644 index 0000000..1b0c5e4 --- /dev/null +++ b/src/assets/myPage/myInfoVector2.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/myPage/profile.svg b/src/assets/myPage/profile.svg new file mode 100644 index 0000000..4c1157e --- /dev/null +++ b/src/assets/myPage/profile.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Card/memberCard.js b/src/components/Card/memberCard.js new file mode 100644 index 0000000..2197a63 --- /dev/null +++ b/src/components/Card/memberCard.js @@ -0,0 +1,73 @@ +import { + ButtonBox, + Container, + Description, + InteractBox, + LikeButton, + LocationLabel, + Position, + StateLabel, + StyledButton, + TeamNameLabel, + TimeLabel, + Title, +} from "./styles"; + +const MemberCard = ({ data }) => { + return ( + +
+
+
+
+ +
+
+ {data.name} + {data.position} +
+
+
+ {data.gender} + {data.location} +
+
+
+ +
+ {data.introduction} +
+
+ + + {data.skill1} + {data.skill2} + +
+ +
+
+ + ); +}; + +export default MemberCard; diff --git a/src/components/Card/styles.js b/src/components/Card/styles.js new file mode 100644 index 0000000..9f95cc4 --- /dev/null +++ b/src/components/Card/styles.js @@ -0,0 +1,82 @@ +import styled from "styled-components"; + +export const Container = styled.div` + padding: 24px; + display: flex; + flex-direction: column; + border-radius: 24px; + border: 1px solid #c9c9c9; + max-width: 360px; +`; + +export const Title = styled.label` + font-size: 24px; + color: #6d758f; + font-weight: 700; +`; + +export const Position = styled.label` + font-size: 16px; + color: #6d758f; + font-weight: 500; + margin-top: 4px; +`; + +export const StateLabel = styled.label` + font-size: 14px; + color: #3376f6; + padding-right: 10px; +`; + +export const TimeLabel = styled.label` + border-left: 1px solid; + font-size: 14px; + padding-left: 10px; + color: #6d758f; +`; + +export const TeamNameLabel = styled.label` + font-size: 14px; + padding-right: 10px; + color: #6d758f; +`; + +export const LocationLabel = styled.label` + font-size: 14px; + color: #6d758f; +`; + +export const Description = styled.label` + font-size: 18px; + color: #6d758f; + text-align: start; +`; + +export const InteractBox = styled.div` + display: flex; + justify-content: space-between; + border-top: 1px solid #c9c9c9; + align-items: center; + margin-top: 20px; + padding-top: 20px; +`; + +export const ButtonBox = styled.div` + display: flex; + gap: 20px; +`; + +export const StyledButton = styled.button` + all: unset; + cursor: pointer; + background-color: #3376f6; + border-radius: 18px; + padding: 6px 14px; + color: white; + font-size: 14px; + font-weight: 500; +`; + +export const LikeButton = styled.img` + cursor: pointer; +`; diff --git a/src/components/Card/teamCard.js b/src/components/Card/teamCard.js new file mode 100644 index 0000000..86b7752 --- /dev/null +++ b/src/components/Card/teamCard.js @@ -0,0 +1,64 @@ +import { + ButtonBox, + Container, + Description, + InteractBox, + LikeButton, + LocationLabel, + StateLabel, + StyledButton, + TeamNameLabel, + TimeLabel, + Title, +} from "./styles"; + +const TeamCard = ({ data }) => { + return ( + +
+ {data.projectName} +
+ {data.recruitmentStatus ? ( + 모집 중 + ) : ( + 모집 마감 + )} + 1시간 전 +
+
+
+ {data.teamName} + {data.location} +
+
+ {data.projectDescription} +
+
+ + + {data.category1} + {data.category2} + +
+ +
+
+ + ); +}; + +export default TeamCard; diff --git a/src/components/CardGrid/contestCardGrid.js b/src/components/CardGrid/contestCardGrid.js new file mode 100644 index 0000000..d03cae0 --- /dev/null +++ b/src/components/CardGrid/contestCardGrid.js @@ -0,0 +1,23 @@ +import ContestCard from "../ContestCard/contestCard"; +import { GridContainer, Title } from "./styles"; + +const ContestCardGrid = (props) => { + return ( +
+ 마감 임박 공모전 + + {props.cardDatas.map((item) => ( + + ))} + +
+ ); +}; + +export default ContestCardGrid; diff --git a/src/components/CardGrid/memberCardGrid.js b/src/components/CardGrid/memberCardGrid.js new file mode 100644 index 0000000..6b51c05 --- /dev/null +++ b/src/components/CardGrid/memberCardGrid.js @@ -0,0 +1,19 @@ +import MemberCard from "../Card/memberCard"; +import { GridContainer, Title } from "./styles"; + +const MemberCardGrid = (props) => { + return ( +
+ AI 팀원 추천 + + {props.cardDatas.map((item) => ( + + ))} + +
+ ); +}; + +export default MemberCardGrid; diff --git a/src/components/CardGrid/styles.js b/src/components/CardGrid/styles.js new file mode 100644 index 0000000..7a33a07 --- /dev/null +++ b/src/components/CardGrid/styles.js @@ -0,0 +1,13 @@ +import styled from "styled-components"; + +export const GridContainer = styled.div` + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 52px 26px; +`; + +export const Title = styled.label` + font-size: 30px; + font-weight: 700; + margin-bottom: 40px; +`; diff --git a/src/components/CardGrid/teamCardGrid.js b/src/components/CardGrid/teamCardGrid.js new file mode 100644 index 0000000..63cf5ad --- /dev/null +++ b/src/components/CardGrid/teamCardGrid.js @@ -0,0 +1,19 @@ +import TeamCard from "../Card/teamCard"; +import { GridContainer, Title } from "./styles"; + +const TeamCardGrid = (props) => { + return ( +
+ AI 팀 추천 + + {props.cardDatas.map((item) => ( + + ))} + +
+ ); +}; + +export default TeamCardGrid; diff --git a/src/components/ContestCard/contestCard.js b/src/components/ContestCard/contestCard.js new file mode 100644 index 0000000..c0e9b33 --- /dev/null +++ b/src/components/ContestCard/contestCard.js @@ -0,0 +1,48 @@ +import { + CardContainer, + ContestDetails, + ContestHit, + ContestInfo, + ContestName, + DeadlineButton, + DeadlineText, + PosterImage, +} from "./styles"; + +const ContestCard = ({ data }) => { + return ( + + + D - {data.deadline} + +
+ +
+ +
+ {data.name} + {data.organizer} +
+
+ 조회{data.views} +
+
+
+ ); +}; + +export default ContestCard; diff --git a/src/components/ContestCard/styles.js b/src/components/ContestCard/styles.js new file mode 100644 index 0000000..db91cf4 --- /dev/null +++ b/src/components/ContestCard/styles.js @@ -0,0 +1,60 @@ +import styled from "styled-components"; + +export const CardContainer = styled.div` + position: relative; + display: flex; + flex-direction: column; + align-items: center; + width: 300px; + border: 1px solid #c9c9c9; + border-radius: 12px; +`; + +export const DeadlineButton = styled.button` + all: unset; + position: absolute; + left: 16px; + top: 16px; + background-color: #376fff; + border-radius: 8px; + padding: 6px 16px; +`; + +export const DeadlineText = styled.label` + font-size: 18px; + font-weight: 700; + color: white; +`; + +export const PosterImage = styled.img` + border-radius: 12px 12px 0px 0px; + width: 100%; +`; + +export const ContestDetails = styled.div` + width: 100%; + display: flex; + flex-direction: column; + justify-content: start; + align-items: start; +`; + +export const ContestName = styled.label` + font-size: 18px; + font-weight: 700; + color: #6d758f; + margin-bottom: 8px; +`; + +export const ContestInfo = styled.label` + font-size: 14px; + font-weight: 500; + color: #6d758f; +`; + +export const ContestHit = styled.label` + padding: 14px; + font-size: 12px; + font-weight: 500; + color: #6d758f; +`; diff --git a/src/components/Introduce/introduce.js b/src/components/Introduce/introduce.js index 1357a36..d2dce34 100644 --- a/src/components/Introduce/introduce.js +++ b/src/components/Introduce/introduce.js @@ -1,34 +1,30 @@ import { + Box, ButtonText, Container, Description, GetTeamButton, + InnerBox, Slogan, } from "./styles"; const Introduce = () => { return ( -
- 세상의 모든 팀플을 위한 연결의 시작! - - 이음이 제공하는 자유롭고 편안한 프로젝트 서비스, - - - 팀원, 팀플을 구하는 새로운 전환점과 AI서비스를 이용해보세요 - - - 첫 팀 구하기 - -
+ + + 세상의 모든 팀플을 위한 연결의 시작! + + 이음이 제공하는 자유롭고 편안한 프로젝트 서비스, + + + 팀원, 팀플을 구하는 새로운 전환점과 AI서비스를 이용해보세요 + + + 첫 팀 구하기 + + +
); }; diff --git a/src/components/Introduce/styles.js b/src/components/Introduce/styles.js index 78e26f5..219e658 100644 --- a/src/components/Introduce/styles.js +++ b/src/components/Introduce/styles.js @@ -2,22 +2,22 @@ import styled from "styled-components"; export const Container = styled.div` width: 100%; - background-color: #a6fcdc; height: 100%; display: flex; justify-content: center; + margin-bottom: 60px; `; export const Slogan = styled.label` - font-size: 64px; - font-weight: 600; + font-size: 40px; + font-weight: 700; margin-top: 80px; margin-bottom: 20px; `; export const Description = styled.label` - font-size: 32px; - font-weight: 400; + font-size: 24px; + font-weight: 500; margin-bottom: 6px; `; @@ -25,15 +25,33 @@ export const GetTeamButton = styled.button` all: unset; background-color: #376fff; padding: 11px 30px; - color: white; margin-top: 60px; - margin-bottom: 100px; + margin-bottom: 80px; border-radius: 12px; cursor: pointer; `; export const ButtonText = styled.label` - font-size: 24px; + color: #ffffff; + font-size: 20px; font-weight: 700; cursor: pointer; `; + +export const Box = styled.div` + background-color: #a6fcdc; + width: 100%; + height: 100%; + justify-content: center; + display: flex; +`; + +export const InnerBox = styled.div` + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: start; + max-width: 1000px; +`; diff --git a/src/components/MyFavorites/myFavorites.js b/src/components/MyFavorites/myFavorites.js new file mode 100644 index 0000000..cf59fae --- /dev/null +++ b/src/components/MyFavorites/myFavorites.js @@ -0,0 +1,60 @@ +import { SelectButton, NotSelectButton, CardContainter } from "./styles"; + +import MyFavoriteCard from "../MyPageCard/MyFavoriteCard/myFavoriteCard"; +import MyTeamTestData from "../../api/myTeamTestData"; +import { useState } from "react"; + +const MyFavorites = (props) => { + const [isToggle, setIsToggle] = useState(false); + + const TeamButton = () => { + setIsToggle(true); + }; + + const TeamMemberButton = () => { + setIsToggle(false); + }; + + return ( + <> + {isToggle ? ( + <> + + 팀 + + + 팀원 + + + ) : ( + <> + + 팀 + + + 팀원 + + + )} + + {MyTeamTestData.map((item) => ( + + ))} + + + ); +}; + +export default MyFavorites; diff --git a/src/components/MyFavorites/styles.js b/src/components/MyFavorites/styles.js new file mode 100644 index 0000000..12a8854 --- /dev/null +++ b/src/components/MyFavorites/styles.js @@ -0,0 +1,43 @@ +import styled from "styled-components"; + +export const SelectButton = styled.button` + position: absolute; + width: 66px; + height: 34px; + border: solid; + border-radius: 39px; + border-color: #376fff; + font-size: 18px; + font-weight: 500; + color: #ffffff; + background-color: #376fff; + user-select: none; + cursor: pointer; +`; + +export const NotSelectButton = styled.button` + position: absolute; + width: 66px; + height: 34px; + border: solid; + border-radius: 39px; + font-size: 18px; + font-weight: 500; + color: #376fff; + background-color: #ffffff; + user-select: none; + cursor: pointer; +`; + +export const CardContainter = styled.div` + position: absolute; + transform: translateX(-50%); + left: 50%; + top: 250px; + width: 767px; + height: 600px; + display: flex; + flex-wrap: wrap; + gap: 20px; + overflow-y: auto; +`; diff --git a/src/components/MyInfo/myInfo.js b/src/components/MyInfo/myInfo.js new file mode 100644 index 0000000..606c6ff --- /dev/null +++ b/src/components/MyInfo/myInfo.js @@ -0,0 +1,125 @@ +import { + ProfileChangeButton, + Tag, + Input, + SchoolMailButton, + AlarmContainter, + Alarm, + AlarmLabel, + CallLabel, + AlarmRow, + AlarmButton, + SaveButton, + CannelButton, + WithdrawalButton, +} from "./styles"; + +import { ReactComponent as Line } from "../../assets/myPage/myInfoVector2.svg"; +import { ReactComponent as Profile } from "../../assets/myPage/profile.svg"; +import { ReactComponent as CheckCircleOff } from "../../assets/myPage/CheckCircleOff.svg"; +import { ReactComponent as CheckCircleOn } from "../../assets/myPage/CheckCircleOn.svg"; +import { useState } from "react"; + +const MyInfo = ({ IsWithdrawal }) => { + const [isAlarm, setIsAlarm] = useState(false); + const [isMail, setIsMail] = useState(false); + const [isMessage, setIsMessage] = useState(false); + const [isApplication, setIsApplication] = useState(false); + + const profileChange = () => {}; + const SchoolMail = () => {}; + const AlarmSetting = () => { + setIsAlarm(!isAlarm); + }; + const AlarmMail = () => { + setIsMail(!isMail); + }; + const AlarmMessage = () => { + setIsMessage(!isMessage); + }; + const AlarmApplication = () => { + setIsApplication(!isApplication); + }; + + return ( +
+ + + 사진 변경 + + IsWithdrawal(true)}> + 회원 탈퇴 + + + 이름 + + 닉네임 + + 전화번호 + + 생년월일 + + 소속/학교 + + 학교 메일 인증 + + 거주 지역 + + + + + + MBTI + + + + + + + {isAlarm ? : } + 알림 설정 + + 합격/불합격 연락 받을 수단 + + + + MAIL + {isMail ? : } + + + MESSAGE + {isMessage ? : } + + + APPLICATION + {isApplication ? : } + + + + + + + 저장 + 취소 +
+ ); +}; + +export default MyInfo; diff --git a/src/components/MyInfo/styles.js b/src/components/MyInfo/styles.js new file mode 100644 index 0000000..ca02dd5 --- /dev/null +++ b/src/components/MyInfo/styles.js @@ -0,0 +1,148 @@ +import styled from "styled-components"; + +export const ProfileChangeButton = styled.button` + position: absolute; + top: 297px; + left: 106px; + width: 92px; + height: 32px; + border: 1px solid; + border-radius: 48px; + font-size: 16px; + font-weight: 400; + background-color: #ffffff; + cursor: pointer; +`; + +export const WithdrawalButton = styled.button` + position: absolute; + top: 341px; + left: 106px; + width: 92px; + height: 32px; + border: none; + border-radius: 48px; + font-size: 16px; + font-weight: 400; + color: #646464; + background-color: #dedede; + cursor: pointer; +`; + +export const Tag = styled.label` + position: absolute; + font-size: 18px; + font-weight: 600; +`; + +export const Input = styled.input` + position: absolute; + border: 1px solid; + border-radius: 9px; + font-size: 16px; + font-weight: 400; + text-align: center; + cursor: pointer; +`; + +export const SchoolMailButton = styled.button` + position: absolute; + left: 534px; + top: 421px; + width: 135px; + height: 35px; + border: none; + border-radius: 9px; + background-color: #376fff; + font-size: 18px; + font-weight: 500; + color: #ffffff; + text-align: center; + user-select: none; + cursor: pointer; +`; + +export const AlarmContainter = styled.div` + position: absolute; + flex-direction: column; + top: 608px; + left: 314px; + width: 500px; + height: 200px; +`; + +export const Alarm = styled.button` + display: flex; + position: absolute; + width: 150px; + height: 50px; + align-items: center; + border: none; + background-color: #ffffff; +`; + +export const AlarmLabel = styled.div` + margin-left: 30px; + font-size: 16px; + font-weight: 400; +`; + +export const CallLabel = styled.label` + position: absolute; + top: 80px; + left: 0px; + font-size: 18px; + font-weight: 800; +`; + +export const AlarmRow = styled.div` + position: absolute; + top: 120px; + display: flex; + justify-content: start; + align-items: center; +`; + +export const AlarmButton = styled.button` + height: 32px; + border: 1px solid; + border-radius: 9px; + font-size: 16px; + font-weight: 400; + background-color: white; + display: flex; + align-items: center; + justify-content: center; + margin-right: 20px; +`; + +export const SaveButton = styled.button` + position: absolute; + top: 804px; + right: 117px; + width: 64px; + height: 32px; + background-color: #376fff; + border: none; + border-radius: 9px; + font-size: 18px; + font-weight: 700; + color: #ffffff; + user-select: none; + cursor: pointer; +`; +export const CannelButton = styled.button` + position: absolute; + top: 804px; + right: 40px; + width: 64px; + height: 32px; + background-color: #dedede; + border: none; + border-radius: 9px; + font-size: 18px; + font-weight: 700; + color: #646464; + user-select: none; + cursor: pointer; +`; diff --git a/src/components/MyPageCard/MyFavoriteCard/myFavoriteCard.js b/src/components/MyPageCard/MyFavoriteCard/myFavoriteCard.js new file mode 100644 index 0000000..fb292b7 --- /dev/null +++ b/src/components/MyPageCard/MyFavoriteCard/myFavoriteCard.js @@ -0,0 +1,45 @@ +import { + Container, + ProjectName, + TeamName, + Region, + Recruitment, + RecruitmentTime, + Introduction, +} from "./styles"; +import { ReactComponent as CenterLine } from "../../../assets/myPage/MemberCenterLine.svg"; +import { ReactComponent as HeartOff } from "../../../assets/myPage/HeartOff.svg"; + +const MyFavoriteCard = ({ data }) => { + return ( + + {data.projectName} + [팀명]:{data.teamName} + [지역]:{data.region} + + {data.recruitment ? "모집중" : "모집완료"} + | {data.recruitmentTime} + + {data.introduction} + + + + + + ); +}; + +export default MyFavoriteCard; diff --git a/src/components/MyPageCard/MyFavoriteCard/styles.js b/src/components/MyPageCard/MyFavoriteCard/styles.js new file mode 100644 index 0000000..b02ff92 --- /dev/null +++ b/src/components/MyPageCard/MyFavoriteCard/styles.js @@ -0,0 +1,64 @@ +import styled from "styled-components"; + +export const Container = styled.div` + position: relative; + width: 360px; + height: 246px; + border: 2px solid; + border-radius: 11px; + border-color: #c9c9c9; +`; + +export const ProjectName = styled.label` + position: absolute; + left: 25px; + top: 20px; + font-size: 17px; + font-weight: 700; + color: #6d758f; +`; + +export const TeamName = styled.label` + position: absolute; + left: 25px; + top: 56px; + font-size: 11px; + font-weight: 600; + color: #6d758f; +`; + +export const Region = styled.label` + position: absolute; + left: 25px; + top: 71px; + font-size: 11px; + font-weight: 600; + color: #6d758f; +`; + +export const Recruitment = styled.label` + position: absolute; + right: 76px; + top: 24px; + font-size: 11px; + font-weight: 400; +`; + +export const RecruitmentTime = styled.label` + position: absolute; + width: 45px; + font-size: 11px; + font-weight: 400; + color: #6d758f; +`; + +export const Introduction = styled.label` + position: absolute; + left: 25px; + top: 108px; + width: 300px; + font-size: 15px; + font-weight: 400; + color: #6d758f; + text-align: left; +`; diff --git a/src/components/MyPageCard/MyResumeCard/myResumeCard.js b/src/components/MyPageCard/MyResumeCard/myResumeCard.js new file mode 100644 index 0000000..5a0e7d4 --- /dev/null +++ b/src/components/MyPageCard/MyResumeCard/myResumeCard.js @@ -0,0 +1,49 @@ +import { + Containter, + Name, + GenderAge, + Belong, + Region, + Occupation, + Introduction, +} from "./styles"; +import { ReactComponent as Profile } from "../../../assets/myPage/ResumeProfile.svg"; +import { ReactComponent as CenterLine } from "../../../assets/myPage/ResumeCenterLine.svg"; +import { ReactComponent as SettingButton } from "../../../assets/myPage/SettingButton.svg"; +import { ReactComponent as DeleteButton } from "../../../assets/myPage/DeleteButton.svg"; + +const MyResumeCard = ({ data }) => { + return ( + + + + {data.name} + + {data.gender}/{data.age} + + 소속:{data.belong} + 지역:{data.region} + + 개발자 + {data.introduction} + + + + + ); +}; + +export default MyResumeCard; diff --git a/src/components/MyPageCard/MyResumeCard/styles.js b/src/components/MyPageCard/MyResumeCard/styles.js new file mode 100644 index 0000000..e1e44f4 --- /dev/null +++ b/src/components/MyPageCard/MyResumeCard/styles.js @@ -0,0 +1,74 @@ +import styled from "styled-components"; + +export const Containter = styled.div` + position: relative; + width: 360px; + height: 255px; + border: 2px solid; + border-radius: 11px; + border-color: #c9c9c9; +`; + +export const Name = styled.label` + position: absolute; + left: 113px; + top: 25px; + font-size: 17px; + font-weight: 700; + color: #6d758f; +`; + +export const GenderAge = styled.label` + position: absolute; + left: 167px; + top: 28px; + font-size: 11px; + font-weight: 400; + color: #6d758f; +`; + +export const Belong = styled.label` + position: absolute; + left: 113px; + top: 56px; + font-size: 11px; + font-weight: 600; + color: #6d758f; +`; + +export const Region = styled.label` + position: absolute; + left: 113px; + top: 71px; + font-size: 11px; + font-weight: 600; + color: #6d758f; +`; + +export const Occupation = styled.label` + position: absolute; + left: 25px; + top: 122px; + width: 54px; + height: 24px; + border: none; + border-radius: 17px; + font-size: 12px; + font-weight: 700; + color: #ffffff; + background-color: #3376f6; + display: flex; + justify-content: center; + align-items: center; +`; + +export const Introduction = styled.label` + position: absolute; + left: 27px; + top: 158px; + width: 250px; + font-size: 15px; + font-weight: 400; + color: #6d758f; + text-align: left; +`; diff --git a/src/components/MyPageCard/MySupportCard/mySupportCard.js b/src/components/MyPageCard/MySupportCard/mySupportCard.js new file mode 100644 index 0000000..8cf008a --- /dev/null +++ b/src/components/MyPageCard/MySupportCard/mySupportCard.js @@ -0,0 +1,40 @@ +import { + Containter, + ProjectName, + TeamAndRegion, + DateLabel, + TimeLabel, + Introduction, + Pass, + Fail, +} from "./styles"; + +import { ReactComponent as CenterLine } from "../../../assets/myPage/SupportCenterLine.svg"; + +const MySupportCard = ({ data }) => { + console.log(data.projectName); + return ( + + {data.projectName} + + {data.teamName} / {data.region} + + {data.date} + | {data.time} + + + + {data.introduction} + {data.pass ? 합격 : 불합격} + + ); +}; + +export default MySupportCard; diff --git a/src/components/MyPageCard/MySupportCard/styles.js b/src/components/MyPageCard/MySupportCard/styles.js new file mode 100644 index 0000000..ee5b984 --- /dev/null +++ b/src/components/MyPageCard/MySupportCard/styles.js @@ -0,0 +1,91 @@ +import styled from "styled-components"; + +export const Containter = styled.div` + position: relative; + width: 780px; + height: 106px; + border: 1.9px solid; + border-radius: 11px; + border-color: #c9c9c9; +`; + +export const ProjectName = styled.label` + position: absolute; + left: 21px; + top: 12px; + font-size: 17px; + font-weight: 700; + color: #6d758f; +`; + +export const TeamAndRegion = styled.label` + position: absolute; + left: 126px; + top: 17px; + font-size: 11px; + font-weight: 600; + color: #c9c9c9; +`; + +export const DateLabel = styled.label` + position: absolute; + right: 56px; + top: 17px; + font-size: 12px; + font-weight: 500; + color: #7c7c7c; +`; + +export const TimeLabel = styled.label` + position: absolute; + right: 16px; + top: 17px; + font-size: 12px; + font-weight: 400; + font-color: #7c7c7c; +`; + +export const Introduction = styled.label` + position: absolute; + left: 21px; + top: 53px; + font-size: 15px; + font-weight: 400; + font-color: #6d758f; +`; + +export const Pass = styled.div` + position: absolute; + right: 18px; + top: 54px; + width: 64px; + height: 34px; + border: 2px solid; + border-radius: 8px; + border-color: #376fff; + font-size: 18px; + font-weight: 500; + color: #376fff; + display: flex; + justify-content: center; + align-items: center; + text-align: center; +`; + +export const Fail = styled.div` + position: absolute; + right: 18px; + top: 54px; + width: 64px; + height: 34px; + border: 2px solid; + border-radius: 8px; + border-color: #ff3737; + font-size: 18px; + font-weight: 500; + color: #ff3737; + display: flex; + justify-content: center; + align-items: center; + text-align: center; +`; diff --git a/src/components/MyPageCard/MyTeamCard/myTeamCard.js b/src/components/MyPageCard/MyTeamCard/myTeamCard.js new file mode 100644 index 0000000..267fdc9 --- /dev/null +++ b/src/components/MyPageCard/MyTeamCard/myTeamCard.js @@ -0,0 +1,41 @@ +import { + Containter, + ProejctName, + TeamName, + Region, + Recruitment, + RecruitmentTime, + Introduction, + TeamMemberButtton, + EditButton, +} from "./styles"; +import { ReactComponent as MemberCenterLine } from "../../../assets/myPage/MemberCenterLine.svg"; + +const MyTeamCard = ({ data }) => { + return ( + + {data.projectName} + [{data.teamName}] + [{data.region}] + + + {data.recuritment ? "모집중" : "모집완료"} + | {data.recruitmentTime} + + + {data.introduction} + + 팀원 관리 + 소개 페이지 수정 + + ); +}; + +export default MyTeamCard; diff --git a/src/components/MyPageCard/MyTeamCard/styles.js b/src/components/MyPageCard/MyTeamCard/styles.js new file mode 100644 index 0000000..0e66fb4 --- /dev/null +++ b/src/components/MyPageCard/MyTeamCard/styles.js @@ -0,0 +1,94 @@ +import styled from "styled-components"; + +export const Containter = styled.div` + position: relative; + width: 360px; + height: 246px; + border: 1.9px solid; + border-radius: 11px; + border-color: #c9c9c9; +`; + +export const ProejctName = styled.label` + position: absolute; + left: 24px; + top: 19px; + font-size: 17px; + font-weight: 700; + color: #6d758f; +`; + +export const TeamName = styled.label` + position: absolute; + left: 24px; + top: 57px; + font-size: 11px; + font-weight: 600; + color: #6d758f; +`; + +export const Region = styled.label` + position: absolute; + left: 24px; + top: 71px; + font-size: 11px; + font-weight: 600; + color: #6d758f; +`; + +export const Recruitment = styled.label` + position: absolute; + right: 76px; + top: 24px; + font-size: 11px; + font-weight: 400; +`; + +export const RecruitmentTime = styled.label` + position: absolute; + width: 45px; + font-size: 11px; + font-weight: 400; + color: #6d758f; +`; + +export const Introduction = styled.label` + position: absolute; + left: 26px; + top: 108px; + font-size: 15px; + font-weight: 400; + color: #6d758f; +`; + +export const TeamMemberButtton = styled.button` + position: absolute; + left: 14px; + top: 201px; + width: 159px; + height: 32px; + border: 2px solid; + border-radius: 4px; + border-color: #376fff; + font-size: 14px; + font-weight: 400; + color: #376fff; + background-color: #ffffff; + cursor: pointer; +`; + +export const EditButton = styled.button` + position: absolute; + right: 14px; + top: 201px; + width: 159px; + height: 32px; + border: 2px solid; + border-radius: 4px; + border-color: #376fff; + font-size: 14px; + font-weight: 400; + color: #376fff; + background-color: #ffffff; + cursor: pointer; +`; diff --git a/src/components/MyPageSideBar/myPageSideBar.js b/src/components/MyPageSideBar/myPageSideBar.js new file mode 100644 index 0000000..c389c90 --- /dev/null +++ b/src/components/MyPageSideBar/myPageSideBar.js @@ -0,0 +1,65 @@ +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { ReactComponent as CheckCircleOn } from "../../assets/myPage/Circle.svg"; +import { Container, SelectPage, NotSelectPage } from "./styles"; + +const MyPageSideBar = ({ setIsCreateTeam }) => { + const navigate = useNavigate(); + const [curPage, setCurPage] = useState(0); + + var arr = ["내정보", "즐겨찾기", "지원현황", "팀관리", "이력서"]; + + const sideButtonClick = (index) => { + setIsCreateTeam(false); + switch (index) { + case 0: + navigate("/mypage"); + break; + case 1: + navigate("/mypage/favorites"); + break; + case 2: + navigate("/mypage/support"); + break; + case 3: + navigate("/mypage/team"); + break; + case 4: + navigate("/mypage/resume"); + break; + default: + break; + } + + setCurPage(index); + }; + + return ( +
+ + {arr.map((item, index) => { + const ItemComponent = curPage === index ? SelectPage : NotSelectPage; + + return ( + sideButtonClick(index)} + style={{ + display: "flex", + alignItems: "center", + justifyContent: "center", + }} + > + {curPage === index && ( + + )} + {item} + + ); + })} + +
+ ); +}; + +export default MyPageSideBar; diff --git a/src/components/MyPageSideBar/styles.js b/src/components/MyPageSideBar/styles.js new file mode 100644 index 0000000..9a6f444 --- /dev/null +++ b/src/components/MyPageSideBar/styles.js @@ -0,0 +1,36 @@ +import styled from "styled-components"; + +export const Container = styled.div` + position: absolute; + transform: translateX(-100%); + top: 0px; + left: -30px; + width: 212px; + height: 495px; + border: 2px solid; + border-color: #c9c9c9; + border-radius: 12px; + padding-top: 30px; + display: flex; + flex-direction: column; +`; + +export const SelectPage = styled.button` + font-size: 20px; + font-weight: 800; + margin-bottom: 80px; + border: none; + background-color: #ffffff; + cursor: pointer; +`; + +export const NotSelectPage = styled.button` + font-size: 20px; + font-weight: 400; + margin-bottom: 80px; + + border: none; + background-color: #ffffff; + color: #a9a9a9; + cursor: pointer; +`; diff --git a/src/components/MyResume/myResume.js b/src/components/MyResume/myResume.js new file mode 100644 index 0000000..f4a2356 --- /dev/null +++ b/src/components/MyResume/myResume.js @@ -0,0 +1,22 @@ +import { ResumeButton, CardContainter } from "./styles"; +import { ReactComponent as Cross } from "../../assets/myPage/Cross.svg"; +import MyResumeCard from "../MyPageCard/MyResumeCard/myResumeCard"; +import MyResumeTestData from "../../api/myResumeTestData"; + +const MyResume = (props) => { + return ( +
+ + + 이력서 생성 + + + {MyResumeTestData.map((item) => ( + + ))} + +
+ ); +}; + +export default MyResume; diff --git a/src/components/MyResume/styles.js b/src/components/MyResume/styles.js new file mode 100644 index 0000000..afc2d79 --- /dev/null +++ b/src/components/MyResume/styles.js @@ -0,0 +1,33 @@ +import styled from "styled-components"; + +export const ResumeButton = styled.button` + position: absolute; + left: 50%; + top: 113px; + transform: translateX(-50%); + width: 750px; + height: 40px; + border: none; + border-radius: 8px; + background-color: #376fff; + font-size: 18px; + font-weight: 700; + color: #ffffff; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +`; + +export const CardContainter = styled.div` + position: relative; + left: 50%; + top: 179px; + transform: translateX(-50%); + width: 767px; + height: 650px; + display: flex; + flex-wrap: wrap; + gap: 20px; + overflow-y: auto; +`; diff --git a/src/components/MySupport/mySupport.js b/src/components/MySupport/mySupport.js new file mode 100644 index 0000000..3c6a13e --- /dev/null +++ b/src/components/MySupport/mySupport.js @@ -0,0 +1,29 @@ +import { useState } from "react"; +import { Completed, CompletedLabel, CardContainter } from "./styles"; +import { ReactComponent as CheckCircleOff } from "../../assets/myPage/CheckCircleOff.svg"; +import { ReactComponent as CheckCircleOn } from "../../assets/myPage/CheckCircleOn.svg"; +import MySupportCard from "../MyPageCard/MySupportCard/mySupportCard"; +import supportTestData from "../../api/supportTestData"; + +const MySupport = (props) => { + const [isCompleted, setIsCompleted] = useState(false); + + const CompletedSetting = () => { + setIsCompleted(!isCompleted); + }; + return ( +
+ + {isCompleted ? : } + 모집 완료 제외하기 + + + {supportTestData.map((item) => ( + + ))} + +
+ ); +}; + +export default MySupport; diff --git a/src/components/MySupport/styles.js b/src/components/MySupport/styles.js new file mode 100644 index 0000000..f902db8 --- /dev/null +++ b/src/components/MySupport/styles.js @@ -0,0 +1,32 @@ +import styled from "styled-components"; + +export const Completed = styled.button` + position: absolute; + right: 55px; + top: 103px; + border: none; + background-color: #ffffff; + display: flex; + align-items: center; + cursor: pointer; +`; + +export const CompletedLabel = styled.label` + margin-left: 10px; + font-size: 16px; + font-weight: 600; + cursor: pointer; +`; + +export const CardContainter = styled.div` + position: absolute; + top: 170px; + left: 50%; + width: 800px; + transform: translateX(-50%); + height: 670px; + display: grid; + flex-direction: column; + gap: 20px; + overflow-y: auto; +`; diff --git a/src/components/MyTeam/myTeam.js b/src/components/MyTeam/myTeam.js new file mode 100644 index 0000000..1d55cdc --- /dev/null +++ b/src/components/MyTeam/myTeam.js @@ -0,0 +1,39 @@ +import { useState } from "react"; +import { + MyTeamButton, + MyTeamLabel, + CardContainter, + CreateTeamButton, +} from "./styles"; +import { ReactComponent as CheckCircleOff } from "../../assets/myPage/CheckCircleOff.svg"; +import { ReactComponent as CheckCircleOn } from "../../assets/myPage/CheckCircleOn.svg"; +import { ReactComponent as Cross } from "../../assets/myPage/Cross.svg"; +import MyTeamCard from "../MyPageCard/MyTeamCard/myTeamCard"; +import MyTeamTestData from "../../api/myTeamTestData"; + +const MyTeam = ({ setIsCreateTeam }) => { + const [isMyTeam, setIsMyTeam] = useState(false); + + const MyTeamBtn = () => { + setIsMyTeam(!isMyTeam); + }; + + return ( +
+ + {isMyTeam ? : } + 나의 팀만 보기 + + setIsCreateTeam(true)}> + 팀 생성 + + + {MyTeamTestData.map((item) => ( + + ))} + +
+ ); +}; + +export default MyTeam; diff --git a/src/components/MyTeam/styles.js b/src/components/MyTeam/styles.js new file mode 100644 index 0000000..b9f7085 --- /dev/null +++ b/src/components/MyTeam/styles.js @@ -0,0 +1,51 @@ +import styled from "styled-components"; + +export const MyTeamButton = styled.button` + position: absolute; + top: 101px; + right: 55px; + border: none; + background-color: #ffffff; + display: flex; + align-items: center; + cursor: pointer; +`; + +export const MyTeamLabel = styled.label` + margin-left: 10px; + font-size: 16px; + font-weight: 600; + cursor: pointer; +`; + +export const CreateTeamButton = styled.button` + position: absolute; + left: 50%; + top: 185px; + transform: translateX(-50%); + width: 749px; + height: 39px; + border: none; + border-radius: 8px; + background-color: #376fff; + font-size: 18px; + font-weight: 700; + color: #ffffff; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +`; + +export const CardContainter = styled.div` + position: absolute; + top: 255px; + left: 50%; + transform: translateX(-50%); + width: 767px; + height: 600px; + display: flex; + flex-wrap: wrap; + gap: 20px; + overflow-y: auto; +`; diff --git a/src/components/MyTeamCreate/myTeamCreate.js b/src/components/MyTeamCreate/myTeamCreate.js new file mode 100644 index 0000000..efacca4 --- /dev/null +++ b/src/components/MyTeamCreate/myTeamCreate.js @@ -0,0 +1,34 @@ +import { Explanation, Input, SaveButton, Tag, Title } from "./styled"; + +const MyTeamCreate = () => { + return ( +
+ 신규 팀 등록 + + 팀명 + + + 분야 + + + 활동 국가 + + + 활동 지역 + + + 프로젝트 단계 + + + 현재 인원 + + + 팀 상세 설명 + + + 저장 +
+ ); +}; + +export default MyTeamCreate; diff --git a/src/components/MyTeamCreate/styled.js b/src/components/MyTeamCreate/styled.js new file mode 100644 index 0000000..694639b --- /dev/null +++ b/src/components/MyTeamCreate/styled.js @@ -0,0 +1,48 @@ +import styled from "styled-components"; + +export const Title = styled.label` + position: absolute; + left: 50px; + top: 107px; + font-size: 24px; + font-weight: 700; +`; + +export const Tag = styled.label` + position: absolute; + font-size: 18px; + font-weight: 600; +`; + +export const Input = styled.input` + position: absolute; + width: 350px; + height: 36px; + border: 1.9px solid; + border-radius: 6px; + border-color: #c9c9c9; +`; + +export const Explanation = styled.textarea` + position: absolute; + width: 749px; + height: 269px; + border: 1.9px solid; + border-radius: 6px; + border-color: #c9c9c9; +`; + +export const SaveButton = styled.button` + position: absolute; + right: 94px; + top: 882px; + width: 64px; + height: 32px; + font-size: 18px; + font-weight: 700; + color: #ffffff; + background-color: #376fff; + border: none; + border-radius: 8px; + cursor: pointer; +`; diff --git a/src/components/Navigation/navigation.js b/src/components/Navigation/navigation.js index a5d5ec5..5400aa1 100644 --- a/src/components/Navigation/navigation.js +++ b/src/components/Navigation/navigation.js @@ -9,45 +9,84 @@ import { Title, } from "./styles"; import { ReactComponent as Alert } from "../../assets/icons/alert.svg"; +import { useNavigate } from "react-router-dom"; +import SocialLoginModal from "../SocialLoginModal/SocialLoginModal"; +import { useRecoilState } from "recoil"; +import { userInfoState } from "../../states/authState"; const Navigation = (props) => { - const [clickLanguageDropdown, setClickLanguageDropdown] = useState(false); + const navigate = useNavigate(); + const [clickLoginButton, setClickLoginButton] = useState(false); + const [userInfo, setUserInfo] = useRecoilState(userInfoState); + return ( + {clickLoginButton ? ( + + ) : null}
- 이음 - - 팀구하기 - 팀원구하기 + { + navigate("/"); + }} + > + 이음 + + + { + navigate("/team"); + }} + > + 팀구하기 + + { + navigate("/member"); + }} + > + 팀원구하기 + 대외활동 + { + navigate("/mypage"); + }} + > + 마이페이지(임시) + + + 앱 다운로드 +
- 회원가입/로그인 - -
-
    { - setClickLanguageDropdown(!clickLanguageDropdown); + if (userInfo.isLogin) { + setUserInfo({}); + localStorage.removeItem("access_token"); + // TODO 로그아웃 API 요청 보내기 + } else { + setClickLoginButton(true); + } }} > - {"KR"} - {clickLanguageDropdown ? "⌃" : "⌄"} - {clickLanguageDropdown && ( - <> -
  • KR
  • -
  • EN
  • - - )} -
-
+ {userInfo.isLogin ? "로그아웃" : "로그인"} + +
diff --git a/src/components/Navigation/styles.js b/src/components/Navigation/styles.js index 73264f0..df9a8ce 100644 --- a/src/components/Navigation/styles.js +++ b/src/components/Navigation/styles.js @@ -2,30 +2,31 @@ import styled from "styled-components"; export const Container = styled.div` background-color: #7cfbcb; - padding: 8px; `; export const Box = styled.div` display: flex; align-items: center; justify-content: space-between; + height: 76px; `; export const Title = styled.label` + color: #000000; font-size: 36px; font-weight: 900; - margin-left: 50px; + margin-left: 160px; cursor: pointer; `; export const MenuBox = styled.div` - margin-left: 100px; + display: flex; + gap: 120px; `; export const MenuItem = styled.label` font-size: 18px; font-weight: 700; - margin-left: 50px; cursor: pointer; `; @@ -33,13 +34,14 @@ export const LoginButton = styled.button` font-size: 24px; all: unset; background-color: white; - padding: 10px 22px; + padding: 10px 18px; border-radius: 12px; cursor: pointer; `; export const LoginButtonLabel = styled.label` - font-size: 14px; + color: #000000; + font-size: 16px; font-weight: 700; cursor: pointer; `; diff --git a/src/components/PagenationComponent/pagenationComponent.js b/src/components/PagenationComponent/pagenationComponent.js new file mode 100644 index 0000000..18bc3cc --- /dev/null +++ b/src/components/PagenationComponent/pagenationComponent.js @@ -0,0 +1,53 @@ +import React from "react"; +import styled from "styled-components"; + +// Styled-components for the pagination +const PaginationWrapper = styled.div` + display: flex; + list-style: none; +`; + +const PageItem = styled.div` + border: 1px solid #ddd; + border-radius: 10px; + padding: 8px 12px; + margin: 4px; + cursor: pointer; + background-color: ${(props) => (props.isActive ? "#2F80ED" : "white")}; + color: ${(props) => (props.isActive ? "white" : "black")}; + + &:hover { + background-color: ${(props) => (props.isActive ? "#2F80ED" : "#f0f0f0")}; + } +`; + +// React component for the pagination +const PaginationComponent = ({ pages, currentPage, onPageChange }) => { + // Create the page numbers based on the 'pages' prop + const pageNumbers = []; + for (let number = 1; number <= pages; number++) { + pageNumbers.push( + onPageChange(number)} + > + {number} + , + ); + } + + return ( + + {currentPage > 1 && ( + onPageChange(currentPage - 1)}>{"<"} + )} + {pageNumbers} + {currentPage < pages && ( + onPageChange(currentPage + 1)}>{">"} + )} + + ); +}; + +export default PaginationComponent; diff --git a/src/components/SideNavigation/jobPosition.js b/src/components/SideNavigation/jobPosition.js new file mode 100644 index 0000000..07e09da --- /dev/null +++ b/src/components/SideNavigation/jobPosition.js @@ -0,0 +1,70 @@ +export const jobCategories = [ + { + kind: "design", + mainCategory: "디자인", + subCategories: [ + "UI/UX 디자이너", + "일러스트/캐릭터 디자이너", + "영상/모션 그래픽 디자이너", + "제품/패키지 디자이너", + "인테리어 디자이너", + "패션 디자이너", + "공예", + "그래픽 디자이너", + ], + }, + { + kind: "development", + mainCategory: "개발", + subCategories: [ + "프론트엔드", + "백엔드", + "AI 데이터 엔지니어", + "데브옵스 개발자", + "보안 전문가", + "게임 개발자", + "임베디드 개발", + "DBA", + ], + }, + { + kind: "planning", + mainCategory: "기획", + subCategories: ["기획"], + }, + { + kind: "media", + mainCategory: "미디어", + subCategories: [ + "영상 편집", + "영상 촬영", + "PD", + "사진 작가", + "음향 엔지니어", + ], + }, + { + kind: "marketing", + mainCategory: "마케팅", + subCategories: ["관리", "홍보", "컨설팅"], + }, + { + kind: "translation", + mainCategory: "통번역", + subCategories: [ + "영어", + "일본어", + "중국어", + "스페인어", + "아랍어", + "힌디어", + "프랑스어", + "기타", + ], + }, + { + kind: "other", + mainCategory: "기타", + subCategories: ["기타"], + }, +]; diff --git a/src/components/SideNavigation/sideNavigation.js b/src/components/SideNavigation/sideNavigation.js new file mode 100644 index 0000000..679e4fa --- /dev/null +++ b/src/components/SideNavigation/sideNavigation.js @@ -0,0 +1,91 @@ +import React, { useState } from "react"; +import { + Checkbox, + Item, + ItemList, + NavHeader, + Navigation, + ResetButton, + Section, + SectionTitle, + SectionTitleRow, + Title, +} from "./styles"; +import { jobCategories } from "./jobPosition"; + +const SideNavigation = () => { + const [sectionEnabled, setSectionEnabled] = useState({ + design: false, + development: false, + planning: false, + media: false, + marketing: false, + translation: false, + other: false, + }); + const [subCategoryEnabled, setSubCategoryEnabled] = useState({}); + + const handleSectionCheckbox = (section) => { + setSectionEnabled((prev) => ({ ...prev, [section]: !prev[section] })); + }; + + return ( + + + 필터 + + setSectionEnabled({ + design: false, + development: false, + planning: false, + media: false, + marketing: false, + translation: false, + other: false, + }) + } + > + 초기화 + + + + {/* 모집기간 섹션 */} + + 모집 기간 + + 직종 분류 + {jobCategories.map((category) => ( +
+ + handleSectionCheckbox(category.kind)} + /> + {category.mainCategory} + + + {category.subCategories.map((subCategory, index) => ( + + handleSubCategoryCheckbox(subCategoryName)} + /> + {subCategory} + + ))} + +
+ ))} +
+ ); +}; + +export default SideNavigation; diff --git a/src/components/SideNavigation/styles.js b/src/components/SideNavigation/styles.js new file mode 100644 index 0000000..9c00284 --- /dev/null +++ b/src/components/SideNavigation/styles.js @@ -0,0 +1,73 @@ +import styled from "styled-components"; + +export const Navigation = styled.nav` + background-color: #ffffff; + border-radius: 12px; + border: #c9c9c9 solid 2px; + padding: 20px; + width: 300px; +`; + +export const NavHeader = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +`; + +export const Title = styled.h3` + border-top: 1px solid #eee; + padding-top: 20px; + font-size: 1.25rem; + color: #333; + &:first-of-type { + border-top: none; + padding-top: 0; + } +`; + +export const ResetButton = styled.button` + background: none; + border: none; + cursor: pointer; + color: #007bff; + font-size: 1rem; +`; + +export const Section = styled.section` + padding-top: 20px; +`; + +export const SectionTitleRow = styled.div` + display: flex; + align-items: center; + margin-bottom: 10px; +`; + +export const SectionTitle = styled.h4` + color: #333; + font-size: 18px; + margin: 0; +`; + +export const Checkbox = styled.input.attrs({ type: "checkbox" })` + margin-right: 10px; + width: 16px; + height: 16px; + cursor: pointer; +`; + +export const ItemList = styled.ul` + list-style: none; + padding-left: 0; +`; + +export const Item = styled.li` + font-size: 18px; + color: #333; + display: flex; + align-items: center; + margin-bottom: 8px; + margin-left: 20px; + cursor: pointer; +`; diff --git a/src/components/SocialLoginModal/SocialLoginModal.js b/src/components/SocialLoginModal/SocialLoginModal.js new file mode 100644 index 0000000..6c76ed1 --- /dev/null +++ b/src/components/SocialLoginModal/SocialLoginModal.js @@ -0,0 +1,52 @@ +import { ReactComponent as Vector } from "../../assets/icons/Vector.svg"; + +import { + ContainerOut, + Container, + Explanation, + Title, + NaverButton, + GoogleButton, + KakaoButton, + ExitButton, +} from "./styles"; + +const SocialLoginModal = ({ setClickLoginButton }) => { + const loginWithKakao = () => { + window.location.href = "/oauth2/authorization/kakao"; + }; + + const loginWithGoogle = () => { + // window.location.href = "http://e-um.site/api/oauth2/google"; + window.location.href = "http://localhost:8080/api/oauth2/google"; + }; + + const loginWithNaver = () => { + window.location.href = "/oauth2/authorization/naver"; + }; + + return ( +
+ + + 이음 + 간편하게 시작하는 회원가입 + + 카카오톡으로 진행하기 + + 구글로 진행하기 + 네이버로 진행하기 + { + setClickLoginButton(false); + }} + > + + + + +
+ ); +}; + +export default SocialLoginModal; diff --git a/src/components/SocialLoginModal/styles.js b/src/components/SocialLoginModal/styles.js new file mode 100644 index 0000000..a527f5e --- /dev/null +++ b/src/components/SocialLoginModal/styles.js @@ -0,0 +1,88 @@ +import styled from "styled-components"; + +export const ContainerOut = styled.div` + display: flex; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.6); + align-items: center; + justify-content: center; +`; + +export const Container = styled.div` + position: absolute; + width: 688px; + height: 590px; + border-radius: 56px; + background-color: #ffffff; +`; + +export const Title = styled.label` + display: block; + font-size: 65px; + font-weight: 800; + margin-top: 76.01px; +`; + +export const Explanation = styled.label` + display: block; + font-size: 20px; + font-weight: 400; +`; + +export const KakaoButton = styled.button` + position: absolute; + font-size: 24px; + font-weight: 600; + top: 246.87px; + left: 102.42px; + width: 480px; + height: 82px; + border-radius: 12px; + background-color: #fee500; + color: black; + border: none; + cursor: pointer; +`; +export const GoogleButton = styled.button` + position: absolute; + font-size: 24px; + font-weight: 600; + top: 347.08px; + left: 102.42px; + width: 480px; + height: 82px; + border-radius: 12px; + background-color: #1c48ff; + color: white; + border: none; + cursor: pointer; +`; +export const NaverButton = styled.button` + position: absolute; + font-size: 24px; + font-weight: 600; + top: 447.28px; + left: 102.42px; + width: 480px; + height: 82px; + border-radius: 12px; + background-color: #5ab335; + color: white; + border: none; + cursor: pointer; +`; + +export const ExitButton = styled.button` + position: absolute; + top: 20px; + left: 603px; + width: 61px; + height: 61px; + background-color: #ffffff; + border: none; + cursor: pointer; +`; diff --git a/src/components/SubNavigation/menuButton.js b/src/components/SubNavigation/menuButton.js new file mode 100644 index 0000000..adae341 --- /dev/null +++ b/src/components/SubNavigation/menuButton.js @@ -0,0 +1,18 @@ +import { IconBox } from "./styles"; + +const MenuButton = (props) => { + return ( +
+ + icon + + +
+ ); +}; + +export default MenuButton; diff --git a/src/components/SubNavigation/styles.js b/src/components/SubNavigation/styles.js new file mode 100644 index 0000000..44b8ec6 --- /dev/null +++ b/src/components/SubNavigation/styles.js @@ -0,0 +1,12 @@ +import styled from "styled-components"; + +export const IconBox = styled.div` + display: flex; + justify-content: center; + width: 100px; + height: 100px; + border-radius: 24px; + border: 1px solid #c9c9c9; + box-shadow: 4px 10px 30px 0px #00000008; + margin-bottom: 16px; +`; diff --git a/src/components/SubNavigation/subNavigation.js b/src/components/SubNavigation/subNavigation.js new file mode 100644 index 0000000..cb7980a --- /dev/null +++ b/src/components/SubNavigation/subNavigation.js @@ -0,0 +1,17 @@ +import MenuButton from "./menuButton"; + +const SubNavigation = () => { + return ( +
+
+ + + + + +
+
+ ); +}; + +export default SubNavigation; diff --git a/src/components/WithdrawalModal/styles.js b/src/components/WithdrawalModal/styles.js new file mode 100644 index 0000000..8f4eec0 --- /dev/null +++ b/src/components/WithdrawalModal/styles.js @@ -0,0 +1,69 @@ +import styled from "styled-components"; + +export const ContainerOut = styled.div` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +`; + +export const Containter = styled.div` + position: relative; + width: 516px; + height: 524px; + border-radius: 42px; + background-color: #ffffff; + display: flex; + justify-content: center; +`; + +export const Title = styled.label` + position: absolute; + top: 231px; + font-size: 32px; + font-weight: 700; +`; + +export const Explanation = styled.label` + position: absolute; + top: 297px; + font-size: 18px; + font-weight: 500; + color: #8f8f8f; +`; + +export const CannelButton = styled.button` + position: absolute; + top: 387px; + left: 151px; + width: 95px; + height: 35px; + border: none; + border-radius: 8px; + background-color: #dedede; + font-size: 20px; + font-weight: 400; + color: #646464; + cursor: pointer; +`; + +export const SecessionButton = styled.button` + position: absolute; + top: 387px; + right: 151px; + width: 95px; + height: 35px; + border: none; + border-radius: 8px; + background-color: #376fff; + font-size: 20px; + font-weight: 400; + color: #ffffff; + cursor: pointer; +`; diff --git a/src/components/WithdrawalModal/withdrawalModal.js b/src/components/WithdrawalModal/withdrawalModal.js new file mode 100644 index 0000000..8185cfb --- /dev/null +++ b/src/components/WithdrawalModal/withdrawalModal.js @@ -0,0 +1,31 @@ +import { + ContainerOut, + Containter, + Title, + Explanation, + CannelButton, + SecessionButton, +} from "./styles"; + +import { ReactComponent as Icon } from "../../assets/myPage/WithdrawalIcon.svg"; + +const WithdrawalModal = ({ IsWithdrawal }) => { + return ( + + + + 회원 탈퇴 + + 회원 탈퇴시 사용자 계정의 모든 정보가 삭제됩니다.
+ 정말로 탈퇴하시겠습니까? +
+ IsWithdrawal(false)}>취소 + IsWithdrawal(false)}> + 회원탈퇴 + +
+
+ ); +}; + +export default WithdrawalModal; diff --git a/src/index.js b/src/index.js index 902eb7c..388c707 100644 --- a/src/index.js +++ b/src/index.js @@ -3,12 +3,13 @@ import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; +import { RecoilRoot } from "recoil"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - + - , + , ); // If you want to start measuring performance in your app, pass a function diff --git a/src/lib/axios.js b/src/lib/axios.js new file mode 100644 index 0000000..a09aec1 --- /dev/null +++ b/src/lib/axios.js @@ -0,0 +1,41 @@ +import axios from "axios"; + +export const axiosWithAuth = axios.create({ + baseURL: + process.env.NODE_ENV === "development" + ? "http://localhost:8080" + : "https://e-um.site", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("access_token")}`, + }, + withCredentials: true, +}); + +axiosWithAuth.interceptors.response.use( + function (res) { + return res; + }, + async function (err) { + // const { config: originRequest } = err; + if (err.response.status === 401) { + // access token이 만료되어서 refresh token을 사용해서 재발급 요청할 때 + const reIssueResponse = await axiosWithAuth.post("/api/auth/reissue"); + if (reIssueResponse.status === 200) { + const { accessToken } = reIssueResponse.data; + localStorage.setItem("access_token", accessToken); + axiosWithAuth.defaults.headers.Authorization = `Bearer ${accessToken}`; + // await axios(originRequest).then((res) => {}); + window.location.replace("/"); + } else { + window.location.replace("/sign-in"); + } + } else if (err.response.status === 403) { + // refresh token이 만료 혹은 없을 때 + console.log("refresh token 만료 혹은 존재X. 재로그인 요망"); + return; + } + + return Promise.reject(err); + }, +); diff --git a/src/pages/Login/login.js b/src/pages/Login/login.js new file mode 100644 index 0000000..5e0beb7 --- /dev/null +++ b/src/pages/Login/login.js @@ -0,0 +1,39 @@ +import { useEffect } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; +import { axiosWithAuth } from "../../lib/axios"; + +const Login = (props) => { + const location = useLocation(); + const navigate = useNavigate(); + + useEffect(() => { + const queryParams = new URLSearchParams(location.search); + console.log("location", location); + // "/login/success" + const url = location.pathname; + const result2 = url.split("/"); // ["", "login", "success"] + const result = result2[result2.length - 1]; // "success" + console.log("queryParams", queryParams); + const token = queryParams.get("accesstoken"); + + // http://e-um.site/login/success?accesstoken=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0IiwiZW1haWwiOiJnZWVob29uNjIwMTdAZ21haWwuY29tIiwibmFtZSI6Iuy1nOyngO2biCAiLCJhdmF0YXIiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NLZDVzR216Nm5fa1Z5d0U2QW1WbS1NdHlpaTlwc2NhbmUtMmxZN2hRTWdEMjB4RlE9czk2LWMiLCJhdXRob3JpdGllcyI6IlJPTEVfVVNFUiIsImlhdCI6MTcxMjY0MjMxMywiZXhwIjoxNzEyNjQ0MTEzfQ.BqvQwgrdYwlQ4xCwer4wHHnQC1tciu2Rvxp9kC_iZEJNuK6mjYQUKCk_GDEgyPHP9b384RFfmI1hdyAzQ3TkpQ + console.log("result", result); + if (result === "success") { + if (token) { + console.log("토큰 저장"); + localStorage.setItem("access_token", token); + axiosWithAuth.defaults.headers.Authorization = `Bearer ${token}`; + navigate("/"); + } else { + // 토큰이 없거나 문제가 있다면 로그인 페이지나 오류 페이지로 리다이렉트 + console.log("url에 토큰이 포함되어 있지 않습니다"); + navigate("/"); + } + } else { + } + }, [location, navigate]); + + return
Loading...
; +}; + +export default Login; diff --git a/src/pages/Main/main.js b/src/pages/Main/main.js index ce97993..96c6f32 100644 --- a/src/pages/Main/main.js +++ b/src/pages/Main/main.js @@ -1,12 +1,36 @@ -import React from "react"; import Navigation from "../../components/Navigation/navigation"; import Introduce from "../../components/Introduce/introduce"; +import SubNavigation from "../../components/SubNavigation/subNavigation"; +import TeamCardGrid from "../../components/CardGrid/teamCardGrid"; +import MemberCardGrid from "../../components/CardGrid/memberCardGrid"; +import teamTestData from "../../api/teamTestData"; +import memberTestData from "../../api/memberTestData"; +import contestTestData from "../../api/contestTestData"; +import ContestCardGrid from "../../components/CardGrid/contestCardGrid"; const Main = (props) => { return (
- +
+ + +
+ +
+
+ +
+
+ +
+
); }; diff --git a/src/pages/Main/styles.js b/src/pages/Main/styles.js index e69de29..6ccfd2e 100644 --- a/src/pages/Main/styles.js +++ b/src/pages/Main/styles.js @@ -0,0 +1,11 @@ +import styled from "styled-components"; + +export const CardContainter = styled.div` + position: absolute; + top: 300px; + left: 100px; + width: 700px; + height: 650px; + border: solid; + overflow-y: auto; +`; diff --git a/src/pages/MemberSearch/memberSearch.js b/src/pages/MemberSearch/memberSearch.js new file mode 100644 index 0000000..8363ba8 --- /dev/null +++ b/src/pages/MemberSearch/memberSearch.js @@ -0,0 +1,60 @@ +import { useState } from "react"; +import TeamCardGrid from "../../components/CardGrid/teamCardGrid"; +import Introduce from "../../components/Introduce/introduce"; +import Navigation from "../../components/Navigation/navigation"; +import PaginationComponent from "../../components/PagenationComponent/pagenationComponent"; +import SideNavigation from "../../components/SideNavigation/sideNavigation"; +import memberTestData2 from "../../api/memberTestDats2"; +import memberTestData3 from "../../api/memberTestData3"; +import MemberCardGrid from "../../components/CardGrid/memberCardGrid"; +const MemberSearch = () => { + const [currentPage, setCurrentPage] = useState(1); + + const handlePageChange = (pageNumber) => { + setCurrentPage(pageNumber); + // 추가적인 페이지 변경 처리 로직 + }; + return ( +
+ +
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ ); +}; + +export default MemberSearch; diff --git a/src/api/q.txt b/src/pages/MemberSearch/styles.js similarity index 100% rename from src/api/q.txt rename to src/pages/MemberSearch/styles.js diff --git a/src/pages/MyPage/myPage.js b/src/pages/MyPage/myPage.js new file mode 100644 index 0000000..9370deb --- /dev/null +++ b/src/pages/MyPage/myPage.js @@ -0,0 +1,98 @@ +import React, { useState } from "react"; +import { Routes, Route } from "react-router-dom"; + +import Navigation from "../../components/Navigation/navigation"; +import MyPageSideBar from "../../components/MyPageSideBar/myPageSideBar"; +import MyInfo from "../../components/MyInfo/myInfo"; +import MyFavorites from "../../components/MyFavorites/myFavorites"; +import MySupport from "../../components/MySupport/mySupport"; +import MyTeam from "../../components/MyTeam/myTeam"; +import MyTeamCreate from "../../components/MyTeamCreate/myTeamCreate"; +import MyResume from "../../components/MyResume/myResume"; +import { ReactComponent as Vector } from "../../assets/myPage/myInfoVector1.svg"; + +import { Title, Container, PageName } from "./styles"; +import WithdrawalModal from "../../components/WithdrawalModal/withdrawalModal"; + +const MyPage = (props) => { + const [isCreateTeam, setIsCreateTeam] = useState(false); + const [isWithdrawal, setIsWithdrawal] = useState(false); + + return ( +
+ + + 마이페이지 + + + + + + 내정보 + +
+ } + /> + + 즐겨찾기 목록 + +
+ } + /> + + 지원 현황 + +
+ } + /> + + 팀관리 + {isCreateTeam ? ( + + ) : ( + + )} +
+ } + /> + + 이력서 관리 + +
+ } + /> + +
+ + {isWithdrawal ? ( + + ) : ( + <> + )} + + ); +}; + +export default MyPage; diff --git a/src/pages/MyPage/styles.js b/src/pages/MyPage/styles.js new file mode 100644 index 0000000..4f7f854 --- /dev/null +++ b/src/pages/MyPage/styles.js @@ -0,0 +1,30 @@ +import styled from "styled-components"; + +export const Title = styled.div` + position: absolute; + transform: translateX(-100%); + top: -90px; + left: -70px; + font-size: 32px; + font-weight: 700; +`; + +export const Container = styled.div` + position: absolute; + transform: translateX(-50%); + top: 201px; + left: 55%; + width: 898px; + height: 949px; + border: solid; + border-color: #c9c9c9; + border-radius: 12px; +`; + +export const PageName = styled.label` + position: absolute; + left: 50px; + top: 35px; + font-size: 30px; + font-weight: 900; +`; diff --git a/src/pages/TeamSearch/styles.js b/src/pages/TeamSearch/styles.js new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/TeamSearch/teamSearch.js b/src/pages/TeamSearch/teamSearch.js new file mode 100644 index 0000000..72caff8 --- /dev/null +++ b/src/pages/TeamSearch/teamSearch.js @@ -0,0 +1,60 @@ +import { useState } from "react"; +import teamTestData2 from "../../api/teamTestData2"; +import teamTestData3 from "../../api/teamTestData3"; +import TeamCardGrid from "../../components/CardGrid/teamCardGrid"; +import Introduce from "../../components/Introduce/introduce"; +import Navigation from "../../components/Navigation/navigation"; +import PaginationComponent from "../../components/PagenationComponent/pagenationComponent"; +import SideNavigation from "../../components/SideNavigation/sideNavigation"; + +const TeamSearch = () => { + const [currentPage, setCurrentPage] = useState(1); + + const handlePageChange = (pageNumber) => { + setCurrentPage(pageNumber); + // 추가적인 페이지 변경 처리 로직 + }; + return ( +
+ +
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ ); +}; + +export default TeamSearch; diff --git a/src/states/authState.js b/src/states/authState.js new file mode 100644 index 0000000..e226304 --- /dev/null +++ b/src/states/authState.js @@ -0,0 +1,16 @@ +import { atom } from "recoil"; + +export const userInfoState = atom({ + key: "userInfoState", + default: { + isLogin: false, + userId: 0, + email: "", + avatar: "", + mbti: "", + name: { + first: "", + fullName: "", + }, + }, +});